Python Selenium 爬虫淘宝案例

news2024/10/3 22:25:31

爬虫专栏:http://t.csdnimg.cn/WfCSx

前言

在前一章中,我们已经成功尝试分析 Ajax 来抓取相关数据,但是并不是所有页面都可以通过分析 Ajax 来完成抓取。比如,淘宝,它的整个页面数据确实也是通过 Ajax 获取的,但是这些 Ajax 接口参数比较复杂,可能会包含加密密钥等,所以如果想自己构造 Ajax 参数,还是比较困难的。对于这种页面,最方便快捷的抓取方法就是通过 Selenium。本节中,我们就用 Selenium 来模拟浏览器操作,抓取淘宝的商品信息,并将结果保存到 MongoDB。

1. 本节目标

本节中,我们要利用 Selenium 抓取淘宝商品并用 pyquery 解析得到商品的图片、名称、价格、购买人数、店铺名称和店铺所在地信息,并将其保存到 MongoDB。

2. 准备工作

本节中,我们首先以 Chrome 为例来讲解 Selenium 的用法。在开始之前,请确保已经正确安装好 Chrome 浏览器并配置好了 ChromeDriver;另外,还需要正确安装 Python 的 Selenium 库;最后,还对接了 PhantomJS 和 Firefox,请确保安装好 PhantomJS 和 Firefox 并配置好了 GeckoDriver。如果环境没有配置好,请参考:Python爬虫请求库安装#1-CSDN博客

3. 接口分析

首先,我们来看下淘宝的接口,看看它比一般 Ajax 多了怎样的内容。

打开淘宝页面,搜索商品,比如 iPad,此时打开开发者工具,截获 Ajax 请求,我们可以发现获取商品列表的接口。

它的链接包含了几个 GET 参数,如果要想构造 Ajax 链接,直接请求再好不过了,它的返回内容是 JSON 格式。

但是这个 Ajax 接口包含几个参数,其中_ksTS、rn 参数不能直接发现其规律,如果要去探寻它的生成规律,也不是做不到,但这样相对会比较烦琐,所以如果直接用 Selenium 来模拟浏览器的话,就不需要再关注这些接口参数了,只要在浏览器里面可以看到的,都可以爬取。这也是我们选用 Selenium 爬取淘宝的原因。

4. 页面分析

本节的目标是爬取商品信息。下图是一个商品条目,其中包含商品的基本信息,包括商品图片、名称、价格、购买人数、店铺名称和店铺所在地,我们要做的就是将这些信息都抓取下来。

抓取入口就是淘宝的搜索页面,这个链接可以通过直接构造参数访问。例如,如果搜索 iPad,就可以直接访问 https://s.taobao.com/search?q=iPad,呈现的就是第一页的搜索结果:

在页面下方,有一个分页导航,其中既包括前 5 页的链接,也包括下一页的链接,同时还有一个输入任意页码跳转的链接。

这里商品的搜索结果一般最大都为 100 页,要获取每一页的内容,只需要将页码从 1 到 100 顺序遍历即可,页码数是确定的。所以,直接在页面跳转文本框中输入要跳转的页码,然后点击 “确定” 按钮即可跳转到页码对应的页面。

这里不直接点击 “下一页” 的原因是:一旦爬取过程中出现异常退出,比如到 50 页退出了,此时点击 “下一页” 时,就无法快速切换到对应的后续页面了。此外,在爬取过程中,也需要记录当前的页码数,而且一旦点击 “下一页” 之后页面加载失败,还需要做异常检测,检测当前页面是加载到了第几页。整个流程相对比较复杂,所以这里我们直接用跳转的方式来爬取页面。

当我们成功加载出某一页商品列表时,利用 Selenium 即可获取页面源代码,然后再用相应的解析库解析即可。这里我们选用 pyquery 进行解析。下面我们用代码来实现整个抓取过程。

5. 获取商品列表

首先,需要构造一个抓取的 URL:https://s.taobao.com/search?q=iPad。这个 URL 非常简洁,参数 q 就是要搜索的关键字。只要改变这个参数,即可获取不同商品的列表。这里我们将商品的关键字定义成一个变量,然后构造出这样的一个 URL。

然后,就需要用 Selenium 进行抓取了。我们实现如下抓取列表页的方法:

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from urllib.parse import quote
​
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)
KEYWORD = 'iPad'
​
def index_page(page):
    """
    抓取索引页
    :param page: 页码
    """
    print(' 正在爬取第 ', page, ' 页 ')
    try:
        url = 'https://s.taobao.com/search?q=' + quote(KEYWORD)
        browser.get(url)
        if page > 1:
            input = 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.clear()
            input.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)))
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item')))
        get_products()
    except TimeoutException:
        index_page(page)

