一篇就够!selenium教你爬取京东商品。

人生苦短,我选爬虫!

今天,心血来潮想用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()

进入商品展示面后,下面三个圈出的地方是关键,关系到让整个浏览器自动运行。

  1. 定位总共页数,用于遍历,css选择器路径为:'#J_bottomPage > span.p-skip > em:nth-child(1)'(注:省略这一步也可以!自己输入想得到的页数)
  2. 定位页数导航框,css选择器路径为:"#J_bottomPage > span.p-skip > input",通过send_keys输入页数,这个方法比较好用。我试过用while true循环不断点击下一页,但需要手动停止代码运行,强迫症的我无法忍受!
  3. 定位确定按钮,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选择器路径,注意一下小细节即可。
  • 如果您需要,可以找我要一下淘宝源码!