人生苦短,我选爬虫!
今天,心血来潮想用selenium来爬取京东商品。
毕竟,这是个大创作(狗头)!
可能有的小伙伴会问,为什么不爬淘宝?
答案:淘宝的反爬太厉害了,一两次就被拦截了,还要过一两天才能爬取到内容。但是,经过反复的测试,京东,相对仁慈多了,拦截了又并不完全拦!
(如果跳出登录界面,正常扫码即可)
原理:
利用selenium打开京东,定位输入框和搜索框,点击搜索按钮
browser = webdriver.Chrome()
browser.get('https://www.jd.com/')
# 输入框
input = browser.find_element_by_css_selector('#key')
input.send_keys(keyword)
# 搜索框
btn = browser.find_element_by_css_selector('#search > div > div.form > button')
btn.click()
进入商品展示面后,下面三个圈出的地方是关键,关系到让整个浏览器自动运行。
- 定位总共页数,用于遍历,css选择器路径为:
'#J_bottomPage > span.p-skip > em:nth-child(1)'
(注:省略这一步也可以!自己输入想得到的页数) - 定位页数导航框,css选择器路径为:
"#J_bottomPage > span.p-skip > input"
,通过send_keys输入页数,这个方法比较好用。我试过用while true循环不断点击下一页,但需要手动停止代码运行,强迫症的我无法忍受! - 定位确定按钮,css选择器路径为:
'#J_bottomPage > span.p-skip > a'
到此,其原理差不多就这样!虽然梳理起来很简单,但操作起来真的很麻烦,容易犯一些低级错误!我测了几天,最后决定分享给大家,一起加油!
源码:
import re
import time
import csv, codecs
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from pyquery import PyQuery as pq
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
url = 'https://www.jd.com/'
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 60)
def get_url(keyword):
# browser=webdriver.PhantomJS()
browser.get(url)
# 输入框
input = browser.find_element_by_css_selector('#key')
input.send_keys(keyword)
# 搜索框
btn = browser.find_element_by_css_selector('#search > div > div.form > button')
btn.click()
# 获取页数并用正则提取
total_page_str = wait.until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, '#J_bottomPage > span.p-skip > em:nth-child(1)'))).text
total_page_num = int(re.search("(\d+)", total_page_str).group(1))
return total_page_num
def get_page(page_num):
print("正在获取第%d页数据" % page_num)
try:
# 定位页数导航框
page_num_box = wait.until(
EC.presence_of_element_located(
(By.CSS_SELECTOR, "#J_bottomPage > span.p-skip > input")))
# 确定按钮
ok_btn = wait.until(EC.element_to_be_clickable(
(By.CSS_SELECTOR, '#J_bottomPage > span.p-skip > a')))
page_num_box.clear() # 清空
page_num_box.send_keys(page_num)
ok_btn.click()
# 创建文件,写好表头
f = codecs.open('selenium京东商品.csv', 'w+', encoding='utf-8-sig')
filename = ['image', 'price', 'title', 'shop']
writer = csv.DictWriter(f, fieldnames=filename)
writer.writeheader()
# 调用外部函数
for item in get_goods():
print(item)
writer.writerow(item)
# time.sleep(0.5)
#若超时,将重新尝试获取
except TimeoutException:
return get_page(page_num)
def get_goods():
'''wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "#J_goodsList > ul > li.gl-item")))'''
#获取网页
html = browser.page_source
#初始化
doc = pq(html)
#转换列表形式
items = list(doc('#J_goodsList > ul > li.gl-item').items())
for item in items:
goods_list={}
goods_list['image'] = 'http:' + str(item.find('.p-img > a > img').attr('src'))
goods_list['price'] = item.find('.p-price').text()
goods_list['title'] = item.find('.p-name.p-name-type-2>a>em').text().strip()
goods_list['shop'] = item.find('.J_im_icon').text()
yield goods_list
if __name__ == '__main__':
try:
keyword = input("请输入想要搜素的商品")
total_num = get_url(keyword)
for page_num in range(2, total_num + 1):
get_page(page_num)
time.sleep(1)
except Exception as e:
print("出错了", e.args)
finally: # 确保 浏览器能正常关闭
browser.close()
效果图;
注意:
- 商品的链接只有部分显示,我真的晕了,检查了路径,没错就是不知道为什么,路过的大神如果知道,还望不吝赐教!(建议注释掉,因为到一定页数可能会报错停止,我猜是不是路径发生变化?)
- 小伙伴,也可以尝试爬一下淘宝,原理一样,改一下css选择器路径,注意一下小细节即可。
- 如果您需要,可以找我要一下淘宝源码!