这里首先构造了一个 WebDriver 对象,使用的浏览器是 Chrome,然后指定一个关键词,如 iPad,接着定义了 index_page() 方法,用于抓取商品列表页。

在该方法里,我们首先访问了搜索商品的链接,然后判断了当前的页码,如果大于 1,就进行跳页操作,否则等待页面加载完成。

等待加载时,我们使用了 WebDriverWait 对象,它可以指定等待条件,同时指定一个最长等待时间,这里指定为最长 10 秒。如果在这个时间内成功匹配了等待条件,也就是说页面元素成功加载出来了,就立即返回相应结果并继续向下执行,否则到了最大等待时间还没有加载出来时,就直接抛出超时异常。

比如,我们最终要等待商品信息加载出来,就指定了 presence_of_element_located 这个条件,然后传入了.m-itemlist .items .item 这个选择器,而这个选择器对应的页面内容就是每个商品的信息块,可以到网页里面查看一下。如果加载成功,就会执行后续的 get_products() 方法,提取商品信息。

关于翻页操作,这里首先获取页码输入框,赋值为 input,然后获取 “确定” 按钮,赋值为 submit,分别是下图中的两个元素。

首先,我们清空了输入框,此时调用 clear() 方法即可。随后,调用 send_keys() 方法将页码填充到输入框中,然后点击 “确定” 按钮即可。

那么,怎样知道有没有跳转到对应的页码呢?我们可以注意到,成功跳转某一页后,页码都会高亮显示。

我们只需要判断当前高亮的页码数是当前的页码数即可,所以这里使用了另一个等待条件 text_to_be_present_in_element,它会等待指定的文本出现在某一个节点里面时即返回成功。这里我们将高亮的页码节点对应的 CSS 选择器和当前要跳转的页码通过参数传递给这个等待条件,这样它就会检测当前高亮的页码节点是不是我们传过来的页码数,如果是,就证明页面成功跳转到了这一页,页面跳转成功。

这样刚才实现的 index_page() 方法就可以传入对应的页码,待加载出对应页码的商品列表后,再去调用 get_products() 方法进行页面解析。

6. 解析商品列表

接下来,我们就可以实现 get_products 方法来解析商品列表了。这里我们直接获取页面源代码,然后用 pyquery 进行解析,实现如下:

from pyquery import PyQuery as pq
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)
        save_to_mongo(product)

首先,调用 page_source 属性获取页码的源代码,然后构造了 PyQuery 解析对象,接着提取了商品列表,此时使用的 CSS 选择器是 #mainsrp-itemlist .items .item,它会匹配整个页面的每个商品。它的匹配结果是多个,所以这里我们又对它进行了一次遍历,用 for 循环将每个结果分别进行解析,每次循环把它赋值为 item 变量,每个 item 变量都是一个 PyQuery 对象,然后再调用它的 find() 方法,传入 CSS 选择器,就可以获取单个商品的特定内容了。

比如,查看一下商品信息的源码。

可以发现,它是一个 img 节点,包含 id、class、data-src、alt 和 src 等属性。这里之所以可以看到这张图片,是因为它的 src 属性被赋值为图片的 URL。把它的 src 属性提取出来,就可以获取商品的图片了。不过我们还注意 data-src 属性,它的内容也是图片的 URL,观察后发现此 URL 是图片的完整大图,而 src 是压缩后的小图,所以这里抓取 data-src 属性来作为商品的图片。

因此,我们需要先利用 find() 方法找到图片的这个节点,然后再调用 attr() 方法获取商品的 data-src 属性,这样就成功提取了商品图片链接。然后用同样的方法提取商品的价格、成交量、名称、店铺和店铺所在地等信息,接着将所有提取结果赋值为一个字典 product,随后调用 save_to_mongo() 将其保存到 MongoDB 即可。

7. 保存到 MongoDB

接下来,我们再将商品信息保存到 MongoDB,实现如下:

MONGO_URL = 'localhost'
MONGO_DB = 'taobao'
MONGO_COLLECTION = 'products'
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]
def save_to_mongo(result):
    """
    保存至 MongoDB
    :param result: 结果
    """
    try:
        if db[MONGO_COLLECTION].insert(result):
            print(' 存储到 MongoDB 成功 ')
    except Exception:
        print(' 存储到 MongoDB 失败 ')

这里首先创建了一个 MongoDB 的连接对象,然后指定了数据库,随后指定了 Collection 的名称,接着直接调用 insert 方法将数据插入到 MongoDB。此处的 result 变量就是在 get_products 方法里传来的 product,包含单个商品的信息。

8. 遍历每页

刚才我们所定义的 index_page() 方法需要接收参数 page,page 代表页码。这里我们实现页码遍历即可,代码如下:

MAX_PAGE = 100
def main():
    """遍历每一页"""
    for i in range(1, MAX_PAGE + 1):
        index_page(i)

