Selenium 实战 之 淘宝商品信息的爬取

虽然淘宝的页面数据是通过 Ajax 获取的,也就是可以通过开发者模式直接找到它请求数据的接口,并且发现返回的数据是 json 的格式;但是这里需要注意的是这些 Ajax 接口的参数比较复杂,包含了加密密钥,因此如果想自己构造 Ajax 参数是比较困难的。
既然那么困难搞到数据,那么有没有办法使抓取的成本第一点呢?当然有,一种是使用 特定的数据接口 ;另一种就是使用 selenium了,selenium 有个特点就是 可见即所得。
那么接下来我们开始观察页面效果图:
Selenium 实战 之 淘宝商品信息的爬取_第1张图片
image.png
经过效果图的观察,我们不难发现规律:我们要加载商品列表的节点;页面跳转时通过页面输入框再点击“确定”按钮进行跳转,并且只需判断当前高亮的页码数是当前的页码数即可。

一、首先导入相应的模块:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from urllib.parse import quote
from pyquery import PyQuery as pq

二、加载及跳转逻辑的代码函数如下:

browser = webdriver.Chrome()  # 浏览器对象
wait = WebDriverWait(browser, 10)  # 加载等待最大时间
KEYWORD = "华为荣耀10"

def index_page(page):
    print("正在抓取第 ", page, "页...")
    try:
        url = r'https://s.taobao.com/search?q='+ quote(KEYWORD)
        browser.get(url)
        if page > 1:  # 当页码大于 1 的时候则进行跳转
            # 节点加载出来,传入定位元组,如(By.ID, 'p')
            input_word = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager div.form > input')))  # 输入页码框
            # 节点可点击
            submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager div.form > span.btn.J_Submit')))  # 页码跳转"确定"按钮
            input_word.clear()  # 清空编辑框
            input_word.send_keys(page)  # 将页码填充到输入框
            submit.click()  # 点击"确定"按钮

        # 某个节点文本包含某文字
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager li.item.active > span'), str(page)))  # 翻页按钮列表选项数字
        # 节点加载出来,传入定位元组,如(By.ID, 'p')
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item')))  # 渲染商品所在列表选项
        # 解析数据
        get_products()

    except TimeoutException as e:
        index_page(page)



到这里,你可以直接运行该函数看是否能成功加载源码,这里我不做演示;那么接下来在观察我们所要加载信息(商品图片、名称、价格、购买人数、店铺名称、店铺地址)的页面节点:

Selenium 实战 之 淘宝商品信息的爬取_第2张图片
image.png

三、观察商品节点之后解析代码如下 (由于截图大小有限,其它标签自行观察)

# 解析函数-提取商品信息
def get_products():
    html = browser.page_source
    doc = pq(html)
    items = doc('#mainsrp-itemlist .items .item').items()
    for item in items:
        product = {
            'image':item.find('.pic .img').attr('data-src'),
            'price':item.find('.price').text(),
            'deal':item.find('.deal-cnt').text(),
            'title':item.find('.title').text(),
            'shop':item.find('.shop').text(),
            'location':item.find('.location').text()
        }
        print(product)

四、编写主函数并调用:

def main():
    #page = 1  # 据观察总共有 100 页
    for page in range(1, 11):
        index_page(page)


if __name__ == '__main__':
    main()

运行部分效果图如下:


Selenium 实战 之 淘宝商品信息的爬取_第3张图片
image.png
如果我们不想爬取的时候有浏览器弹出,那么有两种方式可以做到:1- 使用 Chrome Headless 模式 (这个模式前面一章有介绍并使用过);2- 对接 PhantomJS

五、首先看第一种 -> 直接将 webdriver 的声明修改为:

#browser = webdriver.Chrome()  # 浏览器对象
chrome_options = webdriver.ChromeOptions()  # 获取 ChromeOptions 对象
chrome_options.add_argument('--headless')  # 添加 headless 参数
browser = webdriver.Chrome(chrome_options=chrome_options)  # 初始化 Chrome 对象

六、第二种 -> 同理,直接将 webdriver 的声明修改为:

path = r"E:\\KaiFaSoftware\\MyPython\\MyPhantomjs\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe"
# browser = webdriver.PhantomJS(executable_path=path)

# 我们还可以通过命令行配置,设置缓存和禁用图片加载功能,进一步提高爬取效率
SERVICE_ARGS = ['--load-images=false','--disk-cache=true']
browser = webdriver.PhantomJS(executable_path=path,service_args=SERVICE_ARGS)

这里值得注意的是:如果配置了环境变量则不需要 path 指定路径了,还有提供一个 PhantomJS 的下载地址 -> http://phantomjs.org/download.html

最后的话非常感谢崔老师的思路,嘿嘿,相信通过本次实战同学们应该学到了不少了;本次实战到此为止,感恩一切。。。 *^_^*

你可能感兴趣的:(Selenium 实战 之 淘宝商品信息的爬取)