引子——
最近小编在沉迷捕鱼之余,扫到了某问答网站里的一个网友提问的标题叫做“Python真的有那么神吗?”,各位被邀嘉宾们针对最近Python热度近年来持续上升并吊打老牌编程语言的现象,分析总结了Python相对于其他编程语言的优势,并展望Python登顶成为下一个编程语言之王的未来。
当然,Python辉煌的现状小编在此就不讨论了。小编认为,一个编程的语言的热度高不高跟它的学习曲线前端的陡峭程度联系十分紧密。Python易于上手的特性使得它能得到大家如此的追捧变得毫不意外。另外,Python海量的拓展包资源使得很多复杂的应用只需要一行代码就可以搞定,从常用的最优化问题求解到目前最热的AI,很多资源都可以直接找到并立刻用起来,真香!
爬虫,小编身为结构工程师,这个词直到我意识到我需要从太平洋地震工程研究中心(PEERC)数据库下载海量地震波时程之前都是又遥远又神秘的。整个地震波时程的下载流程大概是这样的:进入PEERC的网站,找到数据库,登陆账号,搜地震波号,点击下载,搜地震波号,点击下载,搜地震波号,点击下……我想我可以不用再往下说了。
当我机械性地重复了好几次点击下载之后,我就意识到我的鼠标以及我的手可能撑不到把这库里上万条波全都下载下来的那个时候了。这手要是废了还怎么好好摸鱼工作??于是——我想起来了那个神秘的词:爬虫。
鉴于小编自己在学习python的过程中见证的这门语言对于新手的友好程度,我当机立断地认为直接搜索“python爬虫”就立刻可以出来一大片的教程,果不其然
经过一顿阅读之后,总结了一下爬虫的原理基本上就是模拟浏览器来发送各个指令给目标服务器(当然,这种指令是需要有规则的、重复性的,不然也就没有需要爬虫的意义了),最终达到能够实现自动捕获大量所需要的内容。理论上来说,学习爬虫需要懂html(网页文件构成编码),如果是复杂一点的网页,还需要一些php、JavaScript之类的各类开发语言。(小编的头开始变大……)
但是!!感谢Chrome和Firefox的开发者们,他们基于测试网站bug的初衷,开发了一套用于网页测试的脚本驱动器,可以让浏览器自动执行某些代码。这个脚本驱动器可以被Python的一个扩展包所驱动,于是理所当然的——爬虫也可以利用这个包来开发,来模拟各类浏览器的重复操作。这个包的名字就是Selenium。
感谢Selenium,把我的双手从上万次的点击中拯救了出来,并且一边下载一边工(mo)作(yu)了!
1 – import selenium
Selenium的安装与其他的python包并无他异,最简单的方法当然是配置好python之后并安装pip,然后跟其他任何python包的安装一样直接输入
pip install selenium
大功告成。
为了测试Selenium包是否正确安装,可以在python的运行环境下直接import selenium。如果不报错的话,那么就是正确安装了。
2 – 爬虫问题分析
要实现教会爬虫自动下载地震波,那必然是要将“下载地震波”这整个操作流程一步一步地拆分出来,然后详细地把每个拆分的流程写进爬虫里。
首先要做的就是操作流程分析,我们需要详细地把从访问太平洋地震工程研究中心至最后点下“下载”这个按钮的全流程都分步骤写出来:
i. 访问PEER(https://ngawest2.berkeley.edu/)
ii. 点击NGA-West2数据库
iii. 登陆账号
iv. 提交目标地震波谱
v. 输入地震波编号然后搜索
vi. 点击下载按钮,并更新搜索条件再次点击搜索按钮
重复vi.过程直至到达下载次数上限(PEER限制每个账号每周下载200条地震波)
分析完了各个步骤,接下来是要对各个步骤里我们需要爬虫去做什么行为进行归类一下,发现主要有下面三种:
-
访问某网页(比如首页)
-
填入网页里的表单信息(比如用户名密码、搜索条件)
-
点击网页里的某个按钮
a) 访问某网页
首先要做的当然是
import selenium
然后,在访问某网页之前,我们需要建立一个浏览器的对象,就像我们打开网页之前要打开浏览器一样,有了浏览器对象我们才能模拟浏览器进行各类操作。
browser = selenium.webdriver.Chrome(chromedriverPath)
这里小编使用的是Chrome浏览器,所以要用到chromedriver,也就是Chrome浏览器测试的驱动器,这个驱动器可以在Chrome的官网上下到,也可以在网上对应找到资源。下载完成之后把对应的路径替换chromedriverPath就可以了。
接下来,访问网页的操作就是:
browser.get(‘https://ngawest2.berkeley.edu/’)
把中间的网址换成任意一个网址就可以实现在浏览器中访问该网址了,下面就是运行结果:
那一行“Chrome正在受到自动测试软件的控制”就表明我们调用Selenium驱动Chrome自动运行脚本成功,兴奋!接下来就可以继续做进一步的开心的事情了。
b) 填入网页里的表单信息
首先需要找到填的那个框是什么,这个时候就需要用到Chrome浏览器里的“检查元素”功能了。在Chrome浏览器中打开我们需要填用户名的地方,然后在用户名的填入框里面点击右键,选择”检查…”
这样我们就可以打开这个网页的html代码来看看这个框到底是从哪里出来的。我们会发现Chrome已经自动帮我们高亮了这一段代码
我们发现它有个叫做name的属性,赋值为”user[email]”。于是我们可以用selenium里的”find_element_by_name”来确定这个框的位置,然后再使用”send_keys”来填入我们的账号:
usernameBox = browser.find_element_by_name(‘user[email]’)
usernameBox.send_keys(‘zhangsan@qq.com’)
c) 点击网页里的某个按钮
同样的,我们也可以用审查元素的方式在网页的按钮上点击右键找到这个按钮的网页源代码是什么,比如上例中填完用户名密码之后的“登陆”按钮:
如法炮制,我们先用”find_element_by_name”来确定这个按钮,然后再使用“click”来模拟点击这个按钮。在此,我们可以把两行代码缩略成一行代码:
signInButton = browser.find_element_by_name (‘commit’)
signInButton.click()
However!!当小编用“右键-检查”点开地震波搜索界面的搜索按钮的网页源码时,发现
这啥?不按套路出牌啊。这种没有“name”属性的按钮应该怎么处理?
还好强大的selenium早就考虑到了这种情况,为我们提供了一种通用的查找元素的方法”find_element_by_xpath”,通过它,网页上几乎任何元素都可以被其抓取,只需要写出对应的xpath表达式即可。
对于上例中的搜索按钮,其对应的xpath表达式为
searchButton_XPATH = ‘//button[@type=”button” and @onclick=”uncheck_plot_selected();reset_selectedResult();OnSubmit();”]’
可以看到,其关键字是一一对应的,只需要找出正确的关键词,就可以实现找到网页中的元素了!
然后就是点击这个按钮的动作:
searchButton = browser.find_element_by_xpath(searchButton_XPATH)
searchButton.click()
就实现了成功点击这个按钮了!
3 – 爬虫的最终Python代码实现
所以,把上面所有的内容串在一起,实现所有的步骤,整体的Python代码就形成了:
import selenium
browser = webdriver.Chrome(chromedriverPath)
# 第一步访问主页并找到登陆页面登陆
browser.get(‘https://ngawest2.berkeley.edu/users/sign_in’)
# 第二步填写用户名密码
username = browser.find_element_by_name(‘user[email]’)
username.send_keys(‘zhangsan@abc.com’)
password = browser.find_element_by_name(‘user[password]’)
password.send_keys(‘123456abc’)
# 第三步点击登陆按钮
browser.find_element_by_id(‘user_submit’).click()
# 第四步在目标地震波谱形式中点击提交按钮
submitButton_XPATH = ‘//button[@type=”button” and @onclick=”OnSubmit();”]’
button = broswer.find_element_by_xpath(submitButton_XPATH)
button.click()
# 第五步 输入地震波号然后搜索
searchRecordNumber = browser.find_element_by_id(‘search_search_nga_number’)
searchRecordNumber.send_keys(123)
searchButton_XPATH = ‘//button[@type=”button” and @onclick=”uncheck_plot_selected();reset_selectedResult();OnSubmit();”]’
button = broswer.find_element_by_xpath(searchButton_XPATH)
button.click()
# 第六步 点击下载按钮
downloadButton_XPATH = ‘//button[@type=”button” and @onclick=”getSelectedResult(true)”]’
button = broswer.find_element_by_xpath(downloadButton_XPATH)
button.click()
接下来只需要把第五、六步写进一个for循环,然后其中的地震波号随着每次for循环的迭代而变化就可以了。小编此刻静静地享受python给生活带来的便利……
后记:
随着爬虫在卖力地向我证明它对地震波的热爱,小编的硬盘里也渐渐的填满了地震波:
但是问题也接踵而至:PEER似乎限制了每个电脑的下载数量限制,即每周最多200条,每月最多400条。到底这个限制跟什么因素有关呢,能不能想办法突破它?不过,这些东西似乎都与网络安全相关了,小编已经在深思是不是要走上黑客这条路了……
文中的方法可以轻易移植到其他爬虫应用,类似于找淘宝某物品价格等,小编的同事已经在爬虫的帮助下在链家找到了心仪的房价区间。Python的应用还有很多,真香!