其实现非常简单,只需要调用一个 for 循环即可。这里定义最大的页码数为 100,range() 方法的返回结果就是 1 到 100 的列表,顺序遍历,调用 index_page() 方法即可。

这样我们的淘宝商品爬虫就完成了,最后调用 main() 方法即可运行。

9. 运行

运行代码,可以发现首先会弹出一个 Chrome 浏览器,然后会访问淘宝页面,接着控制台便会输出相应的提取结果。

可以发现,这些商品信息的结果都是字典形式,它们被存储到 MongoDB 里面。

再看一下 MongoDB 中的结果。

可以看到,所有的信息都保存到 MongoDB 里了,这说明爬取成功。

10. Chrome Headless 模式

从 Chrome 59 版本开始,已经开始支持 Headless 模式,也就是无界面模式,这样爬取的时候就不会弹出浏览器了。如果要使用此模式,请把 Chrome 升级到 59 版本及以上。启用 Headless 模式的方式如下:

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
browser = webdriver.Chrome(chrome_options=chrome_options)

首先,创建 ChromeOptions 对象,接着添加 headless 参数,然后在初始化 Chrome 对象的时候通过 chrome_options 传递这个 ChromeOptions 对象,这样我们就可以成功启用 Chrome 的 Headless 模式了。

11. 对接 Firefox

要对接 Firefox 浏览器非常简单,只需要更改一处即可:

browser = webdriver.Firefox()

这里更改了 browser 对象的创建方式,这样爬取的时候就会使用 Firefox 浏览器了。

12. 对接 PhantomJS

如果不想使用 Chrome 的 Headless 模式,还可以使用 PhantomJS(它是一个无界面浏览器)来抓取。抓取时,同样不会弹出窗口,还是只需要将 WebDriver 的声明修改一下即可:

browser = webdriver.PhantomJS()

另外,它还支持命令行配置。比如,可以设置缓存和禁用图片加载的功能,进一步提高爬取效率:

SERVICE_ARGS = ['--load-images=false', '--disk-cache=true']
browser = webdriver.PhantomJS(service_args=SERVICE_ARGS)

这样我们就可以禁用 PhantomJS 的图片加载同时开启缓存,可以发现页面爬取速度进一步提升。

结尾

本节中,我们用 Selenium 演示了淘宝页面的抓取。利用它,我们不用去分析 Ajax 请求,真正做到可见即可爬。

下一章,我们将学习图片验证码识别、极验滑动验证码识别、点触验证码识别。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1457503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Radware Alteon负载均衡-基于域名的七层负载均衡

Radware Alteon作为一款高性能的负载均衡器,其基于域名的七层负载均衡功能为众多企业提供了灵活、高效的解决方案。 该案例实现如下需求:客户端访问服务器,当访问域名为www.iisstart.com时,默认访问Server1,当配置七层…

数据结构-最短路径(Dijkstra算法与Floyd算法)

