查看原文
其他

下拉选择框如何变成“小猫咪” | selenium小技巧

爬虫俱乐部 Stata and Python数据分析 2022-03-15

本文作者:任   哲, 中南财经政法大学经济学院

本文编辑:尚晨曦

技术总编:王子一

Stata&Python云端课程来啦!

      寒雪梅中尽,春风柳上归。为了感谢大家长久以来的支持和信任,爬虫俱乐部为大家送福利啦!!!Stata&python特惠课程双双上线腾讯课堂~原价2400元的Python编程培训课程,现在仅需100元,详情请查看推文《Python云端课程福利大放送!0基础也能学~》;原价600元的正则表达式课程,现在仅需49.9元,详情请查看推文《与春天有个约会,爬虫俱乐部重磅推出正则表达式网络课程!》;原价600元的基本字符串函数课程,现在仅需49.9元,更多信息请查看推文《与春天有个约会,爬虫俱乐部重磅推出基本字符串函数网络课程;原价600元的网络爬虫课程,现在仅需49.9元,更多信息请查看推文《与春天有个约会,爬虫俱乐部重磅推出网络爬虫专题课程》原价600元的文本分析课程,现在仅需49.9元,更多信息请查看推文与春天有个约会,爬虫俱乐部重磅推出文本分析网络课程。变的是价格,不变的是课程质量和答疑服务。对报名有任何疑问欢迎在公众号后台和腾讯课堂留言哦!

导读
在之前的《偷懒小妙招| selenium之玩转鼠标键盘操作(上)》《偷懒小妙招|selenium之玩转鼠标键盘操作--鼠标篇》推文中,我们已经向大家介绍了在selenium模拟用户操作之时所用的常用操作,这里不再赘述,但在许多网站之中都存在的下拉选择框却成为了大家使用时的绊脚石。其实下拉选择框虽然看起来千变万化,可实际上不过是一只“Paper Tiger”,接下来本文将传授技巧,助你将“纸老虎”变成“小猫咪”。

大家在日常使用的时候也会发现,有些下拉选择框既可以下拉选择目标信息,也可以直接输入信息,比如在很多网站中,选择日期时,上述两种方法都可以使用;而有的下拉选择框却无法输入信息,只能点击选择网站提供的信息。这在爬虫的时候实在是令人发狂,很想质问那些程序员们,为什么不能开个会统一一下,最好让我们能一键操作,直接把数据送到手上(谨慎发言🙂)。
哈哈,这当然是开玩笑的。事实上,网站选择框的种类都是程序员们根据实际的功能而选择的。尽管大家在爬虫的时候觉得自己见过无穷无尽的种类,难以搞定。但其实都只是外表不同,花里胡哨的纸老虎,这些各式各样的选择框其实可以只分为两种:1.利用input标签做的假下拉选择框;2.利用select标签做的真选择框。
梁建章教授在学界和商界都混得风生水起,实在是令人羡慕。今天,就让我们蹭一下梁教授的光,把携程拿来作为本文的案例。携程上的酒店预订界面包含着种类丰富的下拉选择框,这使得它成为了一个极好的例子。话不多说,接下来本文会分别介绍两种选择框的处理办法。

一. input标签做的假下拉框





为什么说利用input标签做的选择框是假的选择框呢?这是因为,这种选择框我们其实不必去打开,直接往选择框中输入信息即可,名义为选择框,但在实际操作中选择的功能是可有可无的,所以被称为假选择框。对于这种假选择框的处理十分简单,只要通过元素定位找到该选择框,再利用send_keys()方法需要的选择信息输入其中就行了。下面利用Chrome浏览器进行演示:

首先,打开携程的首页,以目的地对应选择框为例。先按下Ctrl+Shift+C,再点击目的地对应选择框,就可以找到对应源代码了,如下图红框中所示。

可以看到,该选择框源代码中的标签input以及各种属性,在这些属性之中我们需要的是name属性与_cqnotice属性,利用name属性定位选择框,利用_cqnotice属性来了解对输入信息的要求,比如这里我们需要输入中文或拼音。对应代码如下:

1#input 情况一 利用name属性来定位选择框
2driver.find_element_by_name("CityName").clear() #在输入新信息前最后清空选择框
3driver.find_element_by_name("CityName").send_keys("上海")

我们再按下Ctrl+Shift+C,点击入住日期对应选择框,得到对应源代码如下:

1<input type="text" value="yyyy-mm-dd" name="checkIn" id="HD_CheckIn" autocomplete="off" _cqnotice="yyyy-mm-dd" style="background-image: url(&quot;//pic.c-ctrip.com/cquery/pic_aftertomorrow.png&quot;); background-position: right center; background-repeat: no-repeat;">

看到其name属性是”checkIn“,_cqnotice属性"yyyy-mm-dd"。也就是说,输入信息要写出如2021-04-21的格式。同理,退房日期要求和入住信息要求一样。处理这两个下拉框的代码如下:

