优化篇:selenium采集京东商品数据
程序员文章站
2022-06-21 22:50:32
上一篇讲解了如何使用python+selenium爬取京东商品信息,并进行自动翻页与批量采集,但是总体来说代码还是略显臃肿,不符合python的宗旨。所以,这期就对进行一下优化。回顾在上一期中(点击查看),第一页与下一页的采集使用了两个函数,即第一页只负责搜索商品和采集第一页,调用下一页的函数是开始爬取写愿意内容。这两个函数的实现方法大体上是相同的,但是这样的话,当调用主函数的时候,就要先调用一次爬取第一页的函数,再使用for循环执行下一页的爬取。那么有没有什么办法可以一次性对商品信息进行抓取呢?改...
上一篇讲解了如何使用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()
本文地址:https://blog.csdn.net/qq_47183158/article/details/107653105