介绍 对于网图来说,最短路径是指两顶点之间经过的边上权值之和最少的路径,其路径上第一个点记为源点,最后一个为终点。 计算最短路径有两个经典算法,即迪杰斯特拉(Dijkstra)算法与弗洛伊德(Fl…

蓝桥杯嵌入式STM32G431RBT6知识点(主观题部分)

目录 1 前置准备 1.1 Keil 1.1.1 编译器版本及微库 1.1.2 添加官方提供的LCD及I2C文件 1.2 CubeMX 1.2.1 时钟树 1.2.2 其他 1.2.3 明确CubeMX路径,放置芯片包 2 GPIO 2.1 实验1:LED1-LED8循环亮灭 ​编辑 2.2 实验2&#xff1a…

C#使用MiniExcel导入导出数据到Excel/CSV文件

MiniExcel简介 简单、高效避免OOM的.NET处理Excel查、写、填充数据工具。 目前主流框架大多需要将数据全载入到内存方便操作,但这会导致内存消耗问题,MiniExcel 尝试以 Stream 角度写底层算法逻辑,能让原本1000多MB占用降低到几MB&#xff…

提取游戏音频文件.bnk

提取游戏音频文件.bnk 什么是.bnk准备Wwise-Unpacker工具使用Wwise-Unpacker工具总结 什么是.bnk .bnk其实是一种对音频的加密方式,一个.bnk文件中通常包含了多个语音文件,一般可以使用Wwise-Unpacker来解码.bnk格式文件 准备Wwise-Unpacker工具 Wwis…

视频基础学习一——色立体、三原色以及像素

文章目录 前言一、什么是颜色1.色立体特征2.色立体模型 二、三原色和色立体1.三原色(RGB)2.RGB颜色叠加 三、像素和三原色总结 前言 本文的目的是为了梳理音视频基础相关的知识,有很多做流媒体、音视频相关的研发对于音视频的根本原理是不清楚的。博主也是查阅了相…

Linux 内存top命令详解

通过top命令可以监控当前机器的内存实时使用情况,该命令的参数解释如下: 第一行 15:30:14 —— 当前系统时间 up 1167 days, 5:02 —— 系统已经运行的时长,格式为时:分 1 users ——当前有1个用户登录系统 load average: 0.00, 0.01, 0.05…

Code Composer Studio (CCS) - 全局搜索功能

Code Composer Studio [CCS] - 全局搜索功能 1. Ctrl H,全局搜索功能References 1. Ctrl H,全局搜索功能 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

小程序列表下拉刷新和加载更多

配置 在小程序的app.json中,检查window项目中是否已经加入了"enablePullDownRefresh": true,这个用来开启下拉刷新 "window": {"backgroundTextStyle": "light","navigationBarBackgroundColor": &q…

winform实现最小化至系统托盘

NotifyIcon类介绍 NotifyIcon 是 .NET中的一个类,它用于在系统托盘中显示图标。这个类在 System.Windows.Forms 命名空间下。 使用 NotifyIcon 类,你可以在系统托盘中创建一个图标,当用户点击或右键点击这个图标时,可以触发一些事…

GA-kmedoid 遗传算法优化K-medoids聚类

遗传算法优化K-medoids聚类是一种结合了遗传算法和K-medoids聚类算法的优化方法。遗传算法是一种基于自然选择和遗传机制的随机优化算法,它通过模拟生物进化过程中的遗传、交叉、变异等操作来寻找问题的最优解。而K-medoids聚类算法是一种基于划分的聚类方法&#x…

微服务-微服务Nacos配置中心

1.1 配置中心架构 1.2 Config Client源码分析 配置中心核心接口ConfigService public class ConfigServerDemo {public static void main(String[] args) throws NacosException, InterruptedException {String serverAddr "localhost";String dataId "naco…

2024 年 7 项值得学习的高收入技能

曾梦想执剑走天涯,我是程序猿【AK】 目录 简述概要7项高收入技能6 个职业目标示例1. 晋升领导职务2.成为思想领袖3.致力于个人发展4.转向新的职业道路5.体验职业稳定性6.制定职业目标 简述概要 2023年已过,2024年已来,陆陆续续开始了复工&am…

面试经典150题 -- 链表 (总结)

总的地址 : 面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台 c链表总结 : 链表总结 -- 《数据结构》-- c/c-CSDN博客 141 . 环形链表 详细题解参考 : 141 . 环形链表-CSDN博客 这里给出慢双指针的代码 : /*** Defini…

【JAVA WEB】JS的应用

目录 猜数字 预期效果 涉及接口预览 代码实现 表白墙 预期效果 代码实现 代办事项 预期效果 代码实现 猜数字 预期效果 涉及接口预览 //当我们要获得文本框上输入的内容,可以通过.value获取 let guess_text document.querySelector(.guess_num) guess_…

社交商业策略:揭秘Facebook Shops的成功之道

随着数字化时代的不断发展,社交媒体已经成为了商业活动的重要平台之一。在这个趋势下,Facebook作为全球最大的社交媒体平台之一,不仅仅是人们交流互动的场所,更成为了商家开展电子商务的重要渠道。其中,Facebook Shops…

MySQL中SQL语句的执行流程(高频考点)

文章目录 前言SQL语句的执行流程查询语句的执行流程更新语句的执行流程 总结 前言 昨天跟大家讲了MySQL的基础架构(链接:MySQL的基础架构),今天讲一讲我们的高频面试题MySQL中SQL语句的执行流程。 建议看完 MySQL的基础架构 再来…

flutter 文件上传组件和大文件分片上传

文件分片上传 资料 https://www.cnblogs.com/caijinglong/p/11558389.html 使用分段上传来上传和复制对象 - Amazon Simple Storage Service 因为公司使用的是亚马逊的s3桶 下面是查阅资料获得的 亚马逊s3桶的文件上传分片 分段上分为三个步骤:开始上传、上传对…

【漏洞复现-通达OA】通达OA WHERE_STR 存在前台SQL注入漏洞

一、漏洞简介 通达OA(Office Anywhere网络智能办公系统)是由北京通达信科科技有限公司自主研发的协同办公自动化软件,是与中国企业管理实践相结合形成的综合管理办公平台。通达OA WHERE_STR存在前台SQL注入漏洞,攻击者可通过该漏洞获取数据库敏感信息。 二、影响版本 ●…

全网最详细的从0到1的turbo pnpm monorepo的前端工程化项目[vitePress篇]

全网最详细的从0到1的turbo pnpm monorepo的前端工程化项目[vitePress篇] 前言选型为什么选择VitePress安装VitePress运行优化默认UI使用自定义UI编辑自定义布局编写home页面组件编写page页面组件 结语 前言 一个好的工程化项目,必然有一个好的文档管理,…