1driver.find_element_by_name("checkIn").clear() #清空选择框  
2driver.find_element_by_name("checkIn").send_keys("2021-03-11")
3driver.find_element_by_name("checkOut").clear() #清空选择框
4driver.find_element_by_name("checkOut").send_keys("2021-03-12")

当然并不是所有的选择框都能通过进行元素定位并输入信息的,在无法使用元素定位时,还可以通过XPath进行定位。比如本文之中住客数对应选择框的源代码如下:

1<input id="J_RoomGuestInfoTxt" type="text" value="1成人" class="w170" readonly="true">

这里该选择框虽然也是利用input制作的假选择框,但无法输入文本信息,同时也无法用name属性定位,只能点击下方的加号输入信息。所以,这里可以通过XPath定位需要点击的按钮,并使用click()进行点击。
1#input 情况二 没有name属性
2driver.find_element_by_xpath('//*[@id="J_RoomGuestInfoTxt"]').click()       #点击住客数选择框
3driver.find_element_by_xpath('//*[@id="J_AdultCount"]/span[2]/i').click()   #增加1名成人
4driver.find_element_by_xpath('//*[@id="J_ChildCount"]/span[2]').click()     #增加1名儿童
5driver.find_element_by_xpath('//*[@id="J_RoomGuestInfoBtnOK"]').click()     #点击确定
以上就是本文对假选择框的两种处理方法了。但是聪明的你应该已经发现了,说是两种方法,但是它们的本质是一样的,都是先定位下拉选择框,再根据要求输入信息。
二. 利用select标签做的真选择框

接下来介绍的是利用select标签做的真选择框,这种选择框只能靠下拉进行选择,既无法直接输入信息,也无法像住客数选择框一样通过模拟点击选择信息。对于这种选择框,可以通过selenium的Select模块选择我们所需要的信息,下面就来说明如何使用Select模块。
01 选中框内选项
首先,以房间数对应的选择框为例,该选择框的选项和对应源代码如下所示:

1#房间数选择框对应的选择框对应源代码
2<select id="J_roomCountList">
3<option selected="selected" value="1">1间</option>
4<option value="2">2间</option>
5<option value="3">3间</option>
6<option value="4">4间</option>
7<option value="5">5间</option>
8<option value="6">6间</option>
9<option value="7">7间</option>
10<option value="8">8间</option>
11<option value="9">9间</option>
12<option value="10">10间</option>
13</select>

在选择框内目标选项之前,需要对选择框进行定位,这里使用元素定位Select(driver.find_element_by_id('J_roomCountList'))定位到房间数对应的选择框,再在随后使用Select模块。当然也可以将元素定位改为XPath定位。之后大家通过观察源代码可以发现,下拉选择框中的选项都有对应的option标签,标签中包含了该选择框下所有选项的信息。这样就可以利用这些信息进行对框内选项定位。Select模块提供了三种确定框内选项的方式,具体如下:

(1)索引定位

索引定位就是按照目标选项的索引进行定位,索引是从0开始。本例中,选项1间2间3间选项对应的索引分别为0、1、2。

1Select(driver.find_element_by_id('J_roomCountList')).select_by_index(1)  # 选择第二项选项:2间
(2)value值定位

value值定位就是根据option标签的属性value进行定位。本例中,选项1间2间3间选项对应的value值分别为"1"、"2"、"3"。

1Select(driver.find_element_by_id('J_roomCountList')).select_by_value("3")  # 选择value="3"的项:3间

(3)文本定位

文本定位就是根据option标签中间的文本值进行定位。本例中,选项1间2间3间选项对应的文本值分别为"1间"、"2间"、"3间"。

1Select(driver.find_element_by_id('J_roomCountList')).select_by_visible_text("4间")  # 选择text="4间"的项
02 取消框内选项
在我们日常使用时,有时会遇到取消选项的需求,在input标签制作的假选择框中,直接定位选择框后clear()就行了,而在真选择框中,则需要使用Select模块提供的deselect的功能来满足这种需求。取消选项的需求一般出现在选项可以多选的情况,今天携程的案例中都是单选,就不演示了,小伙伴们可以自行寻找案例尝试,用法非常简单,和select功能完全一样。deselect功能的代码如下:
1Select(driver.find_element_by_id('定位目标选择框')).deselect_all             # 取消全部的已选择项
2Select(driver.find_element_by_id('定位目标选择框')).deselect_by_index()        # 取消已选中的索引项
3Select(driver.find_element_by_id('定位目标选择框')).deselect_by_value()        # 取消已选中的value值
4Select(driver.find_element_by_id('定位目标选择框')).deselect_by_visible_text() # 取消已选中的文本值
三. 完整回顾


在最后,我们利用上文中的知识进行一次完整的模拟,来对今天的内容进行回顾。模拟的内容是邀请一个三口之家,要在五一期间来武汉游玩三天,并希望住在光谷附近。具体代码如下:

