Selenium之学习杂记(七)

基于淘宝商品的实战

  • 准备工作
  • 流程简述
  • 代码解读

以淘宝商品为例子,阐述如何采集复杂网站的页面数据,展示较为新颖的实现方法。利用Selenium爬取淘宝商品数据,得到淘宝中与某一关键词对应的商品名称、价格和店铺名称等信息。

准备工作

本次爬取的过程中,我们会使用到一个叫作pyquery的库。这个库依赖于lxml,而lxml依赖于Visual C++ 14。在使用pip安装的过程中,如果在建立lxml.etree扩展的时候失败了,就会提示我们需要安装Visual C++ 14。
Selenium之学习杂记(七)_第1张图片
所以,直接使用pip安装很可能会报错,建议在加利福尼亚大学官网搜索UnofficialWindows Binaries for Python Extension Packages,并下载wheel文件,然后通过pip安装wheel文件,来避免这些麻烦。
Selenium之学习杂记(七)_第2张图片

流程简述

  1. 在淘宝的搜索栏中键入type c 关键词(未点击搜索按钮)
    Selenium之学习杂记(七)_第3张图片
  2. 点击搜索按钮,看返回的地址是什么?
    居然是让我先登录…
    Selenium之学习杂记(七)_第4张图片
  3. 登录之后,我们再来看看搜索type c会返回什么地址。
    Selenium之学习杂记(七)_第5张图片
    返回的地址是这个哈:
    在这里插入图片描述

而我们在其中输入usb关键词,返回的淘宝链接如下。
在这里插入图片描述

所以,我们完全有理由推测,淘宝在搜索时将我们搜索的内容放入链接中,通过返回的链接来确定显示的内容。
其实,这个链接的参数能够说明很多内容。比如,参数q代表我们要查询的内容,imgfile参数和图片搜索相关,initiative_id参数包含访问的时间,ie参数说明使用的编码等。
淘宝的页面内容很多,虽然大多数时候服务器返回内容的速度很快,但不排除部分时候返回内容特别慢,影响我们爬取的速度。然而,判断页面是否已经加载完的标准是我们需要的内容是否显示,而不是必须等到所有的内容都加载完。在淘宝网站中会显示的内容如图所示。Selenium之学习杂记(七)_第6张图片
结合本书前面讲述的显式等待和隐式等待,我们只需要判断这个内容所属的标签是否完全加载了就可以了。当然,这里指的是所有商品的内容。然后,我们可以使用下面的CSS选择器相关代码来判断所有商品是否加载完。
Selenium之学习杂记(七)_第7张图片
Selenium之学习杂记(七)_第8张图片
上面的图中红框没有想明白怎么来的,我用浏览器自带的工具,显示的是如下:
chrome浏览器:
#mainsrp-itemlist > div > div > div:nth-child(1) > div.item.J_MouserOnverReq.item-ad
firefox浏览器:
div.item:nth-child(1)

然后自己有翻阅了一下,css选择器的一些介绍:
Selenium之学习杂记(七)_第9张图片
Selenium之学习杂记(七)_第10张图片
Selenium之学习杂记(七)_第11张图片
所以自己有研究了一下在这里插入图片描述
可能是指如下红框中的,
Selenium之学习杂记(七)_第12张图片
暂时先当这样使用,后续有问题再说。
获取的商品很多,我们使用这个CSS选择器获取的是一个列表。
all = driver.find_elements_by_css_selector(".m-itemlist .items .item")
for i in all:

如果我们使用Selenium获取详细信息,就需要根据商品价格、商店、商家等信息重复写CSS选择器相关代码,然后写多个循环调用函数。为了避免重复写这些相同或相近的内容,我们不采用find_elements_by_css_selector(),而使用一个全新的pyquery库来对页面进行解析,效果和上面的代码是一样的,但更加方便一些。

