python爬虫之selenium自动化测试让你爬虫更像用户
1.6k6PYTHON网络爬虫2018-08-22

全程序自动化操作
demo效果

先科普一下selenium,这是一个用于Web应用程序测试的工具,支持多种浏览器多种语言

框架底层使用JavaScript模拟真实用户对浏览器进行操作,Selenium测试直接运行在浏览器中,代码执行时,可以自动打开浏览器/表单输入/按钮点击,就像真实用户在操作的一样

真真是反爬虫的一大神器啊

先附上文档了解一些基础知识:官方文档中文文档

关于安装

1
cmd命令:pip3 install selenium

下载谷歌驱动安装:https://sites.google.com/a/chromium.org/chromedriver/downloads 

放在谷歌文件夹C:\Program Files (x86)\Google\Chrome\Application下再把这路径加入环境变量

基础知识

Xpath是非常强大的元素查找方式,它可以定位到页面上的任意元素

我这里只介绍了一些今天这个实例会用到的

首先先了解一下它的一些语法

// : 相对路径,以这个开头表示从寻找文档的根节点开始查找元素,若出现在xpath路径中则表示寻找父节点下任意符合条件的子节点,不管嵌套了多少层级
/:绝对路径,表示寻找父节点下的第一层子元素也就是直接子元素
“//标签名[@属性名=’属性值’]”:表示从根目录查找和标签名、属性值相匹配的元素
几乎所有的Xpath路径都是以上面3种方法来组合的

精准定位

以下面这个百度文库这段html举例

shili

要获取输入框怎么写,写法不只一种哈,这地方你也可以直接使用input的id获取元素(一个页面正常来讲不会有相同的id)

input = browser.find_element(By.XPATH, “//form[@name=’ftop’]//input[@id=’kw’]”)

上面这行是用的是find_element是查找单个元素,api在下面可以先看下

表示从根目录查找第一个匹配路径 name为flop的form标签 ,找到这个元素之后再去他所有子元素里面查找id为kw的input框

假设这个页面有两个name为ftop的form标签(name一样的form标签讲道理一个页面是不会有两个现在只是假设,有可能你会遇到class名一样的div标签)

那么获取第二个form标签:”//form[@name=’ftop’][2]//input[@id=’kw’]”, 就在大括号后面加上他的索引,索引是从1开始的

模糊定位

contains关键字:input = browser.find_element(By.XPATH, “//input[contains(@id, ‘kw’)]”)
表示寻找页面中id属性值包含kw所有input元素

text关键字:input = browser.find_element(By.XPATH, “//button[contains(text(), ‘搜索’)]”)
表示寻找页面中文字中包含有搜索的所有button元素

starts-with关键字:input = browser.find_element(By.XPATH, “//a[starts-with(@href,’http://‘)]”)
表示寻找页面中href属性以http://开头的a标签

ends-with关键字:input = browser.find_element(By.XPATH, “//a[ends-with(@href,’com’)]”)
表示寻找页面中href属性以’com’结尾的a标签
关于ends-widh我在使用的时候会报错提示语法不正确而且网上关于ends-with介绍也很少所以我没有找到原因如果大家知道欢迎留言告诉我不胜感激 (´▽`ʃ♡ƪ)

这是一个简单的关于用selenium和xpath来做模糊查询的小实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
chrome_options = Options()

chrome_options.add_argument("--headless")

browser = webdriver.Chrome(chrome_options=chrome_options)

# 打开百度网址

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

# 获取第一个http链接

element_contains = browser.find_element(By.XPATH, "//a[contains(@href, 'http://')]")

print(element_contains.text)

# 获取第一个包含文字中包含'地图'的a标签
element_text = browser.find_element(By.XPATH, "//a[contains(text(), '地图')]")

print(element_text.text)

# 获取第一个文字以'贴'开头的a标签
element_starts = browser.find_element(By.XPATH, "//a[starts-with(text(), '贴')]")

print(element_starts.text)

browser.close()

selenium的一些常用api

find_element和find_elements的使用

browser.find_element(By.XPATH, ‘//button[text()=”Some text”]’)  //单个元素获取

browser.find_elements(By.XPATH, ‘//button’) //多个元素获取

ID = “id”
XPATH = “xpath”
LINK_TEXT = “link text”
PARTIAL_LINK_TEXT = “partial link text”
NAME = “name”
TAG_NAME = “tag name”
CLASS_NAME = “class name”
CSS_SELECTOR = “css selector”

单个元素选取(多个元素选取:就是在element后面加一个s,比如find_elements_by_id):

find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector

获取到标签之后的界面交互:

input.send_keys(“输入中”)  
input.clear()  清空输入框
button.click()  按钮点击

常用的控制浏览器的api:

browser.back() 浏览器后退
browser.forward() 浏览器前进
browser.get(“https://www.zhihu.com/explore") 打开页面
browser.execute_script(“alert(‘To Button’)”)  执行js代码
print(browser.window_handles) 所有的标签
browser.switch_to_window(browser.window_handles[1]) 切换到指定标签页
browser.close() 关闭当前标签页

代码实例

关于页面模块引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 引入浏览器驱动
from selenium import webdriver

# 这里我们需要引入浏览器内核才可以使用浏览器的无头模式,这里我引入的是chrome
# Gecko:是Firefox浏览器的内核
# Trident:是IE浏览器的内核
# Blink:是webkit的一个分支版本,由google开发
# 关于什么是无头模式:即headless browser,是一种没有界面的浏览器,主要是用作爬虫,用以捕捉Web上的各类数据
from selenium.webdriver.chrome.options import Options

# 主要用于使用两个私有方法find_element和find_elements
from selenium.webdriver.common.by import By

# 调用键盘api
from selenium.webdriver.common.keys import Keys

# 用于时间延迟
import time

功能代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
chrome_options = Options()

chrome_options.add_argument("--headless")

browser = webdriver.Chrome()

# 打开页面
browser.get("https://wenku.baidu.com/")

# 获取搜索输入框
input = browser.find_element(ID, 'kw')

# 输入内容
input.send_keys("IT/计算机")

# 模拟回车
input.send_keys(Keys.ENTER)

# 获取'我知道了'按钮
btn = browser.find_element(By.XPATH, "//div[@class='new-filter-box fc5']//span[@class='btn-know']")

btn.click()

time.sleep(1) # 时间延迟

# 点击列表的第一条数据
btn = browser.find_element(By.XPATH, "//div[@class='main']//dl[1]//a[1]")

btn.click()

time.sleep(4)

# 将browser页面切换至当前页面
browser.switch_to_window(browser.window_handles[1])

# 关闭当前页面
browser.close()

# 切换至第一个页面
browser.switch_to_window(browser.window_handles[0])

time.sleep(1)

# 点击列表的第二条数据
btn = browser.find_element(By.XPATH, "//div[@class='main']//dl[2]//a[1]")

btn.click()

time.sleep(4)

# 视图切换至第一个页面
browser.switch_to_window(browser.window_handles[0])

time.sleep(2)

# 去往百度页面
browser.get("https://baidu.com/")

# 打印所有标签
print(browser.window_handles)

开启无头模式
只需要修改一行代码

1
browser = webdriver.Chrome(chrome_options=chrome_options)

欢迎留言交流  (´▽`ʃ♡ƪ)