Python基于selenium实现不同商城的商品价格差异分析系统
1. 前言
selenium原本是一款自动化测试工具,因其出色的 页面数据解析 和 用户行为模拟能力 而常用于爬虫程序中,致使爬虫程序的爬取过程更简单、快捷。
爬虫程序与其它类型程序相比较,本质一样,为数据提供处理逻辑,只是爬虫程序的数据来源于 HTML 代码片段中。
怎样准确查找到页面中数据所在的标签(或叫节点、元素、组件)就成了爬虫程序的关键,只有这一步成立,后续的数据提取、清洗、汇总才有可能。
相比较于 Beaufulsoup 模块, selenium 底层依靠的是强大的 浏览器引擎 ,在页面解析能力上颇有王者的从容和决绝。
本文将使用 selenium 自动摸拟用户的搜索行为,获取不同商城上同类型商品的价格信息,最终生成商品在不同商城上的价格差对比表。
本文通过实现程序流程讲解 selenium,只会讲解程序中涉及到的 selenium 功能。不会深究其它 selenium API 的细节。所以你在阅读本文时,请确定你对 selenium 有所一点点的了解。 2、程序设计流程2.1 需求分析:
本程序实现了用户不打开浏览器、只需要输入一个商品关键字,便能全自动化的实现在不同商城中查找商品价格,并汇总出价格一些差异信息。 程序运行时,提示使用者输入需要搜索的商品关键字。 本程序仅为探研 selenium 的奇妙之处,感受其王者风范,没有在程序结构和界面上费心力。 使用 selenium 摸拟用户打开 京东 和 苏宁易购 首页。 为什么选择京东和苏宁易,而不选择淘宝? 因为这 2 个网站使用搜索功能时没有登录验证需要,可简化本程序代码。 使用 selenium 在首页的文本搜索框中自动输入商品关键字,然后自动触发搜索按钮的点击事件,进入商品列表页面。 使用 selenium 分析、爬取不同商城中商品列表页面中的商品名称和价格数据。 对商品的价格数据做简单分析后,使用 CSV 模块以文件方式保存。 主要分析商品在不同商城上的平均价格、最低价格、最高体系的差异。 当然,如果有需要,可以借助其它的模块或分析逻辑,得到更多的数据分析结论。 2.2 认识 selenium
虽然本文不深究 selenium API 的细节,但是,既然要用它,其使用流程还是要面面俱到。 安装: selenium是 python 第三库,使用前要安装,安装细节就没必要在此多费笔墨。 pip3 install selenium
除了安装 selenium 模块,还需要为它下载一个 浏览器驱动程序 ,否则它无法工作。
什么是浏览器驱动程序?为什么需要它?
解释这个问题,需要从 selenium 的工作原理说起。 浅淡 selenium 的工作原理:
Beautiful soup使用特定的解析器程序解析 HTML 页面。 selenium 更干脆、直接借助浏览器的解析能力。通过调用浏览器的底层 API 完成页面数据查找,也是跪服了,不仅爬取,还可以向浏览器模拟用户行为发送操作指令。
有没有感觉浏览器就是 selenium 手中的牵线木偶(玩弄浏览器于股掌之中)。 selenium 的工作就是驱动浏览器,向浏览器发送指令或接收浏览的反馈,此过程中,浏览器驱动程序(webdriver)就起到了上传下达的作用。
典型的组件开发模式。
很显然,因不同浏览器的内核存在差异性,驱动程序必然也不相同,所以,下载驱动程序之前,请确定你使用的浏览器类型和版本。
本文使用谷歌浏览器,需要下载与谷歌浏览器对应的 webdriver 驱动程序。 进入 https://www.selenium.dev/downloads/ 网站,选择 python 语言,选择最新稳定版本。
请选择与正使用的浏览版本一致的驱动程序。
下载完毕后,指定一个驱动程序的存放目录,本文存放在 D:chromedriverchromedriver.exe 。也可存放在浏览器的安装目录。
2.3 功能函数设计
准备工作就绪后,开始编码: 导入程序所需要的模块,定义程序所需要的变量。 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By import csv import time import math # 浏览器对象 chrome_browser = None # 商品关键字 search_keyword = None # 保存在京东商城搜索到的商品数据,格式{商品名:价格} jd_data = {} # 保存在苏宁商城搜索到的商品数据,格式{商品名:价格} sn_data = {}webdriver:用来构建浏览器对象,从底层设计角度讲,是 selenium 和浏览器之间的接口层。 selenium 向上为用户提供高级应用接口,向下通过 webdriver 和浏览器无障碍沟通。 Service: webdriver 构建浏览器对象时的参数类型。 By: ** 封装了查找页面组件的各种方式。selenium** 向开者提供了很多高级方法用来查询 HTML 页面组件,如通过元素 ID、样式、样式选择器、XPATH……By 封装了这些方案。 诸如:find_element_by_class_name( )、 find_element_by_id()、find_element_by_()、find_element_by_tag_name()、find_element_by_class_name()、find_element_by_xpath()、find_element_by_css_selector() 以上方法已经被标注为过时,请使用 find_element( ) 方法,配合 By 对象切换方式。 csv:用来把获取到的数据以 csv 格式保存。 time:时间模块,用来模拟网络延迟。 math:数学模块,辅助数据分析。 初始化函数:初始化浏览器对象和用户输入数据。 """ 初始浏览器对象 """ def init_data(): # 驱动程序存放路径 webdriver_path = r"D:chromedriverchromedriver.exe" service = Service(webdriver_path) # 构建浏览器对象 browser = webdriver.Chrome(service=service) # 等待浏览器就绪 browser.implicitly_wait(10) return browser """ 初始用户输入的商品名称关键字 """ def input_search_key(): info = input("请输入商品关键字:") return info查询京东商品信息。在京东商城查询商品,分两个步骤,在首页输入商品关键字,点击搜索后,在结果页面查询价格信息。完整代码如下: """ 进入京东商城查询商品信息 """ def search_jd(): global jd_data products_names = [] products_prices = [] # 京东首页 jd_index_url = r"https://www.jd.com/" # 打开京东首面 try: if chrome_browser is None: raise Exception() else: # 打开京东首页 chrome_browser.get(jd_index_url) # 模拟网络延迟 chrome_browser.implicitly_wait(10) # 找到文本输入组件 search_input = chrome_browser.find_element(By.ID, "key") # 在文本框中输入商品关键字 search_input.send_keys(search_keyword) chrome_browser.implicitly_wait(5) # 找到搜索按钮 这里使用 CSS 选择器方案 search_button = chrome_browser.find_element(By.CSS_SELECTOR, "#search > p > p.form > button") # 触发按钮事件 search_button.click() chrome_browser.implicitly_wait(5) # 获取所有打开的窗口(当点击按钮后应该有 2 个) windows = chrome_browser.window_handles # 切换新打开的窗口,使用负索引找到最后打开的窗口 chrome_browser.switch_to.window(windows[-1]) chrome_browser.implicitly_wait(5) # 获取商品价格 product_price_ps = chrome_browser.find_elements(By.CLASS_NAME, "p-price") for i in range(5): p = product_price_ps[i] if len(p.text) != 0: # 删除价格前面的美元符号 products_prices.append(float(p.text[1:])) # 获取商品名称 product_name_ps = chrome_browser.find_elements(By.CLASS_NAME, "p-name") chrome_browser.implicitly_wait(10) for i in range(5): p = product_name_ps[i] if len(p.text) != 0: products_names.append(p.text) jd_data = dict(zip(products_names, products_prices)) jd_data["平均价格"] = sum(products_prices) / len(products_prices) jd_data["最低价格"] = min(products_prices) jd_data["最高价格"] = max(products_prices) # 使用 CSV 模块写入文档 csv_save("京东商城", jd_data) except Exception as e: print(e)
chrome_browser:由 webdriver 构建出来的对 浏览器 映射的对象, selenium 通过此对象控制对浏览器的所有操作。
此对象有一个 find_element( ) 核心方法,用来查找(定位)HTML 页面元素。查找时,可以通过 By 对象指定查找的方式(这里使用了工厂设计模式), By 的取值可以是 ID、CSS_SELECTOR、XPATH、CLASS_NAME、CSS_SELECTOR、TAG_NAME、LINK_TEX、PARTIAL_LINK_TEXT。
打开京东首页后,先定位定位 文本搜索框 和 搜索按钮 。
使用浏览器的开发者工具,检查到文本框的源代码是一段 input html 片段,为了精确地定位到此组件,一般先试着分析此组件有没有独有的属性或特征值,id 是一个不错的选择。html 语法规范 id 值应该是一个唯一值。 search_input = chrome_browser.find_element(By.ID, "key")
找到组件后,可以对此组件进行一系列操作,常用的操作: text 属性:获取组件的文本内容。 send_keys( ) 方法:为此组件赋值。 get_attribute( ) 方法:获取组件的属性值。
这里使用 send_keys 给文本组件赋予用户输入商品关键字。 search_input.send_keys(search_keyword)
再查找搜索按钮组件:
按钮组件是一段 button html 代码,没有过于显著的特性属性值,为了找到这个唯一组件,可以使用 XPATH 或 CSS 选择器 方式。右击此代码片段,在弹出的快捷菜单中找到"复制"命令,再找到此组件的 CSS选择器值。
search_button = chrome_browser.find_element(By.CSS_SELECTOR, "#search > p > p.form > button")
调用按钮组件的 click() 方法,模拟用户点击操作,此操作会打开新窗口,并以列表方式显示搜索出来的商品数据。 search_button.click()
selenium接收到浏览器打开新窗后的反馈后,可以使用 window_handles 属性获取浏览器中已经打开的所有窗口,并以列表的方式存储每一个窗口的操作引用。 windows = chrome_browser.window_handles
对页面元素进行定位查找时,有一个当前窗口(当前可以、正在操作的窗口)的概念。刚开始是在首页窗口操作,现在要在搜索结果窗口中进行操作,所以要切换到刚打开的新窗口。使用负索引得到刚打开的窗口(刚打开的窗口一定是最后一个窗口)。 chrome_browser.switch_to.window(windows[-1])
注意,这时切换到了搜索结果窗口,便可以在这个窗口中搜索所需要组件。
在这个页面中,只需要获取前 5 名的商品具体信息,包括商品名、商品价格。至于具体要获取什么数据,可以根据自己的需要定夺。本程序只需要商品的价格和名称,则检查页面,找到对应的 html 片段。
商品名信息存放在一个 p 片段中,此 p 有一个值为 p-name 的 class 属性。可以使用 CSS-NAME 方式获取,因为所有的商品采用相同片段模板,这里使用 find_elements( ) 方法即可。 product_name_ps = chrome_browser.find_elements(By.CLASS_NAME, "p-name")
find_elements方法返回具有相同 CSS-NAME 的组件列表,编写代码迭代出每一个组件,并获取数据,然后存储在商品名称列表中。 for i in range(5): p = product_name_ps[i] if len(p.text) != 0: products_names.append(p.text)
以同样的方式,获取到价格数据。再把商品名称和价格数据制成字典,并对价格数据做简单分析。 jd_data = dict(zip(products_names, products_prices)) jd_data["平均价格"] = sum(products_prices) / len(products_prices) jd_data["最低价格"] = min(products_prices) jd_data["最高价格"] = max(products_prices) csv_save("京东商城", jd_data)存储数据:数据被压制到字典后,可把字典中的数据以 CSV 格式保存在文档中,以便用户查阅、决策。 def csv_save(sc_name, dic): with open("d:/" + sc_name + ".csv", "w", newline="") as f: csv_writer = csv.writer(f) csv_writer.writerow([sc_name, search_keyword + "价格分析表"]) for key, val in dic.items(): csv_writer.writerow([key, val])
以 CSV 格式存储从京东商城上爬取下来的数据。
获取苏宁易购上的商品数据。与从京东上获取数据的逻辑一样(两段代码可以整合到一个函数中,为了便于理解,本文分开编写)。两者的区别在于页面结构、承载数据的页面组件不一样或组件的属性设置不一样。 def search_sn(): global sn_data # 保存商品名称 products_names = [] # 保存商品价格 products_prices = [] # 苏宁首页 sn_index_url = r"https://www.suning.com/" try: if chrome_browser is None: raise Exception() else: # 打开首页 chrome_browser.get(sn_index_url) # 摸拟网络延迟 chrome_browser.implicitly_wait(10) # 查找文本输入组件 search_input = chrome_browser.find_element(By.ID, "searchKeywords") # 在文本框中输入商品关键字 search_input.send_keys(search_keyword) time.sleep(2) # 找到搜索按钮 这里使用 CSS 选择器方案 search_button = chrome_browser.find_element(By.ID, "searchSubmit") # 触发按钮事件 search_button.click() time.sleep(3) # 获取所有打开的窗口(当点击按钮后应该有 2 个) windows = chrome_browser.window_handles # 切换新打开的窗口,使用负索引找到最后打开的窗口 chrome_browser.switch_to.window(windows[-1]) chrome_browser.implicitly_wait(20) # 获取商品价格所在标签 product_price_ps = chrome_browser.find_elements(By.CLASS_NAME, "def-price") # 仅查看前 5 个商品信息 for i in range(5): p = product_price_ps[i] # 删除价格前面的美元符号 if len(p.text) != 0: products_prices.append(float(p.text[1:])) chrome_browser.implicitly_wait(10) # 获取商品名称 product_name_ps = chrome_browser.find_elements(By.CLASS_NAME, "title-selling-point") for i in range(5): products_names.append(product_name_ps[i].text) # sn_data = dict(zip(products_names, products_prices)) sn_data["平均价格"] = sum(products_prices) / len(products_prices) sn_data["最低价格"] = min(products_prices) sn_data["最高价格"] = max(products_prices) # 使用 CSV 模块写入文档 csv_save("苏宁商城", sn_data) except Exception as e: print(e)
获取到苏宁易购上的商品数据后,同样以 CSV 格式存储。
存储最终的分析结果。这里仅分析了两个商城上同类型商品的平均价格、最低价、最高价的差异性。 def price_result(): if len(jd_data) != 0 and len(sn_data) != 0: with open("d:/商品比较表.csv", "w", newline="") as f: csv_writer = csv.writer(f) jd_name = list(jd_data.keys()) jd_price = list(jd_data.values()) sn_price = list(sn_data.values()) csv_writer.writerow(["比较项", "京东价格", "苏宁价格", "价格差"]) for i in range(5, len(jd_price)): csv_writer.writerow([jd_name[i], jd_price[i], sn_price[i], math.fabs(jd_price[i] - sn_price[i])])
保存了两个商城上商品价格的平均值、最小值、最大值以及绝对差。
最终测试代码 if __name__ == "__main__": search_keyword = input_search_key() chrome_browser = init_data() search_jd() time.sleep(2) search_sn() price_result()请输入商品关键字:华为meta 403. 总结
本文主要是应用 selenium 。通过应用过程对 selenium 做一个讲解,了解 selenium 的基本使用流程。数据分析并不是本文的重点。
如果要得到更全面的分析结果,则需要提供更多维度的数据分析逻辑。
如果塔克拉玛干沙漠每年的平均降雨量再增加3000毫米,10年后会是怎样的景象?感谢提问,在搞清楚这个问题之前,我们先来了解一下塔克拉玛干沙漠的基本现状。众所周知,塔克拉玛干沙漠位于我国南疆三面环山的塔里木盆地中心,总面积达33余万平方公里,它既是我国面积最大
拼多多股价下跌市值蒸发12300亿,其沉默背后的原因很现实前言随着互联网消费平台淘宝的问世,我国的消费市场开始走向电商时代,同时越来越多的企业家纷纷选择模仿淘宝所取得的显著成功,但是能动摇淘宝在消费者心目中地位的电商平台却没有几个,淘宝一
火爆全国的CIM应用工程师来了!开启智慧城市新篇章近年来,我国大力推进CIM平台建设为抓手,促进城市智慧化建设。城市是一个生命体,智慧的城市应当是可感知可判断可反应可学习的。当前,智慧城市建设正向深度推进,在CIM的支撑下,架构城
保障个人及机构互联网言论平等权机器人,水军泛滥是互联网的痼疾,人为造成互联网言论的不平等,也间接使互联网平台为规避风险一刀切管理言论,限制言论的自由,从而带来资本以法规名义控制舆论恶劣倾向。本来实名制理论上可以
深夜突发,证监会紧急回应中国基金报泰勒滴滴出行拟从美股退市下月召开特别股东大会16日晚间,滴滴官网公告,将于2022年5月23日1900举行特别股东大会,就公司的美国存托股票在纽约证券交易所的自愿退市进行
新势力销冠诞生,小鹏汽车智能化威力大爆发2021年是中国新能源车爆发之年,渗透速度之快远超大家想象。据乘联会统计数据显示,2021年111月新能源汽车产销再创新高,累计销量高达251。4万辆,同比增长178。3,渗透率提
想要满满游戏体验感,就选这个ViddaV5G音乐电视随着电视的不断发展,电视对很多人来说,都不是用来看电视的了,而是其他娱乐活动,我就超喜欢用电视打游戏,所以买个好电视很有必要,这样才能有好的游戏体验感呀!我买的是Vidda的这款音
4月25iVOX80不见不散随着各大友商旗舰相继发布完毕,ViVO也将在本月25号发布安卓有史以来最强旗舰X80系列,其中X80搭载天肌9000芯片。前置3200万,后置3个50MP像素摄像头,支持iP68,
每日英语小知识今日是2022。4。16。周6今日分享用了这么久,还不知道键盘上的Esc,Ctrl,Alt都是啥单词?你一定见过很多人不知道键盘上功能键和字母数字键以外的键盘按键有什么用,电脑键盘
布置一整套小米智能家居需要多少钱?结果可能超出想象房子还没有交房,我之前也一直在使用和关注米家的智能家居设备,看到很多网友在咨询把家里改造成整套米家智能家居方案要多少钱,刚好也在计划这件事情,所以在工作之余整理了一下米家智能家居的
锤子SmartisanOS回归,牵手康佳打造电视新品?近些年什么手机品牌最让你觉得惋惜?或许有不少人会投票给锤子,如今锤科也是推出了市场,但SmartisanOS还在正常运营,记得去年还有新版本推送。而在沉寂了好些时间后,Smarti
燃油车一定还有未来!电动车真的不环保吗?我最近电动车发展势头很猛,很多发达国家都提出了停止纯燃油车生产的时限,一个新能源车企的市值远远高于那些传统车企,那燃油汽车业是不是已经变成了夕阳产业,我们应该放弃研发燃油车,主攻新
天玑9000实现对高通骁龙8Gen1的超越真的是奢望吗?欧界欧界报道作为两款顶级旗舰芯片,天玑9000和骁龙8Gen1被不少消费者拿出来比较,天玑9000超越高通骁龙8Gen1究竟是奢望还是事实?不少网友这样看。对于高通骁龙8Gen1,不少
广西创新驱动助力国资国企迈上新台阶新华社南宁1月14日电题广西创新驱动助力国资国企迈上新台阶新华社记者黄浩铭在柳钢集团防城港钢铁基地冷轧厂5G创新工作室里,大屏幕上播放着5G摄像机实时采集的画面,工作人员通过键盘和
降噪耳机悲剧!仅2款获工信部A级认证,不合格耳机危害多大?随着科学技术的发展,我相信很多人都在使用智能产品,并且无论是大人还是小孩,几乎都是人手一对耳机,什么听歌,看电视等都在使用。但是万万没想到的是,据央视报道,近五成降噪耳机降噪量不足
小米首发?中国自研5G芯片正式量产众所周知,在禁令之后,华为海思麒麟5G芯片就不能生产了。即便在如今,华为能够正常采购高通联发科的5G芯片,如骁龙888天玑700等但在去年发布的新机中,绝大部分都是没有5G网络功能
大屏电视怎么选购?我和TCL的故事大屏电视怎么选购?以前想买巨幕电视大家通常会选择激光电视,因为两三万块钱就能买到100英寸巨幕。但是为了买大屏选激光电视,往往牺牲了我们对于画质方面的要求。激光投影
华为Watch3,真正意义上的智能手表年轻用户这几年一直在智能穿戴上发力,而华为的智能手表绝对是市面上最懂得年轻用户的需求。同时随着鸿蒙生态的逐渐完善,华为新推出的Watch3系列,被誉为真正意义上的一款智能手表,能够
重大突破,英国研发超级内存,可同时兼作存储与运存使用可能有部分数码爱好者,尤其是小白用户,可能有这样一种疑惑那就是为什么不管是台式机笔记本,还是智能手机等设备,一定要分存储内存和运行内存,为什么不能统一合二为一?有些内行的朋友可能会
单车女王胡炜炜148万创建摩拜,3年套现15亿,只因她有高人指点文熊猫鉴史编辑熊猫鉴史2018年摩拜单车被美团以37亿美元收购,而摩拜单车创始人胡炜炜成功套现15亿。这一年,她不过36岁,谁能想象到她几年前还拿着每月3000元的工资。从创业到卖
芯片自研时代开始了?1月13日消息,据国外媒体报道,在M1开发团队的领导者杰夫威尔科克斯(JeffWilcox)被英特尔挖走之后不到一周,又出现了苹果芯片团队又一重要设计师被微软挖走的消息。杰夫威尔科
冬天空调开一晚需要多少电?点击蓝字关注我们Winter持续低温,开着空调可太舒服了,但是很多人就会想,空调开一晚到底需要多少电呢?这篇文章给你答案。一般来说,空调开一晚需要多少电是没有准确答案的,因为空调的