Python 爬虫:Selenium&PhantomJS抓取数据!

Selenium和PhantomJS配合,可以模拟浏览器获取包括JavaScript的数据。不单要获取网站数据,还需要过滤出“有效数据”。Selenium本身带有一套自己的定位过滤函数。它可以很方便地从网站返回的数据中过滤出所需的“有效数据”。

Python资源共享群:626017123

1、获取百度搜索结果

想知道Python模块最详细的用法,直接用help函数就可以了。鉴于Selenium.Webdriver的help文件太大,分屏显示又不那么方便,干脆将帮助文件保存到文件中慢慢查看。执行命令:

python

from selenium import webdriver

import sys

browser=webdriver.PhantomJS()

out=sys.stdout

sys.stdout=open('browserHelp.txt','w')

help(browser)

sys.stdout.close()

sys.stdout=out

browser.quit()

exit()

一定要加上browser.quit(),否则cmd.exe在执行exit时会无法退出。

执行结果如图1所示。

 

 

 

 

 

 

图1 获取help文件

想获取“有效信息”,第一步当然是网站获取返回数据,第二步就是定位“有效数据”的位置,第三步就是从定位中获取“有效数据”。

以百度搜索为例,使用百度搜索“Python Selenium”,并保存第一页搜索结果的标题和链接。从服务器返回数据,由PhantomJS负责,获取返回的数据用Selenium.Webdriver自带的方法page_source,例如:

from selenium import webdriver

browser=webdriver.PhantomJS()

browser.get(URL)

html=browser.page_source

有两种方法可以得到搜索结果页面。第一种,百度主页还是使用get方式上传request。这里可以先找一个浏览器,打开百度后搜索关键词。再把返回来的搜索结果的URL保存下来用Selenium&PhantomJS打开,再获取返回的数据。第二种,直接用Selenium&PhantomJS打开百度的主页,然后模拟搜索关键词。直接从Selenium&PhantomJS中返回数据。这里使用第二种方法,可以很清楚地看到Selenium&PhantomJS获取数据的过程。

第一步获取搜索结果。打开cmd.exe,准备好环境。执行命令:

python

from selenium import webdriver

browser=webdriver.PhantomJS()

browser.get('https://www.baidu.com')

browser.implicitly_wait(10)

执行结果如图2所示。

 

 

 

 

 

 

图2 模拟百度搜索

这里要关注一个函数implicitly_wait()。使用Selenium&PhantomJS最大的优势是支持JavaScript,而PhantomJS浏览器解释JavaScript是需要时间的。这个时间是多少并不好确定,当然可以用time.sleep()强行休眠等待一个固定时间。可这个固定的时间定长了,浪费时间;定短了,又没能完整地解释JavaScript。Implicitly_wait函数则完美地解决了这个问题,给implicitly_wait一个时间参数。Implicitly_wait会智能等待,只要解释完成了就进行下一步,完全没有浪费时间。下面从网页的框架中选取表单框,并输入搜索的关键词,完成搜索的过程。

2、获取搜索结果

第二步定位表单框架或“有效数据”位置,可以用import导入bs4来完成,也可以用Selenium本身自带的函数来完成。Selenium本身给出了18个函数,总共8种方法从返回数据中定位“有效数据”位置。这些函数分别是:

find_element(self,by='id',value=None)

find_element_by_class_name(self,name)

find_element_by_css_selector(self,css_selector)

find_element_by_id(self,id_)

find_element_by_link_text(self,link_text)

find_element_by_name(self,name)

find_element_by_partial_link_text(self,link_text)

find_element_by_tag_name(self,name)

find_element_by_xpath(self,xpath)

find_elements(self,by='id',value=None)

find_elements_by_class_name(self,name)

find_elements_by_css_selector(self,css_selector)

find_elements_by_id(self,id_)

find_elements_by_link_text(self,text)

find_elements_by_name(self,name)

find_elements_by_partial_link_text(self,link_text)

find_elements_by_tag_name(self,name)

find_elements_by_xpath(self,xpath)

这18个函数前面的9个带element的函数将返回第一个符合参数要求的element,后面9个带elements的函数将返回一个列表,列表中包含所有符合参数要求的element。命名是9个函数,为什么只有8种方法呢?上面函数中,不带by的函数,配合参数可以替代其他的函数。例如:find_element(by='id', value='abc')就可以替代find_element_by_id('abc')。同理,find_elements(by='id', value='abc')也可以替代find_elements_by_id('abc')。

