Selenium实战两例:爬数据/挂机

Selenium的官网上介绍,它是一款Web Browser Automation,用途是前端页面的自动化测试。通过结合Selenium、Webdriver,再加上python灵活的特性,我们可以轻易地完成一些数据采集、网页操作等任务。

这次在平时生活中有两个小需求,一是某论坛大量女生爆照,其中甚至包含女生们的联系方式,所以。。嘿嘿嘿。另一个需求是学校在某树网上开设了在线课程,需要顺序、依次观看视频课程,视频播放过程中会有弹窗,播放完成需要手动切换下一段视频,所以这里又利用到了Selenium。

配置环境

我们的Python代码基于Python 3.6,Python环境配置不表。

我们利用到了ChromeDriver - WebDriver for Chrome来驱动浏览器,所以需要到Google Sites来下载ChromeDriver,并放在合适的路径,另外安装好Chrome。当然使用其他WebDriver以及配套浏览器也是可以的。

然后是安装Selenium,这个官网上都有说明,细节不表。

初始化

初始化WebDriver,完成配置。以下代码设置了ChromeDriver的路径,下载地址。

1
2
3
4
5
6
driverpath = "/Users/username/chromedriver"
chromeOption = webdriver.ChromeOptions()
prefs = {"download.default_dictionary": "/users/username/desktop"}
chromeOption.add_experimental_option("prefs", prefs)
chromedriver = webdriver.Chrome(executable_path=driverpath, chrome_options=chromeOption)

How to do

用这个方式来加载一个网页:

1
chromedriver.get("http://localhost/")

通过开发者工具我们可以很简单地在HTML中找到需要的标签。WebDriver有多个API供查找标签:find_element_by_id()find_element_by_class_name()find_element_by_css_selector()find_element_by_link_text()find_element_by_name()等等。

举一个例子:

1
<h1 name='classname'>username</h1>

通过上述HTML标签拿到username,可以通过下面这个方式:

webdriver.find_element_by_class_name("classname")这样拿到了一个element,再通过.text即可取到标签的内容“username”。

讲一个小技巧,需要通过标签的特殊attribute来拿标签的时候,我们可以通过find_element_by_css_selector()。比如<h1 wtf="what the fuck">wtf</h1>,就可以通过chromedriver.find_element_by_css_selector("h1[wtf='what the fuck']"来找到这个element。

输入框输入数据,Selenium提供了send_keys()。我们先获取到input标签的element,对这个element调用send_keys()即可。

1
2
usernameInput = chromedriver.find_element_by_id("lUsername")
usernameInput.send_keys("username")

翻页怎么做?都说了Selenium是模拟人工行为,所以思路同样是找到按钮那个标签,点击即可。点击操作就是click()

1
2
pagebtns = chromedriver.find_element_by_id("commentsPageBar").find_elements_by_tag_name("a")
pagebtns.click()

数据写入:

1
2
3
4
5
req = urllib.request.Request(url, headers={'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0'})
data = urllib.request.urlopen(req, timeout=30).read()
f = open(file_name, 'wb')
f.write(data)
f.close()

这段代码需要import urllib.request,通过urllib来打网络请求下载数据,并写入文件。

OK,至此,用Selenium爬数据需要的技术点,基本就够了。

然后说说我是怎么fuck某树视频课程的。

某树视频课程在播放过程中,每五秒通过Ajax向服务器同步一次视频播放进度,如果播放进度有异常,会通报学校查水表的,所以这里想到了利用Selenium来模拟人工操作来刷视频。

登录信息的记录有几种方式,我们通过开发者工具可以观察到,某树其实是把很多信息存在了Cookies里面,我们可以通过WebDriver的有关API操纵Cookies,LocalStorage里面也有一个token。我们当然可以把这些数据完全模拟到我们的ChromeDriver里,其实没必要,没有这些数据的时候,我们也仅需要拿到input后填充登录信息即可,所以没必要把那么多数据伪造进去。

视频播放过程中会有弹窗,用户如果不手动关闭弹窗,视频不会继续播放,干掉弹窗的方式很简单,找到弹窗的关闭按钮,click()即可。我们把find_element_by...方法的异常捕获,如果找不到,那说明没有弹窗。

视频播放完成,不会自动切换下一段视频,所以需要判断视频播放器的播放状态。当视频播放暂停,我们可以点击下一课。我们这里为了测试方便,直接拿了播放按钮的状态,我们拿播放进度条的width=100%可以更好地判断视频是否播放完。拿按钮状态代码如下:

1
2
3
4
5
6
7
def checkVideo():
playButton = chromedriver.find_element_by_id("playButton")
playStutusClass = playButton.get_attribute("class")
if playStutusClass == "playButton":
return True
else:
return False

如何切换到下一小节视频?这里就看特征,小节的li标签都有_order这个唯一的attribute,比如第一章第一节第一小节是1.1.1,第三章第二节是3.2,以此类推。具体的找标签逻辑可以看代码,已经开源。

ZhihuishuFucker