Python爬虫技术之Selenium自动化测试及模拟点击页面爬虫最全知识

Posted 熊凯瑞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python爬虫技术之Selenium自动化测试及模拟点击页面爬虫最全知识相关的知识,希望对你有一定的参考价值。

Python爬虫之Selenium

一、基础认识

1、解释

Selenium是一套Web网站的程序自动化操作解决方案(比如点击界面按钮,在文本框中输入文字等操作)

2、流程

Selenium的自动化原理如下

3、安装库

3.1 下载selenium库的命令

pip install selenium

3.2 下载谷歌浏览器Chrome对应的驱动

驱动库网址:http://chromedriver.storage.googleapis.com/index.html
注意:根据自己的Chrome版本进行选择

由于我的是103版的,那么就选103版的驱动进行下载,只要版本(比如开头的103)一样,后面的数字比如0.5060.114啥的不会造成什么影响。

3.3 样例

from selenium import webdriver
from selenium.webdriver.chrome.service import Service

#创建webDriver对象,指明使用chrome浏览器驱动
wd = webdriver.Chrome(service=Service(r'D:\\chromedriver_win32\\chromedriver.exe'))

#隐式等待,防止程序过快而网页反应不过来(10s)
wd.implicitly_wait(10)

#调用webDriver 对象的get方法,可以让浏览器打开指定网址
wd.get('http://www.baidu.com/')

注意:service里的路径’D:\\chromedriver_win32\\chromedriver.exe’也可以在电脑系统的环境变量中来配,之后直接调用即可,细节就不展开了,可以自行搜索。

4、implicitly_wait和time.sleep

wd.implicitly_wait(10)是指当找不到元素的时候才会等,如果找到了就不会等。每次调用find_element或find_elements都会判断,因此当能找到时,就用time.sleep(1)来控制时间间隔。

二、元素的选择

1、通过id来选择对应元素

1.1 解释

id属性是唯一的,所以如果元素有id,则根据id选择元素是最简单高效的方式。

1.2 样例

#根据id选择元素,返回的就是该元素对应的WebElement对象
element = wd.find_element(By.ID, 'kw')

#通过该WebElement对象,就可以对页面元素进行操作
#比如输入字符串到这个输入框里
element.send_keys('水果\\n')

#输出当前窗口的标题栏
print(wd.title)

#关闭页面退出
#wd.close()

2、根据class属性、tag名选择元素

2.1 相关方法

2.1.1 find_elements

使用find_elements选择的是符合条件的所有元素,如果没有符合条件的元素,返回空列表

2.1.2 find_elements

使用find_element选择的是符合条件的第一个元素,如果没有符合条件的元素,抛出异常

2.2 根据属性名(class_name)来选择元素

# 根据class name 选择元素,返回的是一个列表
# 里面都是class属性值为animal的元素对应的WebElement对象
elements = wd.find_elements(By.CLASS_NAME, 'animal')

print(elements)

2.3 根据标签名(tag_name)来选择元素

# 根据tag name选择元素,返回的是一个列表
# 里面都是tag名为div元素对应的WebElement对象
elements = wd.find_elements(By.TAG_NAME, 'div')
print(elements)

# 取出列表中的每个WebElement对象,打印出其text属性的值
# text属性就是该WebElement对象对应的元素在网页中的文本内容
for element in elements:
    print(element.text)

3、根据WebElement对象选择元素

3.1 解释

WebElement对象也可以调用find_elements、find_element之类的方法

3.2 作用

WebDriver对象选择元素的范围是整个web页面,而WebElement对象选择元素的范围是该元素内部

# 根据id选择元素
# 里面都是id名为container元素对应的WebElement对象
elements = wd.find_element(By.ID, 'container')

# 限制选择元素的范围id为container元素的内部
spans = elements.find_elements(By.TAG_NAME, 'span')

for span in spans:
    print(span.text)

wd.quit()

4、操控元素的基本方法

4.1 点击元素

