优化篇:selenium采集京东商品数据(去除冗余代码)

上一篇讲解了如何使用python+selenium爬取京东商品信息,并进行自动翻页与批量采集,但是总体来说代码还是略显臃肿,不符合python的宗旨。所以这期就对其进行优化。

回顾

在上一期中(点击查看),第一页与下一页的采集使用了两个函数,即第一页只负责搜索商品和采集第一页,调用下一页的函数是开始爬取写愿意内容。这两个函数的实现方法大体上是相同的,但是这样的话,当调用主函数的时候,就要先调用一次爬取第一页的函数,再使用for循环执行下一页的爬取。那么有没有什么办法可以一次性对商品信息进行抓取呢?

在这里插入图片描述

改造思路

我们先来模拟一遍浏览器操作过程,当我们在商品搜索框中输入商品名称并回车之后,页面中会先加载出来30个商品,只有当我们往下拖动页面时,后30个商品才会加载出来。之后,我们来判断下一页的按钮是否加载出来,要是按钮加载完成就点击。

这里我们只需把数据的解析与保存放在翻页之前(当前页面采集完成后,点击下一页,浏览器跳转到下一页,又开始加载前30个商品,也就是说这是一个循环的过程),最后利用for循环就可以实现一次性抓取了。

我的表述可能不是很清晰,这里附一张流程图:
流程图

代码实现:

def change_page():
    try:
        wait.until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(30)"))
        )  # 等到30个商品都加载出来
        time.sleep(2)
        # 下拉
        browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        wait.until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(60)"))
        )  # 等待最后一个商品信息加载完毕
        html = browser.page_source
        find_save(html)  # 调用函数筛选数据
        button = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage > span.p-num > a.pn-next > em'))
        )  # 等待翻页按钮可以点击
        button.click()  # 点击翻页按钮
    except TimeoutException:
        print("Error")
        search()

总结

此次代码的重写,实现了在for循环下调用采集函数就可以自动实现翻页与爬取,一次性采集的功能,不需要再像上次那样第一页与下一页的采集分开调用,整体思路还算清晰。当然了,大家如果有更好的思路和方法可以在评论区提出来。

完整代码如下:

import time
import json
from pyquery import PyQuery as pq
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from urllib.parse import quote

# 不加载图片
options = webdriver.ChromeOptions()
options.add_experimental_option('prefs', {'profile.managed_default_content_settings.images': 2})
browser = webdriver.Chrome(options=options)
base_url = 'https://search.jd.com/Search?keyword='
wait = WebDriverWait(browser, 20)  # 设置等待时间
data_list = []  # 设置全局变量用来存储数据
keyword = "平凡的世界"  # 商品名称
max_page = 5


def change_page():
    try:
        wait.until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(30)"))
        )  # 等到30个商品都加载出来
        time.sleep(2)
        # 下拉
        browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        wait.until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(60)"))
        )  # 等待最后一个商品信息加载完毕
        html = browser.page_source
        find_save(html)  # 调用函数筛选数据
        button = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage > span.p-num > a.pn-next > em'))
        )  # 等待翻页按钮可以点击
        button.click()  # 点击翻页按钮
    except TimeoutException:
        print("Error")
        search()


def find_save(html):
    """
    筛选数据以json形式保存
    """
    doc = pq(html)
    items = doc('#J_goodsList > ul > li').items()
    for item in items:
        product = {
            'name': item('.p-name a').text(),
            'price': item('.p-price i').text(),
            'commit': item('.p-commit a').text()
        }
        data_list.append(product)  # 写入全局变量
    print('商品个数:', len(data_list))
    # 把全局变量转化为json数据
    content = json.dumps(data_list, ensure_ascii=False, indent=2)
    with open("E:\python\project\selenium\info.json", "w", encoding="utf-8") as f:
        f.write(content)


def main():
    url = base_url + quote(keyword)
    browser.get(url)
    for i in range(1, max_page + 1):
        print("第", i, "页:")
        change_page()


if __name__ == "__main__":
    main()

猜你喜欢

转载自blog.csdn.net/qq_47183158/article/details/107653105