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']/*[position()>=last()-2]
14.6 组选择和兄弟节点
14.6.1 组选择
css有组选择,可以同时使用多个表达式,多个表达式选择的结果都是要选择的元素。
(1)css和xpath的区别
css组选择,表达式之间用 逗号 隔开
xpath则是用 竖线 隔开多个表达式
#选择所有的option元素和所有的h4元素
//option|//h4
#等同于css选择器
option,h4
#选择所有的class为single_choice和class为multi_choice的元素
//*[@class='single_choice']|//*[@class='multi_choice']
14.6.2 选择父节点
某个元素的父节点用/…表示
#选择id为china的节点的父节点
//*[@id='china']/..
#继续找上层父节点
//*[@id='china']/../../..
14.6.3 选择兄弟节点
(1) xpath选择后续兄弟节点,用following-sibling::
#选择class为single_choice的元素的所有后续兄弟节点
//*[@class='single_choice']/following-sibling::*
#选择class为single_choice的元素的所有后续兄弟节点的div节点
//*[@class='single_choice']/following-sibling::div
(2) xpath选择前面的兄弟节点,用preceding-sibling::
#选择class为single_choice的元素的所有前面的兄弟节点
//*[@class='single_choice']/preceding-sibling::*
14.7 注意
xpath如果在某个WebElement里使用时,如果要选择里面的元素,前面一定要加小数点
#先寻找id是china的元素
china = wd.find_element(By.ID, 'china')
#再通过WebElement对象选择该元素内部的p元素
elements = china.find_element(By.XPATH, './/p')
文章出处登录后可见!