调用元素WebElement对象的click方法(浏览器接到自动化命令,点击的是该元素中心点的位置)

#直接调用click()
a.click()

4.2 输入框

调用元素WebElement对象的send_keys方法,如果要清除输入框已经有的内容,可以用WebElement对象的clear方法

element = wd.find_element(By.ID,"input")

#清除输入框已有的字符串
element.clear()

#输入新字符串
element.send_keys('xxxx')

4.3 获取元素内容

获取元素的文本内容

element = wd.find_element(By.ID,'xxx')
print(element.text)

4.4 获取元素属性

通过WebElement对象的get_attribute方法来获取元素的属性值

element = wd.find_element(By.ID,'input_name')
print(element.get_attribute('class'))

4.5 获取整个元素对应的html

(1)要获取整个元素对应的HTML文本内容
element.get_attribute(‘outerHTML’)

(2)如果只是想获取某个元素内部的HTML文本内容
element.get_attribute(‘innerHTML’)

4.6 获取输入框里面的文字

element = wd.find_element(By.ID,"input")
#获取输入框中的文本
print(element.get_attribute('value'))

4.7 获取元素文本内容2

通过WebElement对象的text属性,可以获取元素展现在界面上的文本内容,但有时候元素的文本内容没有展示在界面上,或者没有完全展示在界面上。这时,用WebElement对象的text属性,获取文本内容,就会有问题。

element.get_attribute('innerText')

element.get_attribute('textContent')

5、CSS表达式选择元素

基础格式,通过css样式来选

element = wd.find_element(By.CSS_SELECTOR, '.plant')

print(element.get_attribute('outerHTML'))

5.1 根据tag名、id属性、class属性选择元素

5.1.1 根据tag名选择元素

根据tag名选择元素,直接写上tag名

elements = wd.find_elements(By.CSS_SELECTOR,'div')
#等价于
elements = wd.find_elements(By.TAG_NAME,'div')

注意:

#如果根据标签名来选择,比如<span>.... </span>
elements = wd.find_elements(By.CSS_SELECTOR,'span')

#对比

#如果根据样式class属性来选择,比如<a class="span">...</a>,那么前面要加'.' 
elements = wd.find_elements(By.CSS_SELECTOR,'.span')

5.1.2 根据id属性选择元素

选择元素的话,要在id号前加上一个井号:#id值

elements = wd.find_elements(By.CSS_SELECTOR,'#search')

5.2 选择子元素和后代元素

5.2.1 常用表示方法

(1)大于号’>',元素1>元素2,表示元素2是元素1的后代元素,可以有多级关系,但必须是直接子元素,不能是间接的。

#通过大于号就可以层层递进找到要的内容
elements = wd.find_elements(By.CSS_SELECTOR,'#search > qu > look > #lazy')

(2)空格分隔’ ',元素1 元素2,表示元素2在元素1的范围内,不管是否是直接子元素,间接子元素也可以。

#通过空格的判定,也可以找到对应的元素里的内容
elements = wd.find_elements(By.CSS_SELECTOR,'#search #lazy')

5.3 根据属性选择

css选择器支持通过任何属性来选择元素,语法是用一个方括号[ ]

elements = wd.find_element(By.CSS_SELECTOR,'[href]')

也可以组合限制

#表示选择所有标签名为div,且class属性为SKnet的元素
elements = wd.find_element(By.CSS_SELECTOR,'div[class='SKnet']')

5.4 验证CSS Selector

在浏览器里按CTRL + F键来检查

5.5 组合选择

5.5.1 并列(用逗号 ‘,’ 分割)

#输出的是class属性为plant和animal的值
elements = wd.find_element(By.CSS_SELECTOR,'.plant,.animal')

5.6 按照次序选择子节点

5.6.1 父元素的第n个子节点

指定选择的元素是父元素的第几个子节点,使用nth-child

#指定父元素为span的第二个子元素
elements = wd.find_element(By.CSS_SELECTOR,'span:nth-child(2)')

5.6.2 父元素倒数第几个节点