这8种定位方法组合应用,灵活配合,可以获取定位数据中的任何位置。在使用浏览器请求数据时,用find_element_by_name、find_element_by_class_name、find_element_by_id、find_element_by_tag_name会比较方便。一般的表单、元素都会有name、class、id,这样定位会比较方便。如果仅仅是为了获取“有效数据”的位置,还是find_element_by_xpath和find_element_by_css比较方便。强烈推荐find_element_by_xpath,真的是超级方便。

先定位文本框,输入搜索关键词并向服务器发送数据。在Chrome中打开百度主页,查看源代码页面(如果想全程无GUI,也可以直接在Selenium中用page_source获取页面代码,保存后再慢慢搜索,不过这样就比较麻烦了)。在源代码页面搜索type=text,也就是查找页面使用的文本框,搜索结果如图3所示。

 

 

 

 

 

 

图3 搜索文本框位置

从图3可以看出文本框里有class、name、id属性,可以使用find_element_by_class_name、find_element_by_id、find_element_by_name来定位。执行命令:

textElement=browser.find_element_by_class_name('s_ipt')

textElement=browser.find_element_by_id('kw')

textElement=browser.find_element_by_name('wd') #这三个任选其一都可以

textElement.clear()

textElement.send_keys('Python selenium')

回到Chorme中百度源代码页面,搜索type=submit,定位submit按键位置,如图4所示。

 

 

 

 

 

 

图4 搜索submit按键

从图4可看出,submit按键有id、class属性,可以用find_element_by_class_name和find_element_by_id定位。执行命令:

submitElement=browser.find_element_by_class_name('btn self-btn bgs_btn')

submitElement=browser.find_element_by_id('su') #这两个任选一个

submitElement.click()

print browser.title

执行结果如图5所示。

 

 

 

 

 

 

图5 获取搜索结果

此时browser已经获取搜索的结果。

3、获取有效数据位置

第三步获取“有效数据”位置或者说是element。先定位搜索结果的标题和链接,再回到Chrome浏览器,在百度中搜索python selenium,在搜索结果页面中查看源代码。因为Chrome浏览器和PhantomJS浏览器返回的结果可能有所不同,这里只需要知道返回结果的大致结构,不需要完全一致。Chrome浏览器返回结果如图6所示。

 

 

 

 

 

 

图6 Chrome浏览器搜索结果

打开源代码页面搜索第一个结果的标题Selenium with Python,如图7所示。

 

 

 

 

 

 

图7 搜索结果定位

在这里发现了一个比较特别的属性class="c-tools",在代码中查找这个属性,如图8所示。

 

 

 

 

 

 

图8 搜索class属性

发现共有10个结果,并且第二个搜索结果的标题和搜索页面中第二个搜索结果相同,再数一数百度搜索结果页面中总共10个结果。可以确定所有的搜索结果中都包含有class="ctools"标签,可以使用find_elements_by_class_name定位所有的搜索结果了。执行命令:

resultElements=browser.find_elements_by_class_name('c-tools')

len(resultElements)

执行结果如图9所示。

 

 

 

 

 

 

图9 定位搜索结果

这里使用的是find_elements,不是find_element。定位多个结果时用elements。

一般来说定位结果用find_element_by_xpath或find_element_by_css比较方便,如果结果中有特殊的属性,用find_element_by_class_name也挺好,哪个方便就用哪一个。

4、从位置中获取有效数据

有效数据的位置确定后,如何从位置中过滤出有效的数据呢?一般就是获取element的文字或者获取Element中某个属性值。Selenium有自己独特的方法,分别是:

element.text

element.get_attribute(name)

回到Chrome浏览器搜索结果的源代码页面,如图10所示。

 

 

 

 

 

 

图10 有效数据

所需的有效数据就是data-tools属性的值。执行命令:

value=resultElements[0].get_attribute('data-tools')

valueDic=eval(value)

print valueDic.get('title').decode('utf8')

print valueDic.get('url')

执行结果如图11所示。

 

 

 

 

 

 

图11 获取有效数据

遍历resultElements列表,可以获取所有搜索结果的title和url。至此,已将Selenium&PhantomJS爬虫运行了一遍。根据这个过程可以编写一个完整的爬虫。

你可能感兴趣的:(Python)