通过以下代码导入库并将其简写为PQ。
在这里插入图片描述
通过以下代码解析页面源代码。
在这里插入图片描述
在页面中使用CSS选择器#mainsrp-itemlist .items .item来查找所有的内容。
在这里插入图片描述
分别选择下级中class属性为Pic img的标签(示例标签如下),获取这个标签的data-src属性,也就是图片路径。
在这里插入图片描述
类似地,我们将商品的一些信息拼凑成列表。
Selenium之学习杂记(七)_第13张图片
上面截图中的代码,应该是指如下:
Selenium之学习杂记(七)_第14张图片
内容显示的实现部分结束了。我们还需要考虑多页面采集问题。页码可以采用循环来实现,而要对指定页码的页面进行采集,我们首先需要进行页面的跳转。页面的跳转实现起来并不是很复杂,只需要找到相应的文本框,然后输入相应的数字再进行跳转有关的操作即可。Selenium之学习杂记(七)_第15张图片

代码解读

在理解了思路和实现流程之后,我们就可以尝试爬取淘宝网站的数据。最终,我们编写的功能代码如下。

# 导入库
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
from urllib.parse import quote
from pyquery import PyQuery
def get_products():
    # 提取商品数据
    # 获取页面源代码
    html = driver.page_source
    # 解析页面
    pq_file = PyQuery(html)
    all = pq_file('#mainsrp-itemlist .items .item')
    for i in all:
        product = [i.find('.pic .img').attr('data-src'),  # 商品图片地址
                   i.find('.price').text(),               # 商品价格
                   i.find('.deal-cnt').text(),            # 交易量
                   i.find('.title').text(),               # 商品名称(这个有点蒙,先放着)
                   i.find('.shop').text(),                # 店铺
                   i.find('.location').text(),            # 店铺所在位置
                   ]
        print(product)
# 打开浏览器
driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)
keyword = 'iPad'
def scratch_page(page):
    # 输出页面
    print('正在爬取第',page,'页')
    # 防止因为爬取某个页面失败而导致爬虫停止
    try:
        # 跳转到搜索关键词链接
        url = 'https://s.taobao.com/search?q=' + quote(keyword)
        driver.get(url)
        if page > 1:
            # 检测输入框
            input = wait.until(expected_conditions.presence_of_element_located((By.XPATH,'//*[@id="mainsrp-pager"]/div/div/div/div[2]/input')))
            # 检测提交
            submit = wait.until(expected_conditions.element_to_be_clickable((By.XPATH, '//*[@id="mainsrp-pager"]/div/div/div/div[2]/span[3]')))
            # 清空输入
            input.clear()
            # 输入数字
            input.send_keys(page)
            # 单击
            submit.click()
            # 等待页面加载完成
            wait.until(expected_conditions.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager li.item.active > span', str(page))))
            wait.until(expected_conditions.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item')))
            get_products()
    except:
        # 重试
        scratch_page(page)
def main():
    scratch_page(1)
if __name__ == '__main__':
    main()

等等,淘宝的反爬有些…,这篇文章先悬着吧,以后可以了再补上
我们使用quote()函数来将keyword编码成符合URL规范的内容,包含特殊字符(包括汉字)的字符串会被替换成%xx的格式,只有字母、数字、和“_”“.”“-”不会被转换。一般来说,这个函数是用来格式化URL的,这个函数包含一个可选参数,用来指定不格式化的内容。当编译一个源代码文件的时候,Python编译器会按照顺序执行里面的所有内容,但在执行代码之前,它会先定义一个特定的变量__name__。如果代码是作为主程序运行的(读者主动运行这个源文件,而不是当作库导入源代码),会把__main__赋予__name__;如果是当作库导入的,那么会把这个源文件的名字赋予__name__。定义一个main()函数,只在主动运行的时候,才运行main()函数。当运行程序的时候,会返回以下结果。

你可能感兴趣的:(Selenium,爬虫,python,selenium,残次文章)