37. [实例]Selenium实战应用
1.前言
本节讲解 Python Selenium 爬虫实战案例,通过对实战案例的讲解让您进一步认识 Selenium 框架。
实战案例目标:抓取京东商城(https://www.jd.com/)商品名称、商品价格、评论数量,以及商铺名称。比如输入搜索“Python书籍”,则抓取如下数据:
{'name': 'Python编程 从入门到实践 第2版 人民邮电出版社', 'price': '¥52.50', 'count': '200+条评价', 'shop': '智囊图书专营店'} {'name': 'Python编程 从入门到实践 第2版(图灵出品)', 'price': '¥62.10', 'count': '20万+条评价', 'shop': '人民邮电出版社'} ...
Selenium 框架的学习重点在于定位元素节点,关于如何定位,我们已经介绍了 8 种方法,其中 Xpath 表达式适用性强,并且便捷。因此,建议大家多多熟悉 Xpath 表达式的相关语法规则。本节案例中很大一部分采用了 Xpath 表达式定位元素,希望帮助您温故知新。
本节案例中涉及了几个技术难点:第一,如何下拉滚动条下载商品,第二,如何实现翻页,也就是抓取下一页的内容,第三,如何判断数据已经抓取完毕,即终止页。下面我们逐步讲解。
2. 实现自动搜索
实现自动输出、自动搜索是最基础的一步。首先定位输入框的的节点,其次定位搜索按钮节点,这与实现百度自动搜索思路一致,最关键就是要正确定位元素节点。
通过开发者调试工具检查相应的的位置,可得如下 Xpath 表达式:
1 2 | 输入框表达式: //*[@id="key"] 搜索按钮表达式: //*[@class='form']/button |
代码如下所示:
1 2 3 4 5 | from selenium import webdriver broswer=webdriver.Chrome() broswer. get ( 'https://www.jd.com/' ) broswer.find_element_by_xpath( '//*[@id="key"]' ).send_keys( "python书籍" ) broswer.find_element_by_xpath( "//*[@class='form']/button" ).click() |
3. 滚动滑动条
实现了自动搜索后,接下来就是要抓取页面中的商品信息,而您会发现只有将滑动条滚动至底部,商品才会全部加载完毕。滚动滑轮操作的代码如下:
1 2 3 4 5 6 | # scrollTo(xpos,ypos) # execute_script()执行js语句,拉动进度条件 #scrollHeight属性,表示可滚动内容的高度 self.browser.execute_script( 'window.scrollTo(0,document.body.scrollHeight)' #拉动进度条至底部 ) |
之后在通过 Xpath 表达式匹配所有商品,并将它们放入一个大列表中,通过循环列表取出每个商品,最后提取出想要的信息。
1 2 3 4 5 6 7 8 9 10 11 | li_list=self.browser.find_elements_by_xpath( '//*[@id="J_goodsList"]/ul/li' ) for li in li_list: item={} # 提取商品名 item[ 'name' ]=li.find_element_by_xpath( './/div[@class="p-name"]/a/em' ).text.strip() # 提取价格 item[ 'price' ]=li.find_element_by_xpath( './/div[@class="p-price"]' ).text.strip() # 提取评论数量 item[ 'count' ]=li.find_element_by_xpath( './/div[@class="p-commit"]/strong' ).text.strip() # 提取商家店铺 item[ 'shop' ]=li.find_element_by_xpath( './/div[@class="p-shopnum"]' ).text.strip() |
4. 实现翻页抓取
如何实现翻页抓取数据,并判断数据数据已经抓取完毕呢?这其实并不难想到,我们可以先跳至终止页(即最后一页)。此时最后一页的“下一页”处于不可用状态,其元素节点如下:
1 2 | 终止页下一页 class 属性:<a class = "pn-next disabled" ><em>下一页</em><i> > </i></a> 其他页下一页 class 属性:<a class = "pn-next" onclick= "SEARCH.page(3, true)" ...><em>下一页</em><i> > </i></a> |
如果页面源码中有上述代码存在,则证明此页是最后一页,若没有则不是。因此通过 if ...else 语句即可实现上述需求,如下所示:
1 2 3 | #-1说明没找到,不是最后一页,执行点击 “下一页” 操作 if self.browser.page_source.find( 'pn-next disabled' )==-1: browser.find_element_by_class_name( 'pn-next' ).click() |
5. 完整程序代码
完整程序代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #coding:utf8 from selenium import webdriver import time import pymongo class JdSpider( object ): def __init__(self): self.url= 'http://www.jd.com/' self.options=webdriver.ChromeOptions() # 无头模式 self.options.add_argument( '--headless' ) self.browser=webdriver.Chrome(options=self.options) # 创建无界面参数的浏览器对象 self.i=0 #计数,一共有多少件商品 #输入地址+输入商品+点击按钮,切记这里元素节点是京东首页的输入栏、搜索按钮 def get_html(self): self.browser. get (self.url) self.browser.find_element_by_xpath( '//*[@id="key"]' ).send_keys( 'python书籍' ) self.browser.find_element_by_xpath( "//*[@class='form']/button" ).click() #把进度条件拉倒最底部+提取商品信息 def get_data(self): # 执行js语句,拉动进度条件 self.browser.execute_script( 'window.scrollTo(0,document.body.scrollHeight)' ) # 给页面元素加载时预留时间 time.sleep(2) #用 xpath 提取每页中所有商品,最终形成一个大列表 li_list=self.browser.find_elements_by_xpath( '//*[@id="J_goodsList"]/ul/li' ) for li in li_list: #构建空字典 item={} item[ 'name' ]=li.find_element_by_xpath( './/div[@class="p-name"]/a/em' ).text.strip() item[ 'price' ]=li.find_element_by_xpath( './/div[@class="p-price"]' ).text.strip() item[ 'count' ]=li.find_element_by_xpath( './/div[@class="p-commit"]/strong' ).text.strip() item[ 'shop' ]=li.find_element_by_xpath( './/div[@class="p-shopnum"]' ).text.strip() print(item) self.i+=1 def run(self): #搜索出想要抓取商品的页面 self.get_html() #循环执行点击“下一页”操作 while True: #获取每一页要抓取的数据 self.get_data() #判断是否是最一页 if self.browser.page_source.find( 'pn-next disabled' )==-1: self.browser.find_element_by_class_name( 'pn-next' ).click() #预留元素加载时间 time.sleep(1) else : print( '数量' ,self.i) break if __name__ == '__main__' : spider=JdSpider() spider.run() |
输出结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | { 'name' : 'Python编程 从入门到实践 第2版(图灵出品) 人民邮电出版社' , 'price' : '¥52.50' , 'count' : '200+条评价' , 'shop' : '智囊图书专营店' } { 'name' : 'Python编程 从入门到实践 第2版(图灵出品)' , 'price' : '¥62.10' , 'count' : '20万+条评价' , 'shop' : '人民邮电出版社' } { 'name' : 'Python编程三剑客:Python编程从入门到实践第2版+快速上手第2版+极客编程(套装共3册)' , 'price' : '¥206.90' , 'count' : '5万+条评价' , 'shop' : '人民邮电出版社' } { 'name' : 'Python数据分析从入门到实践(excel高效办公)(3全彩版)' , 'price' : '¥46.10' , 'count' : '10万+条评价' , 'shop' : '明日科技京东自营旗舰店' } { 'name' : '零基础学Python(编程入门 项目实践 同步视频)(3全彩版)' , 'price' : '¥37.50' , 'count' : '10万+条评价' , 'shop' : '明日科技京东自营旗舰店' } { 'name' : 'Python编程快速上手 让繁琐工作自动化 第2版' , 'price' : '¥44.50' , 'count' : '10万+条评价' , 'shop' : '人民邮电出版社' } { 'name' : '现货包邮Python学习手册(原书第5版)上下册2本/计算机编程设计|8053406' , 'price' : '¥142.30' , 'count' : '100+条评价' , 'shop' : '互动创新图书专营店' } { 'name' : '零基础入门学习Python(第2版)' , 'price' : '¥70.30' , 'count' : '1万+条评价' , 'shop' : '清华大学出版社' } { 'name' : '超简单:用Python让Excel飞起来' , 'price' : '¥34.90' , 'count' : '2万+条评价' , 'shop' : '机械工业出版社自营官方旗舰店' } { 'name' : '流畅的Python(图灵出品)' , 'price' : '¥109.80' , 'count' : '2万+条评价' , 'shop' : '人民邮电出版社' } { 'name' : 'Python编程从入门到实践第二版 python编程从入门到实战零基础自学教程计算机基础语言数据分析' , 'price' : '¥49.80' , 'count' : '5000+条评价' , 'shop' : '墨马图书旗舰店' } { 'name' : 'Python深度学习:基于PyTorch' , 'price' : '¥73.40' , 'count' : '5万+条评价' , 'shop' : '机械工业出版社自营官方旗舰店' } { 'name' : 'Python自然语言处理实战:核心技术与算法 自然语言处理教程' , 'price' : '¥48.30' , 'count' : '37条评价' , 'shop' : '芝麻开门图书专营店' } { 'name' : 'Effective Python:编写高质量Python代码的90个有效方法(原书第2版)' , 'price' : '¥110.60\n¥105.10' , 'count' : '2万+条评价' , 'shop' : '机械工业出版社自营官方旗舰店' } ... |
Selenium 自动化爬虫让你无须关心网站的类型(静态或者动态),只需您按部就班的寻找元素节点,并依此点击,即可实现数据抓取。不过 Selenium 最大的缺点就是效率低,因此它只适合做小规模的数据采集工作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)