使用selenium爬取京东商品搜索结果(名字、价格、评价数)
使用selenium爬取京东商品搜索结果(名字、价格、评价数)
Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。
一、环境
- Ubuntu18.04
- Python3
- PyCharm
- MySQL 5.7.29
- selenium、pyquery、json、time
- Chrome
二、项目解析
使用selenium需要等待所要元素加载完成,首先需要京东的搜索框加载完成。
# 等待搜索框加载完成
input_keys = wait.until(EC.presence_of_element_located((By.ID, 'key')))
打开京东搜索手机,观察到结果页面是分两次加载的,用循环体来多次将页面滑到底部,使其加载全部。
# 动态加载太多,多滚动几次
for i in range(2):
# 等待底部翻页栏加载完成
wait.until(EC.presence_of_element_located((By.ID, 'J_bottomPage')))
# 滚动条滚动到底部
browser.execute_script('window.scrollTo(0,10000)')
# 等待加载元素消失
wait.until_not(EC.presence_of_element_located((By.ID, 'J_scroll_loading')))
time.sleep(3)
当前页面的html
html = browser.page_source
查找需要元素
使用pyquery库解析
# 解析爬到页面的信息
def parse_jd_html(html):
# 商品在ul.gl-warp的li.item中
# 使用pyquery解析库解析
doc = PyQuery(html)
items = doc('ul.gl-warp li.gl-item').items()
for item in items:
yield {
'name': item.find('.p-name a em').text().strip(),
'price': item.find('.p-price strong i').text(),
'commit': item.find('.p-commit strong a').text()
}
将数据保存到数据库(填写正确数据库用户名、密码和数据库)
# 写入数据库
def write_to_mysql(item):
try:
# connect MySQL
conn = pymysql.connect(
host='localhost',
user='root',
passwd='123456',
db='jd_selenium',
port=3306,
charset='utf8')
# 创建cursor对象取执行SQL语句
cursor = conn.cursor()
table = 'jd_html2'
keys = ','.join(item.keys())
values = ','.join(['%s']*len(item))
sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table, keys=keys, values=values)
cursor.execute(sql, tuple(item.values()))
conn.commit()
except Exception as e:
print('数据库出错')
print(e)
finally:
cursor.close()
conn.close()
用sql = ‘INSERT INTO {table}({keys}) VALUES ({values})’.format(table=table, keys=keys, values=values)必须确保表元素与item的关键字一样。
数据库保存记录:
完整代码
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from pyquery import PyQuery
import time
import json
import pymysql
# 解析爬到页面的信息
def parse_jd_html(html):
# 商品在ul.gl-warp的li.item中
# 使用pyquery解析库解析
doc = PyQuery(html)
items = doc('ul.gl-warp li.gl-item').items()
for item in items:
yield {
'name': item.find('.p-name a em').text().strip(),
'price': item.find('.p-price strong i').text(),
'commit': item.find('.p-commit strong a').text()
}
# 数据写入文本
def write_to_file(content, filepath):
with open(filepath, 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
# 写入数据库
def write_to_mysql(item):
try:
# connect MySQL
conn = pymysql.connect(
host='localhost',
user='root',
passwd='123456',
db='jd_selenium',
port=3306,
charset='utf8')
# 创建cursor对象取执行SQL语句
cursor = conn.cursor()
table = 'jd_html2'
keys = ','.join(item.keys())
values = ','.join(['%s']*len(item))
sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table, keys=keys, values=values)
cursor.execute(sql, tuple(item.values()))
conn.commit()
except Exception as e:
print('数据库出错')
print(e)
finally:
cursor.close()
conn.close()
# 根据search_key关键字爬取数据
def search_key(keys):
# 开启浏览器
browser = webdriver.Chrome()
# 设置等待时间
wait = WebDriverWait(browser, 10)
try:
# 获取京东首页
browser.get('https://jd.com/')
# 等待搜索框加载完成
input_keys = wait.until(EC.presence_of_element_located((By.ID, 'key')))
input_keys.clear()
input_keys.send_keys(keys)
input_keys.send_keys(Keys.ENTER)
# 爬取数据
def crawling_data():
# 动态加载太多,多滚动几次
for i in range(2):
# 等待底部翻页栏加载完成
wait.until(EC.presence_of_element_located((By.ID, 'J_bottomPage')))
# 滚动条滚动到底部
browser.execute_script('window.scrollTo(0,10000)')
# 等待加载元素消失
wait.until_not(EC.presence_of_element_located((By.ID, 'J_scroll_loading')))
time.sleep(3)
# 获取总页数
page_count = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#J_bottomPage .p-skip b')))
# 获取爬到当前页数
page_input = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '#J_bottomPage .p-skip .input-txt')))
# 确定按钮
page_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_bottomPage .p-skip a')))
html = browser.page_source
# 解析并且写入
for item in parse_jd_html(html):
# 写入txt中
# write_to_file(item, keys + '.txt')
# 写入mysql中
write_to_mysql(item)
# 总页数
count = int(page_count.text)
# 当前页数
current = int(page_input.get_attribute('value'))
print('完成:', current, '/', count)
# 下一页
if current < count:
page_input.clear()
page_input.send_keys(str(current+1))
page_button.click()
crawling_data()
crawling_data()
# 出错处理
except Exception as e:
print('exception', e)
finally:
browser.quit() # 关闭浏览器
# 显示退出
print("browser quit")
if __name__ == '__main__':
search_key('手机')
使用这个有时无法爬取全部页面,会在一半停下来,也不报错,我也不知道为什么。
第一次写,有什么写的不好请联系。
QQ邮箱:172688512@qq.com
参考文献:https://blog.csdn.net/gongjianbo1992/article/details/99769849?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task