指定选择的元素是父元素的倒数第几个子节点,使用nth-last-child

#指定父元素为span的倒数第二个子元素
elements = wd.find_element(By.CSS_SELECTOR,'span:nth-last-child(2)')

5.6.3 父元素的第几个某类型的子节点

指定选择的元素是父元素的第几个某类型的子节点,使用nth-of-type

#选择的是第1个span类型的子元素
elements = wd.find_element(By.CSS_SELECTOR,'span:nth-of-type(1)')

5.6.4 奇数节点和偶数节点

如果要选择的是父元素的偶数节点,使用nth-child(even)
如果要选择的是父元素的奇数节点,使用nth-child(odd)

#选择id为t1下,属性为p的偶数节点
elements = wd.find_element(By.CSS_SELECTOR,'#t1 p:nth-of-type(even)')

5.6.5 兄弟节点选择

5.6.5.1 相邻兄弟节点选择

选择h3后面紧跟着的兄弟节点span
表示元素紧跟关系的是加号+
所以是h3+span

elements = wd.find_element(By.CSS_SELECTOR,'h3+span')
5.6.5.2 后续所有兄弟节点选择

如果要选择h3后面所有的兄弟节点span,可以这样写h3 ~ span

elements = wd.find_element(By.CSS_SELECTOR,'h3~span')

6、frame切换

6.1 解释

在html语法中,frame元素或者iframe元素的内部会包含一个被嵌入的另一份html文档,由于使用selenium打开一个网页,操纵范围是当前的html,并不包括被嵌入的html文档里的内容,如果要操作被嵌入的html文档中的元素,就必须切换操作范围到被嵌入的文档中。

6.2 用法1

wd.switch_to.frame(frame_reference),其中frame_reference可以是frame元素的属性name或id

6.2.1 样例

#切换到被嵌入文档中某个class属性
wd.switch_to.frame('frame1')

6.3 用法2

wd.switch_to.frame(frame_reference),其中frame_reference也可以填写frame所对应的WebElement对象

6.3.1 样例

wd.switch_to.frame(wd.find_element(By.TAG_NAME,'iframe'))

6.4 切换回原来的主页面

wd.switch_to.default_content()

7、切换到新的窗口

7.1 基础操作

由于需要到新的窗口操作
可以使用Webdriver对象的switch_to属性的window方法

wd.switch_to.window(handle)

WebDriver对象有window_handles属性,这是一个列表对象,里面包括了当前浏览器里面所有的窗口句柄(类似于对应窗口的一个ID)

7.2 判别新窗口的代码

#    依次获取wd.window_handles里面的所有句柄对象,并且调用wd.switch_to.window(handle)方法,
#切入到每个窗口,然后检查里面该窗口对象的属性(标题栏。地址栏),判断是不是我们要操作的那个窗口。
#如果是,就跳出循环。
for handle in wd.window_handles:
    #先切换到该窗口
    wd.switch_to.window(handle)
    #得到该窗口的标题栏字符串,判断是不是要操作的那个窗口
    if 'baidu' in wd.title:
        #如果是,那么这时候WebDriver对象就是对应的该窗口,正好跳出循环
        break

7.3 切换到原来的窗口

进入新窗口操作完后,回到原来窗口,可以先保存老窗口句柄

#mainWindow变量保存当前窗口的句柄
mainWindow = wd.current_window_handle

#...等等操作代码....

