文章采集调用(用python+selenuim自动框架来爬取京东商品信息(不要))
优采云 发布时间: 2022-02-21 23:28文章采集调用(用python+selenuim自动框架来爬取京东商品信息(不要))
今天我们使用python+ selenium 自动框架爬取京东商品信息(不要再问我为什么是京东了,因为京东不用登录也可以搜索商品),Selenium是用来模仿人类操作的,免费的手,生产力提升,哈哈,这里是对selenuim的一点介绍。
硒简介
Selenium 是一个 Web 应用程序测试工具,Selenium 测试直接在浏览器中运行,就像真正的用户一样。一般的爬虫方法是使用python脚本直接访问目标网站,并且只对目标数据执行采集,访问速度非常快,这样目标网站就可以轻松识别您这是机器人,它阻止了您。使用selenium写爬虫,python脚本控制浏览器进行访问,也就是说python脚本和目标网站之间多了一个浏览器操作,这个行为更像是人的行为,这么多难以爬取网站你也可以轻松抓取数据。
准备
首先安装selenuim,方法和其他第三方库的安装方法一样,使用pip命令
点安装硒
安装 selenuim 后,您必须安装驱动程序才能使其正常工作。因为我使用的是 Google Chrome,所以我下载了 Google Drive,当然还有 Firefox。下载对应浏览器版本的驱动(如果没有对应版本,也可以下载接近的版本)。以下是两款驱动的下载地址:
- 谷歌云端硬盘:(点击下载)
- 火狐驱动:(点击下载)
下载完成后,驱动就安装好了。Firefox驱动的安装方法与Chrome驱动相同。把下载好的驱动放到你的python安装路径下的Script目录下即可(放到Script文件夹下即可,无需配置环境变量)
至此,selenuim的相关安装就完成了,接下来开始我们今天的任务。
1.导入相关依赖
import time
import json
from pyquery import PyQuery as pq
#pyquery是个解析库
from selenium import webdriver
#导入驱动webdriver
from selenium.webdriver.common.by import By
#By是selenium中内置的一个class,在这个class中有各种方法来定位元素
from selenium.webdriver.support.ui import WebDriverWait
#设置浏览器驱动休眠等待,避免频繁操作封ip
from selenium.webdriver.support import expected_conditions as EC
#判断一个元素是否存在,是否加载完毕等一系列的场景判断方法
二、使用selenium EC操作浏览器
首先,用Chrome浏览器打开产品首页。我们很容易发现该网页是一个动态加载的网页。首次打开网页时,仅显示 30 种产品的信息。只有当网页被向下拖动时,它才会加载其余部分。30 项信息。这里我们可以使用selenium模拟浏览器拉下网页,判断网页元素是否通过EC加载,从而获取所有产品网站的信息。
def search():
browser.get('https://www.jd.com/')
try:
input = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#key"))
) # 等待搜索框加载出来
submit = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#search > div > div.form > button"))
) # 等待搜索按钮可以被点击
input[0].send_keys(keyword) # 向搜索框内输入关键词
submit.click() # 点击搜索
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
except TimeoutError:
search()
三、使用selenium EC实现翻页操作
与第一页类似,它也使用EC来判断页面元素是否加载,并添加延迟以防止数据被抓到。
def next_page(page_number):
try:
button = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage > span.p-num > a.pn-next > em'))
) # 等待翻页按钮可以点击
button.click() # 点击翻页按钮
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);")
time.sleep(2)
wait.until(# 等到60个商品都加载出来
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(60)"))
)
html = browser.page_source
find_save(html) # 调用函数筛选数据
except TimeoutError:
return next_page(page_number)
四、提取数据并保存
这里使用pyquery库解析网页源代码,使用CSS_SELECTOR选择元素。一定要找到参考元素。例如,将鼠标放在搜索框中,右键查看,然后跳转到搜索框中对应的代码处。右键点击它,点击Copy > Copy selector,我们得到我们需要的#key,然后通过.text()获取内容,最后将python对象转换成json数据写入json文件。
def find_save(html):
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) # 写入全局变量
# 把全局变量转化为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)
print("json文件写入成功")
五、编写和调用main函数
使用for循环控制爬取的页面数并添加延迟
def main():
print("第", 1, "页:")
search()
for i in range(2, 6): # 爬取2-5页
time.sleep(2) # 设置延迟
print("第", i, "页:")
next_page(i)
if __name__ == "__main__":
main()
补充:
为了提高爬虫的效率,可以将浏览器设置为无图片模式,即不加载图片,这样可以提高采集的速度
options = webdriver.ChromeOptions()
options.add_experimental_option('prefs'{'profile.managed_default_content_settings.images': 2})
browser = webdriver.Chrome(options=options)
看看结果:
附上完整代码:
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
# 不加载图片
options = webdriver.ChromeOptions()
options.add_experimental_option('prefs', {'profile.managed_default_content_settings.images': 2})
browser = webdriver.Chrome(options=options)
wait = WebDriverWait(browser, 20) # 设置等待时间
data_list = [] # 设置全局变量用来存储数据
keyword = "平凡的世界" # 商品名称
def search():
browser.get('https://www.jd.com/')
try:
input = wait.until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#key"))
) # 等待搜索框加载出来
submit = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#search > div > div.form > button"))
) # 等待搜索按钮可以被点击
input[0].send_keys(keyword) # 向搜索框内输入关键词
submit.click() # 点击搜索
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) # 调用函数筛选数据
except TimeoutError:
search()
def next_page(page_number):
try:
button = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage > span.p-num > a.pn-next > em'))
) # 等待翻页按钮可以点击
button.click() # 点击翻页按钮
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);")
time.sleep(2)
wait.until(# 等到60个商品都加载出来
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#J_goodsList > ul > li:nth-child(60)"))
)
html = browser.page_source
find_save(html) # 调用函数筛选数据
except TimeoutError:
return next_page(page_number)
def find_save(html):
doc = pq(html)
items = doc('#J_goodsList > ul > li').items()
# print(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) # 写入全局变量
# 把全局变量转化为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)
print("json文件写入成功")
def main():
print("第", 1, "页:")
search()
for i in range(2, 6): # 爬取2-5页
time.sleep(2) # 设置延迟
print("第", i, "页:")
next_page(i)
if __name__ == "__main__":
main()
如有错误,请私信指正,谢谢支持!