Selenium Locating
Feb 26th, 2020 - Now
根据xxx查找元素
在浏览器上查找一处元素,使用 webdriver.find_element_by_xxx
的形式,具体而言有如下几种(按照自己的使用频率排序):
find_element_by_xpath()
原称之为最强大最傻瓜式的查找方式,一招毙命,实在想不到为什么还有其他的方式存在(误
在 chrome 中定位到想要的对象,右键 copy->copy full XPath 作为参数即可
这里注意 copy 中有两个选择,一个是 copy XPath 一个是 copy full XPath
由于有一些网页上可能会存在除了功能什么都一样的元素,如:一个搜索框搜索 Project,一个搜索框搜索 Owner
这时候使用单纯的 copy XPath 可能两者是一样的,都是 xxx_search ,这就导致会去定位第一个找到的搜索框
所以 copy full XPth 是最保险的选择,直接返回从 html 开始的 XPath
e.g. copy XPath->//*[@id="rightmenu"]/ul[2]/li[2]
copy full XPath->/html/body/div[3]/ul[2]/li[2]
那么为什么还需要其他方式呢?自己想了两点: 1. 查找一类元素,如爬贴吧的每个分类里面的帖子,肯定就不能每次定位一个确切的 XPath 了,而是要根据 class 或者 tag 找到一个 list 然后逐个爬取。 2. 效率慢,XPath 是直接逐级往下进行查找,每次查找(估计)都要将里面的所有tag整理出来,导致进度缓慢。
find_element_by_css_selector()
首先看懂 CSS 语句:
<div id='inner'>呵呵呵</div> : <type> 是 <div>,其 <id> 为 'inner'
<a href='http://www.baidu.com'>百度一下</a> : <type> 是 <a>,其中有个 [href] 的属性值是 'http://www.baidu.com'
<li class='two three four'>Two</li> : <type> 是 <li>,其属于 'two' 'three' 'four' 三种 <class>
基本CSS选择器
选择器
描述
举例
*
通配选择器,选择所有的元素
*
<type>
选择特定类型的元素,支持基本HTML标签
h1
.<class>
选择具有特定class的元素。
.class1
<type>.<class>
特定类型和特定class的交集。 直接将多个选择器连着一起表示交集
h1.class1
#<id>
选择具有特定id属性值的元素
#id1
属性选择器
选择器
描述
举例
[attr]
选取定义attr属性的元素,即使该属性没有值
[placeholder]
[attr="val"]
选取attr属性等于val的元素
[placeholder="请输入关键词"]
[attr^="val"]
选取attr属性开头为val的元素
[placeholder^="请输入"]
[attr$="val"]
选取attr属性结尾为val的元素
[placeholder$="关键词"]
[attr*="val"]
选取attr属性包含val的元素
[placeholder*="入关"]
[attr~="val"]
选取attr属性包含多个空格分隔的属性,其中一个等于val的元素
[placeholder~="关键词"]
关系选择器
选择器
描述
举例
<selector> <selector>
第二个选择器为第一个选择器的后代元素 选取第二个选择器匹配结果
.class1 h1
<selector> > <selector>
第二个选择器为第一个选择器的直接子元素 选取第二个选择器匹配结果
.class1 > *
<selector> + <selector>
第二个选择器为第一个选择器的兄弟元素 选取第二个选择器的下一兄弟元素
.class1 + [lang]
<selector> ~ <selector>
第二个选择器为第一个选择器的兄弟元素 选取第二个选择器的全部兄弟元素
.class1 ~ [lang]
联合选择器与反选择器
选择器
描述
举例
<selector>,<selector>
属于第一个选择器的元素 或者是属于第二个选择器的元素
h1, h2
:not(<selector>)
不属于选择器选中的元素
:not(html)
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_tag_name()
find_element_by_class_name()
find_element_by_name()
find_elements_by_xxx()
每种方法还有对应的 find_elements_by_xxx
的查找多元素的方法,可以找到整个html页面中满足搜索条件的元素并返回一个 list[]。
查找元素是否存在
有两种方法:
1. 通过 find_elements_by_xxx()
寻找并返回一个数组,如果数组长度为0则没有找到
2. 通过 find_element_by_xxx()
是否抛出异常来判断是否存在
无法找到元素
找不到自己想要的元素的时候可以通过:
elements = b.find_elements_by_xxx() # 注意是 elements
for i in elements:
print(elements)
print(elements.text)
来寻找所有有 xxx 属性的元素,检查自己的元素是否在内,如果元素都不在内,说明很大问题,接着下面。
特殊样式的查找
iframe 框架
查看要寻找的元素前后,是否存在一个 <iframe>
的东西,如果是,可能就是被 iframe 阻挡了.
也就是说,当前你的 browser 只能看到一个最外部的框架,可能可以读到 iframe,但是 iframe 内部的内容被遮挡了,这种框架通常出现在SAP系统,QQ邮箱等地方。 解决方法:
driver.switch_to_frame('iframe标签的name或id') (*)
driver.find_element_by_xxx('what u need')
通过加一个 switch_to_frame()
的方式就可以进入到框架内去查找了。
嵌套 iframe
嵌套:f1中嵌套着f2
driver.switch_to_frame("f1")
driver.switch_to_frame("f2")
退出 iframe
# 第一种方式:跳出所有iframe,回到主界面
driver.switch_to_default_content()
# 第二种方式:回到f1(返回上一级)
driver.switch_to.parent_frame()
table 类
对于表格而言,我们是难以直接定位到里面的元素的,因为可能一个 <table>
中的多个 <td>
或 <tr>
都没有id,只有顺序,所以这个时候我们要先定位到 <table>
然后根据当前的 <table>
定位查找其子元素。
# 定位到table,并获得table中所有得tr元素
menu_table = self.driver.find_element_by_xpath("xxx/table")
rows = menu_table.find_elements_by_tag_name('tr')
# python 的len()函数返回对象(字符、列表、元组)的长度或者元素得个数
before_add_numbers = len(rows)
print(before_add_numbers)
pos=0 # 正确点个数
neg=0 # 错误点个数
# 等待测试点的表出现
element = wait.until(
EC.presence_of_element_located((
By.XPATH, '//*[@id="app"]/div[2]/div/div/div/div[2]/div[1]/div/table')))
# 获取测试点的表
menu_table=b.find_element_by_xpath(
'//*[@id="app"]/div[2]/div/div/div/div[2]/div[1]/div/table')
rows=menu_table.find_elements_by_tag_name('tr')
# 对表的每一行进行遍历
for ii in rows:
tds=ii.find_elements_by_css_selector('tr td pre') # 根据css深层定位
for j in tds:
# 正确加一个
if j.text=='ACCEPTED': # j.text 就是元素的文字
pos += 1
elif j.text=='WRONG ANSWER':
neg += 1
Reference
Last updated
Was this helpful?