#切换新窗口操作完后,将driver对应的对象返回到原来的窗口
wd.switch_to.window(mainWindow`)

8、radio选择框(单选框)

radio框直接用WebElement的click方法,模拟用户点击就可以了。

#获取当前选中的元素
element = wd.find_element(By.CSS_SELECTOR,'#radio input[checked = checked]')
print('当前选中的是:' + element.get_attribute('value'))

#点击选择
wd.find_element(By.CSS_SELECTOR,'#radio input[value = "学院"]').click()

print('现在选中的是:' + element.get_attribute('value'))

9、checkbox框(多选框)

对checkbox进行选择,也是直接用WebElement的click方法,模拟用户点击选择。

9.1 思路

先把已经选中的选项全部点击一下,确保都是未选中状态,再点击想要选择的选择框。

9.2 实现代码

#先把已经选中的选项全部点击一下
elements = wd.find_elements(By.CSS_SELECTOR, '#checkbox input[checked = "checked"]')

for element in elements:
    element.click()
    
wd.find_element(By.CSS_SELECTOR, '#checkbox input[value = '学院']').click()

10、select框

10.1 相关方法

10.1.1 根据选项的value属性值,选择元素

#例如页面里<option value="foo">Bar</option>
s.select_by_value('foo')

10.1.2 根据选项的次序(从1开始),选择元素

#例如页面里<option value="foo">Bar</option>
s.select_by_index(1)

10.1.3 根据选项的可见文本,选择元素

#例如页面里<option value="foo">Bar</option>
s.select_by_visible_text('Bar')

10.1.4 根据选项的value属性值,去除选中元素

deselect_by_value

10.1.5 根据选项的次序,去除选中元素

deselect_by_index

10.1.6 根据选项的可见文本,去除选中元素

deselect_by_visible_text

10.1.7 去除选中所有元素

deselect_all

10.2 Select单选框

直接用Select方法选择

#导入Select类
from.selenium.webdriver.support.ui import Select

#创建Select对象
select = Select(wd.find_element(By.ID,"single"))

#通过Select对象选中
select.select_by_visible_text("学院")

10.3 Select多选框

可以用select类的deselect_all方法,清除所有已经选中的选项,然后通过select_by_visible_text方法选择

#导入Select类
from.selenium.webdriver.support.ui import Select

#创建Select对象
select = Select(wd.find_element(By.ID,"multi"))

#清除所有已经选中的选项
select.deselect_all()

#选择对应选项
select.select_by_visible_text("学院1")
select.select_by_visible_text("学院2")

11、其他操作元素的方法

ActionChains类里面提供了一些特殊动作的模拟。

11.1 使用ActionChains来模拟鼠标移动

from selenium.webdriver.common.action_chains import ActionChains

#初始化对象
ac = ActionChains(wd)

#鼠标移动到元素上
ac.move_to_element(
    wd.find_element(By.CSS_SELECTOR,'[name="briicon"]')
).perform()

12、冻结界面

在开发者工具栏console里面执行如下js代码

#冻结界面5秒
setTimeout(function()debugger,5000)

13、弹出框处理

13.1 Alert弹出框

模拟用户点击OK按钮

#---alert----
driver.find_element(By.ID,'b1').click()

#打印弹出框提示信息(获取弹出对话框的文本)
print(driver.switch_to.alert.text)

#点击OK按钮
driver.switch_to.alert.accept()

13.2 Confirm

Confirm弹出框,主要是让用户确认是否要进行某个操作

13.2.1 点击OK按钮

driver.switch_to.alert.accept()

13.2.2 点击Cancel按钮

driver.switch_to.alert.dismiss()

13.2.3 样例

#---confirm----
driver.find_element(By.ID,'b1').click()

#打印弹出框提示信息(获取弹出对话框的文本)
print(driver.switch_to.alert.text)

#点击OK按钮
driver.switch_to.alert.accept()

driver.find_element(By.ID,'b2').click()

#点击取消按钮
driver.switch_to.alert.dismiss()

13.3 Prompt

13.3.1 基础知识

出现Prompt弹出框是需要用户输入一些信息,提交上去

driver.switch_to.alert.send_keys()

13.3.2 实例

#获取alert对象
alert = driver.switch_to.alert

#打印弹出框提示信息
print(alert.text)

#输入信息,并且点击OK按钮提交
alert.send_keys('web自动化 - selenium')
alert.accept()

#点击Cancel按钮取消
driver.find_element(By.ID,'b3').click()
alert = driver.switch_to.alert
alert.dismiss()

13.4 注意

有些弹窗并非浏览器的alert窗口,而是html元素,这种对话框,只需要通过之前介绍的选择器选中并进行相应的操作。

14、xpath选择元素

14.1 绝对路径选择

Xpath路径以正斜杠(/)开始,就表示从根节点开始,从根节点开始的路径表达式,就是某元素的绝对路径。

xpath表达式  /html/body/div  等价于  css表达式里的 html>body>div

如果要使用Xpath来选择web元素,应该调用WebDriver对象的方法
find_element(By.XPATH, ‘XX’)
或者
find_elements(By.XPATH, ‘XX’)

elements = driver.find_elements(By.XPATH,'/html/body/div')

14.2 相对路径选择

如果要选择某个元素,不管它的位置,那么如果用css表达式,直接写一个div就可以了,如果用xpath,那么xpath需要前面加//,表示从当前节点往下寻找所有的后代元素,不管它在什么位置,则写成//div。

#选择div元素里面的所有的p元素
elements = driver.find_elements(By.XPATH,'//div//p')

14.3 通配符

如果要选择所有div节点的所有直接子节点,可以使用表达式//div/*,是一个通配符,对应任意节点名的元素,等价于css选择器div>

elements = driver.find_elements(By.XPATH,'//div/*')
for element in elements:
    print(element.get_attribute('outerHTML'))

14.4 根据属性选择

14.4.1 用法

根据属性来选择元素,是通过[@属性名 = ‘属性值’]

14.4.2 注意

属性名前有@
属性值一定要用引号,可以是单引号,也可以是双引号

14.4.3 根据id属性选择

选择id为west

//*[@id='west']

14.4.4 根据class属性选择

选择所有div元素中class为single_choice的元素

//div[@class='single_choice']

如果一个元素class有多个

//p[@class="capital huge-city"]

14.4.5 css选择属性值包含某个字符串的元素

#选择a节点,里面的href属性包含了beian字符串
a[href*="beian"]

14.4.6 选择属性值以某个字符串开头的元素

#选择a节点,里面的href属性以http开头
a[href^="beian"]

14.4.7 选择属性值以某个字符串结尾的元素

#选择a节点,里面的href属性以gov.cn结尾
a[href$="gov.cn"]

14.4.8 属性值包含字符串

#选择style属性值包含color字符串的页面元素
//*[contains(@style,'color')]

#选择style属性值以color字符串开头的页面元素
//*[starts-with(@style,'color')]

14.5 按次序选择

xpath也可以根据次序选择元素。语法比css更简洁,直接在方括号中使用数字表示次序

14.5.1 某类型第几个子元素

#选择p类型第2个的子元素
//p[2]

#选取父元素为div中的p类型第2个子元素
//div/p[2]

14.5.2 第几个子元素

#选择父元素为div的第2个子元素
//div/*[2]

14.5.3 某类型 倒数第几个子元素

last( )本身代表最后一个元素
last( )-1本身代表倒数第2个元素

#选取p类型倒数第1个子元素
//p[last()]

#选择p类型倒数第2个子元素
//p[last()-1]

#选择父元素为div中p类型倒数第二个子元素
//div/p[last()-2]

14.5.4 范围选择

xpath还可以选择子元素的次序范围

#选取option类型第1到2个子元素
//option[position()<=2]
//option[position()<3]

#选择class属性为multi_choice的前3个子元素
//*[@class='multi_choice']/*[position()<=3]

#选择class属性为multi-choice的后3个子元素
//*[@class='multi_choice'以上是关于Python爬虫技术之Selenium自动化测试及模拟点击页面爬虫最全知识的主要内容,如果未能解决你的问题,请参考以下文章

Python - 爬虫之Selenium

Python - 爬虫之Selenium

Python爬虫之Web自动化测试工具Selenium&&Chrome handless

python之爬虫 Selenium库的使用

python爬虫从入门到放弃之 Selenium库的使用

python爬虫从入门到放弃之 Selenium库的使用