《selenium官方文档》读书笔记
2021-04-24 21:12:20 22 举报
AI智能生成
如果你发现requests不管用了,尝试用selenium,你会回来感谢我的。 当然,selenium还有很多高效的玩法,比如,当因为工作需要在数据平台上传大量数据的时候,使用selenium库可以自动高效地完成任务。
作者其他创作
大纲/内容
元素定位
普通定位方法
根据id
browser.find_element_by_id('idname')
根据class_name
browser.find_elements_by_class_name('dataintable')
根据name属性
browser.find_element_by_name('username')
一般登录表单中会有name且是唯一的,所以通过name会很方便的定位到相应的元素。
如上图,百度网盘的用户名和密码输入框的name属性分别为userName,password
如上图,百度网盘的用户名和密码输入框的name属性分别为userName,password
根据link
browser.find_elements_by_link_text("编程教程")
根据链接文本定位元素
browser.find_elemrnts_by_partial_text("教程")
上面两个结果是一样的
根据XPATH
browser.find_element_by_xpath()
xpath语法
html
html = etree.HTML('text')
html的层级结构
选取节点
/
绝对路径
html.xpath("/html/body/div/ul/li")
从html文档树的根目录开始,按照层级关系,一层一层解析,直至li标签,如果层级少一个,则没有结果。
绝对路径更多用于定位某个标签的子节点。
html.xpath("//ul/li")
elements = html.xpath("//ul/li")
//
相对路径【跳级】
html.xpath("//div//li")
找到div,再从div中所有后代标签中找到li标签
.
选取当前节点
例子,选取当前li节点下所有的a标签的文本。
如果用 element.xpath("//a/text()"),则会返回所有a标签,而不是当前节点的下,子节点a。
如果没有限定当前节点的情况
..
当前节点的父节点
轴
html.xpath("//ul/child::li")
ul/child::li
ul节点下所有的li子节点,
ul/parent::*
返回当前节点的父节点
ul/descendant::*
返回ul节点下所有的后代节点
ul/descendant-or-self::*
返回当前节点以及当前节点所有的后代节点
ul/ancestor::*
返回当前节点所有的祖先节点
ul/ancestor-or-self::*
返回当前节点和当前节点所有的祖先节点
ul/following::*
返回当前节点结束后,所有的节点
ul/preceding::*
返回当前节点前的所有节点
ul/preceding-sibling::*
返回当前节点的同级节点
ul/namespace::*
返回当前节点命名空间的节点
xml的命名空间
限定条件
[1]
html.xpath("//ul/li[1]")
选取ul下第一个li元素
注意第一个元素为1而不是0
[last()]
html.xpath("//ul/li[last()]")
选取ul下最后一个li元素
[position()=1]
html.xpath("//ul/li[postion()=1]")
选取位置为1的元素。
也可以选择:html.xpath("//ul/li[position()>2]")
选取位置大于2的li元素
[@class]
html.xpath("//ul/li[@class]")
选取有 class属性的li元素
[@class='item1']
html.xpath("//ul/li[@class='item1']")
选取classs属性为item1的li元素
*
html.xpath("//div//*")
选取div标签下,所有的标签
html.xpath("//div[@*]")
选取文档中所有具有属性值的标签
|
html.xpath("//li | //a")
选取所有的li标签和a标签
注意 | 不支持括号语法
比如:寻找div标签下的li标签和a标签
并不支持 html.xpath("//div(//li | //a)")这样的语法
两种解法
html.xpath("//div//li | //div//a")
html.xpath("//div")[0].xpath(".//li | .//a")
运算符
逻辑运算符
and
xml.xpath("//book/year[./text()='2003' and ../price/text()>40]/text()")
or
author = xml.xpath("//author[contains(./text(),'J') or contains(./text(),'K')]")
其他逻辑运算符可参考
常用函数
contains()
几种情况
html.xpath("//div/*[contains(./text(),'a')]")
在div所有的子节点中,节点文本中含有字符a的节点。
//div[@class="blog-content-box"]//*[contains(./text(),'函数')]
class为blog-content-box的div下所有后代标签间的文本包含“函数”字符的标签。
html.xpath("//div[contains(@class,'cm_area')]")
如图,当class有多个属性值时,使用//div[@class='cm_area ns_area_top ']并不能定位到该标签。
找不到结果。遇到这种有多个class属性,可以使用contains函数。
使用contians的结果。
xml.xpath("//book[contains(/,title)]")
不仅支持文本包含,也可以查找子标签中含有title节点的book标签
文本相关
stars-with()
//book/author[starts-with(./text(),'J')]
所有author节点文本中以J开始的节点。
string-length() 返回字符串长度
xml.xpath("//book//author[string-length(./text())>20]/text()")
查找节点文本长度超过20个的节点。
substring-after 和 substring-before
作用:返回指定字符串前/后的字符串。
substring(text,2,5)
返回字符串第2到第5位字符串。如果没有5,则是从第2到最末尾的字符串。
根据css-selector
browser.find_element_by_css_selector()
css选择器的基本语法
直接通过class/id/tag
.类名
browser.find_elements_by_css_selector(".wrapper")
选取class属性为wrapper的元素
#id名
browser.find_elements_by_css_selector("#navfirst")
选取id属性为navfirst的元素。
p 标签名
brower.find_elments_by_css_selector("table")
选取页面所有的table标签。
选择子元素
>
browser.find_elements_by_css_selecor(".dataintable >tbody>tr")
选取两个以上元素
,
browser.find_elements.by_css_selector("#navfirst,#tpn")
选取id属性为navfirst 和id属性为tpn的标签
与xpath的|类似。xpath("//*[@id='navfirst'] | //*[@id='tpn']")
选取所有后代元素
空格
browser.find_elements_by_css_selector(".dataintable tr")
选取class属性为dataintable元素所有后代元素中的tr标签。
有次序的选择后代元素
tr:nth-child(n)
.dataintable tr:nth-child(n)
如果:nth-child(2)前没有限定标签,会返回div和所有div的子标签,
分别计算各个标签【包括div】的子标签数量。
如果有第二个子标签就返回。
如果:nth-child(2)前面限定了标签。则只会返回对应的标签。
li:nth-child(2)
只返回li标签。
分别计算各个标签【包括div】的子标签数量。
如果有第二个子标签就返回。
如果:nth-child(2)前面限定了标签。则只会返回对应的标签。
li:nth-child(2)
只返回li标签。
tr:nth-of-type(n)
.box :nth-of-type(2)
注意与nth-child的区别。nth-child(2),会将所有的子标签放入容器,返回第2个子标签。
nth-of-type(2) 会将所有子标签按照不同类型放入容器中,返回不同类型标签的第2个。
nth-of-type(2) 会将所有子标签按照不同类型放入容器中,返回不同类型标签的第2个。
兄弟的后续节点
+
li+li
紧贴div标签的p标签。如果紧贴是其他标签则不定位。
[]属性选择
[attribute]
选择所有attribute属性的标签
[class]
选择所有有class 属性的标签
li[class]
选择所有有class属性的li标签
div :nth-child(n)[class]
div的子标签中有class属性的标签
[attribute=value]
选择属性值为value的标签
[class=li]
选择class属性为li的所有标签
p[class=li]
选择class属性为li的p标签
[attribute~=value]
选择属性值包含value的标签。
[class=li]只能定位到class=li 不能定位到class=li bi的标签。
[class~=li]可以定位到 class="li bi"标签。
注意:~包含是属性值,而不是属性字符串 class~=l 并不能定位到class='li'的标签
[attribute*=str]
属性值字符串中包含str的标签
如上面的问题:[class*=l] 是可以定位到 class="li "的标签的。因为*= 是根据属性值的字符串进行匹配的。li字符串 含有l
class="lo"也可以匹配。
class="lo"也可以匹配。
[attribute^=str]
类似xpath的starts-with。
如果标签属性字符串开头包含指定str,则返回该标签。
如:如 a[href^=https]
[attribute$=str]
类似xpath的ends-with
如果标签字符串结尾包含指定str,则返该标签
a[href$=asp]定位结尾有asp的a标签。
使用browser.find_elements_by_css_selector("a[href$=asp]") 的结果。
特殊tag的定位
radio
单选框定位相对来说简单一些,直接定位元素,调用click()即可。
checkbox
checkbox需要注意:
如果checkbox之前是选中状态,再次click(),又会变成未选中状态。
所有在操作CheckBox前,要将所有的CheckBox的状态变为未选中。
然后再进行对应的click操作。
如果checkbox之前是选中状态,再次click(),又会变成未选中状态。
所有在操作CheckBox前,要将所有的CheckBox的状态变为未选中。
然后再进行对应的click操作。
初始化点击
按需点击
完整代码
select
selenium 提供了一个管理select 的类Selct可以方便的操作下拉选择框和下拉多选框。使用前先导入Select类。
导入 :from selenium.webdriver.surport.ui import Select
创建select对象:select = Select(browser.find_element_by_css_selector("#ss_single"))
select对象的常用方法
selet.selet_by_value(' 小张老师')
根据option的value进行选择
select.select_by_visible_text("小张老师")
根据option的可见文本选择
select.select_by_index(0)
根据option的index来选择。需要注意两点
不支持多选。只支持单个数字输入。
起始位置是0和xpath中起始位置是1不同。
反选:
select.deselect_all()
去除所有选择
deselect_by_value('小张老师')
去除选择。value为‘小张老师’的option
deselect_by_visible_text('小张老师')
去除选择。text为小张老师的选项。
deselect_by_index(1)
去除选择第个option
一个例子
子主题
from selenium.webdriver.surport.ui import Select
webelement对象属性和方法
常用的方法
element.clear()
清除文本
element.send_keys(value)
模拟键盘输入。value为输入值
element.click()
模拟点击
element.submit()
模拟提交表单。如果有input输入框,不需要定位确认按钮,直接submit()即可。
例子模拟登录百度网盘
element.get_attribte(name)
例如:获取页面所有a标签的href属性
element.get_attribute('href')
如果获取a标签的文字可以使用
element.get_attribute('innerHTML')
如果想获取a标签的源码可以使用
element.get_attribute('outerHTML')
element.is_displayed()
元素是否可见
element.text
获取当前元素的innerText值。开始标签到结束标签内的文本内容
element.size
当前元素的大小。
element.tag_name
当前元素的tag名称
控制浏览器
创建浏览器对象
chrome = webdriver.Chrome('chromedriver.exe')
打开网址
chrome.get('http://www.baidu.com')
前进和后退
chrome.back() 后退
chrome.forword() 前进
退出
chrome.quit()
刷新浏览器
chrome.refresh()
获取窗口的title
chrome.title
获取当前url
chrome.current_url
多窗口切换和frame切换
获取窗口句柄
获取所有窗口句柄:all_windows = browser.window_handles
返回一个列表,每个元素是各个窗口的id。
获取当前窗口句柄:current_window = browser.current_window_handle
分别获取每个窗口的title。
获取title后,就可以知道操作具体的窗口。然后可以通过,browser.switch_to.window(window_handles[0]) 来切换窗口。
也可以使用,browser.switch_to.window(current_window)
browser.switch_to.frame(fame属性)
如果网页中有frame标签,无法直接定位到frame内部的元素
直接定位frame内的元素,并不能定位到。
browser.switch_to.frame('frame1')
思路:先定位到frame,然后switch_to.frame(定位方式)
定位方式
frame属性
使用find_element()
回到主页面:browser.switch_to.default_content()
鼠标和键盘事件
先导入ActionChain
from selenium.common.action_chain import ActionChains
基于浏览器对象,创建ac 实例
browser.get('http://www.baidu.com')
ac = ActionChains(browser)
定位元素
btn = browser.find_element_by_name("button")
定义事件
ac.move_to_element(btn) # 鼠标悬停
ac.context_click(btn) # 右键点击
……
ac.context_click(btn) # 右键点击
……
鼠标事件
ac.move_to_element(btn)
鼠标移动到btn元素上并悬停。
ac.click(btn)
单击
ac.context_click(btn)
右键单击
其他事件,如有需要,可参照
键盘事件
与鼠标事件不用,键盘事件不需要实例化ActionChains实例。直接使用send_keys即可。
如果想组合出ctr+A ctr + C
需要导入:from selenium.webdriver.common.keys import Keys
使用
input = browser.find_element_by_tag_name('a')
a.send_keys(Keys.CONTROL,'a')
使用ctr+a
其他键盘事件参考
执行actionchain
ac.perform()
例子
打开百度--悬停更多--悬停音乐--点击
代码
等待
加载网页需要事件,如果在加载前就执行定位操作,则会抛出找不到元素的异常。
所以要设置等待事件,等元素加载完在执行定位操作。
所以要设置等待事件,等元素加载完在执行定位操作。
设置等待的方法
time.sleep(3)
隐式等待
browser.implicitly_wait(10)
在10内,等待元素加载,如果在10秒内加载完成,则不会抛出异常。
显式等待
需要导入的模块
from selenium.webdriver.surpport.ui import WebDriverWait
from.selenium.webdrvier.surpport import expected_conditions as EC
from selenium.webdriver.common.by import By
创建WebDriverWait()实例
初始化实例的主要参数
browser
对应浏览器驱动。
timeout:5
设置最长等待时间:如果超出这个时间就会抛出异常。
poll_frequency:0.5
多少秒尝试搜索一次。每个0.5秒扫描文档一次。如果找到就停止。
ignored_exceptions
异常提示
调用until(method,value)方法,或者until_not方法
WebDriverWait(browser,5).until(kw,'未找到')
在5秒时间内,如果找到kkw就返回kkw元素,如果没找到就抛出异常。
找到的情况
子主题
没找到的情况:抛出异常!
until(method,message)的实现原理
在webdrvierwait设定的时间条件中,不断的执行method,
注意:method参数中一定要有browser,否则会报错!
如果在限定的时间条件内,method有返回值就返回这个值
如果没有就抛出异常,提示信息可以用 message 来自定义。
EC方法
expected_conditions封装了网页元素查找、可点击、是否可见等众多方法。具体可参考
EC封装的方法中,有些方法本质上是调用browser.find_element和find_elements方法。
源码
presence_of_all_elements_located
presence_of_element_located(locator)
最终会调用find_element方法。
所以在调用EC方法时,需要传递by参数。
find_element和find_elements方法
find_element(by=By.ID,value='kw')
调用EC封装的方法,本身并不会返回find_element 的结果, 而是绑定了by参数和value参数的函数。
使用时,可以直接调用,传入对应的浏览器对象。
这样做的好处,下次如果还想查找id属性为kw 的元素,就不需要在写find_element函数了,直接调用find_kw(browser) 即可。
以上结合使用,可以方便地使用显示等待。
element = WebDriverWait(browser,4,0.5).until(EC.presence_of_element_located((By.ID,'kw')) , message="kw未找到!")
其他操作可参考
0 条评论
下一页