0%

Python爬虫工具之Selenium的概述以及使用笔记

介绍

Selenium 是一个用于web自动化测试的工具集。它的最新版本是Selenium 3.91,其中继承了Webdriver,简而言之就是一个浏览器接口,可以利用多种语言调用浏览器进行自动化的测试。
利用Selenium进行Web网页的渲染以及JS的操作,对于一些使用Ajax的网站可以进行很好的支持,可以为所欲为。
api列表:http://selenium-python.readthedocs.io/api.html
selenium官网:https://www.seleniumhq.org/

安装

在安装了pip服务的python中直接使用
pip install selenium
来进行安装。

使用

引入

在项目的开头引入WebDriver,这里,WebDirver又两种模式,一种是浏览器模式,一种是无头模式。浏览器模式会开启一个浏览器窗口进行操作,所有的操作都能被看到,但是也以为更消耗资源。无头模式不=现实窗口,在后台运行,还禁用了GPU,能大大节省资源;。

1
2
3
4
5
6
7
8
9
10
from selenium import webdriver

#无头模式
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chrome_options=chrome_options)

#浏览器模式
chrome_options = webdriver.Chrome()

如果浏览器运行错误,可能就是因为浏览器驱动没有安装好,升级到最新版本的Chrome浏览器即可。

基础操作

1
2
3
url = 'www.baidu.com'
driver.get(url)
print driver.page_source

显而易见,上面一段代码就是打开www.baidu.com,然后在控制台中打印出网页的html代码,
其中 driver.get 方法会打开请求的URL,WebDriver 会等待页面完全加载完成之后才会返回,即程序会等待页面的所有内容加载完成,JS渲染完毕之后才继续往下执行。注意:如果这里用到了特别多的 Ajax 的话,程序可能不知道是否已经完全加载完毕。
网页加载完毕后,利用page_source输出

1
2
3
elem = driver.find_element_by_name("wd")
elem.send_keys("weicheng97.cn")
elem.send_keys(Keys.RETURN)

WebDriver提供了许多寻找网页元素的方法,譬如 find_element_by_* 的方法。例如一个输入框可以通过find_element_by_name方法寻找nam 属性来确定。
然后我们输入来文本然后模拟点击了回车,就像我们敲击键盘一样。我们可以利用Keys这个类来模拟键盘输入。

页面前进后退

1
2
driver.forward()
driver.back()

emmmm,这个感觉不用多说了,很简洁明了

Cookies处理

添加 Cookies

1
2
cookie = {'name' : 'weicheng', 'value' : '97'}
driver.add_cookie(cookie)

获取Cookies

1
driver.get_cookies()

返回的将是一个list数据格式

执行js

我使用该框架的主要原因就是可以执行js。来执行某些网页上的一些代码,execute_script就可以很容易的解决这一个问题。

1
driver.execute_script("alert('在这里写上你的js代码就会在抓取的网页中执行')")

处理Alert

WebDriver提供了switch_to参数,可以跳转到网页的指定警告blablabla的内容

1
2
alert = driver.switch_to.alert
alert.accept()

在我使用中就遇到一个alert,本来想着使用按键模拟一个回车键,但是WebDirver中提供了这个操作可以处理网页中的警告

获取内容

仅仅抓取页面没有多大卵用,我们真正要做的是做到和页面交互,比如点击,输入等等。那么前提就是要找到页面中的元素。WebDriver提供了各种方法来寻找元素。例如下面有一个表单输入框。

1
<input type="text" name="passwd" id="passwd-id" />

我们可以这样获取它

1
2
3
4
element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_elements_by_tag_name("input")
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

你还可以通过它的文本链接来获取,但是要小心,文本必须完全匹配才可以,所以这并不是一个很好的匹配方式。
而且你在用 xpath 的时候还需要注意的是,如果有多个元素匹配了 xpath,它只会返回第一个匹配的元素。如果没有找到,那么会抛出 NoSuchElementException 的异常。
获取了元素之后,下一步当然就是向文本输入内容了,可以利用下面的方法

1
element.send_keys("some text")

同样你还可以利用 Keys 这个类来模拟点击某个按键。

1
element.send_keys("and some", Keys.ARROW_DOWN)

你可以对任何获取到到元素使用 send_keys 方法,就像你在 GMail 里面点击发送键一样。不过这样会导致的结果就是输入的文本不会自动清除。所以输入的文本都会在原来的基础上继续输入。你可以用下面的方法来清除输入文本的内容。

1
element.clear()

这样输入的文本会被清除。

填充表单

我们已经知道了怎样向文本框中输入文字,但是其它的表单元素呢?例如下拉选项卡的的处理可以如下

1
2
3
4
5
element = driver.find_element_by_xpath("//select[@name='name']")
all_options = element.find_elements_by_tag_name("option")
for option in all_options:
print("Value is: %s" % option.get_attribute("value"))
option.click()

首先获取了第一个 select 元素,也就是下拉选项卡。然后轮流设置了 select 选项卡中的每一个 option 选项。你可以看到,这并不是一个非常有效的方法。
其实 WebDriver 中提供了一个叫 Select 的方法,可以帮助我们完成这些事情。

1
2
3
4
5
from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_name('name'))
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

如你所见,它可以根据索引来选择,可以根据值来选择,可以根据文字来选择。是十分方便的。
全部取消选择怎么办呢?很简单

1
2
select = Select(driver.find_element_by_id('id'))
select.deselect_all()

这样便可以取消所有的选择。
另外我们还可以通过下面的方法获取所有的已选选项。

1
2
select = Select(driver.find_element_by_xpath("xpath"))
all_selected_options = select.all_selected_options

获取所有可选选项是

1
options = select.options

如果你把表单都填好了,最后肯定要提交表单对吧。怎吗提交呢?很简单

1
driver.find_element_by_id("submit").click()

这样就相当于模拟点击了 submit 按钮,做到表单提交。
当然你也可以单独提交某个元素

1
element.submit()

方法,WebDriver 会在表单中寻找它所在的表单,如果发现这个元素并没有被表单所包围,那么程序会抛出 NoSuchElementException 的异常。

页面切换

一个浏览器肯定会有很多窗口,所以我们肯定要有方法来实现窗口的切换。切换窗口的方法为switch_to_window
另外你可以使用 window_handles 方法来获取每个窗口的操作对象
使用switch_to_frame将焦点切换到一个 name 为 child 的 frame 上。

1
2
3
4
driver.switch_to_window("windowName")
for handle in driver.window_handles:
driver.switch_to_window(handle)
driver.switch_to_frame("frameName.0.child")

和BeautifulSoap联合

使用BeautifulSoup(driver.page_source, “html.parser”)读取WebDriver中抓取的Html代码。
具体说说就是另外一篇文章了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
soup = BeautifulSoup(driver.page_source, "html.parser")
table = soup.select('#Xscj1_gvcj1')
i = 0
f = open("C:\\Users\\Weicheng\\Desktop\\test.csv", 'a')
for list in table:
for td in list.findAll("tr"):
i = 0
for tr in td.findAll("td"):
i = i + 1
#处理掉一些表格的占位字符
print('"'+tr.text.replace(u'\xa0', '0')+'"', end='', file=f)
if i < 13:
print(',', end='', file=f)
else:
print('', file=f)
count = count + 1
f.close()