1#设置selenium
2CHROME_OPTIONS = webdriver.ChromeOptions()
3prefs = {"profile.managed_default_content_settings.images":2}   # 1代表显示图片,2代表不显示图片
4CHROME_OPTIONS.add_experimental_option("prefs", prefs)
5#打开携程官网
6url = "https://www.ctrip.com/?allianceid=4897&sid=155950&ouid=pp&bd_vid=7956535655977937950&keywordid=160662196920"
7CHROME_DRIVER = './Driver/chromedriver.exe'
8driver = webdriver.Chrome(executable_path=CHROME_DRIVER, options=CHROME_OPTIONS)   # 初始化浏览器
9driver.set_window_position(00)
10driver.maximize_window()   # 设置浏览器窗口最大化
11driver.get(url)
12sleep(30)
13
14#选择目的地为武汉
15driver.find_element_by_name("CityName").clear()
16driver.find_element_by_name("CityName").send_keys("武汉")
17sleep(0.3)
18#选择入住日期为5月1日,退房日期为5月3日
19driver.find_element_by_name("checkIn").clear() #清空选择框 使用元素定位
20driver.find_element_by_name("checkIn").send_keys("2021-05-01")
21driver.find_element_by_xpath('//*[@id="HD_CheckOut"]').clear() #清空选择框 使用xpath定位
22driver.find_element_by_xpath('//*[@id="HD_CheckOut"]').send_keys("2021-05-03")
23driver.find_element_by_xpath('//*[@id="searchBox"]/div[1]').click() #随便点击空白,关闭日期下拉框
24sleep(1)
25#选择房间数为1间
26Select(driver.find_element_by_id('J_roomCountList')).select_by_value("1")
27#选择酒店级别为五星级豪华
28Select(driver.find_element_by_id('searchHotelLevelSelect')).select_by_visible_text("五星级/豪华")
29sleep(1)
30#选择住客数为2成人1儿童
31driver.find_element_by_xpath('//*[@id="J_RoomGuestInfoTxt"]').click()   #点击住客数选择框
32sleep(5)#考虑网速点击住客数选择框后休息一下,加载剩余信息
33driver.find_element_by_xpath('//*[@id="J_AdultCount"]/span[2]/i').click() #增加1名成人(默认为1名成人故两名成人只需点击一次)
34driver.find_element_by_xpath('//*[@id="J_ChildCount"]/span[2]').click() #增加1名儿童
35driver.find_element_by_id('J_RoomGuestInfoBtnOK').click() #点击确认
36sleep(1)
37#输入关键词:光谷
38driver.find_element_by_name("keywordNew").send_keys("光谷")
39driver.find_element_by_xpath('//*[@id="searchBox"]/div[1]').click() #随便点击空白,关闭关键词下拉框
40sleep(1)
41#模拟搜索
42driver.find_element_by_xpath('//*[@id="HD_Btn"]').click() #点击搜索
43driver.find_element_by_xpath('//*[@id="lg_loginbox"]/a').click()  #关闭登录界面

运行后效果如下图所示:

好了,以上就是今天的全部内容了,今天的内容虽然简单,但却是处理下拉选择框的基本原理,无论你遇到的下拉选择框有多么花里胡哨,掌握了上述内容,你就一定能将“纸老虎”变成“小猫咪”。现在离五一小长假也只有十天左右的时间了,大家根据上面的程序,用selenium去体验自动化查询酒店的感觉吧。

最后,我们为大家揭秘雪球网(https://xueqiu.com/)最新所展示的沪深证券和港股关注人数增长Top10。

欢迎大家点赞、评论、转发呦~


对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!

往期推文推荐

  Python中的运算符知多少?

  快来get缺失值的正确打开方式

  frame框架——我到底在哪个“房间”

如何使用Pandas读取txt文件?

基于MySQL数据库实现增量式爬取

寻找春日气息|本月最受欢迎的景点都在这里!

问世间情为何物,大数据也想参悟——后考研时代,何以解忧?唯有数据!

Python与数据库交互—浅述pymysql

偷懒小妙招|selenium之玩转鼠标键盘操作--鼠标篇

大家用Stata来“找茬”

“粉墨登场”——多期双重差分法(DID)的Stata操作

Python与百度地图合璧,绘制棒呆的热力地图

【数据可视化】统计图绘制神器:Seaborn

检索Stata推文的“任意门”学会了这些,分分钟提升你的毕业体验

【爬虫实战】双一流大学的月关注度

【爬虫实战】“中国人不吃这一套”——人民日报微博评论分析

进化的标签管理助手——elabel命令

“学术明星”——双重差分法(DID)的Stata操作

偷懒小妙招| selenium之玩转鼠标键盘操作(上)

【爬虫实战】南京地铁又上热榜——客流量分析

renfiles:批量重命名文件的利器

Stata中字符串的处理

物以类聚——浅述k-means聚类算法

我在哪里?调用高德API获取地址经纬度信息

超级简单的条件函数,轻松生成虚拟变量

关于我们 


微信公众号“Stata and Python数据分析”分享实用的Stata、Python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。



此外,欢迎大家踊跃投稿,介绍一些关于Stata和Python的数据处理和分析技巧。

投稿邮箱:statatraining@163.com投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存