第二节、自动化第一步之元素定位方式
元素定位注意事项
1、操作单个确定的元素,必须保持表达式唯一定位
2、操作一组元素的时候,你必须保证自己的表达式能且仅能匹配到要操作的元素,即不多不少
3、selenium没有提供判断元素是否存在的方法,且在找不到元素的时候就直接报错了,所以可以用匹配元素列表的方式判断,即根据表达式匹配元素列表,判断列表是否为空若列表为空,则元素不存在,若列表不为空,则元素存在。
4、写自动化的时候,为了便捷,虽然浏览器可以提供css和xpath定位代码供我们复制使用,但是一定要人工确认和优化一下,因为主要一点是,一些js等动态生成的元素,下次访问时,复制的基于下标等方式的定位代码可能会失效或者不准确,且无法维护。
推荐的元素定位优先级
优先级最高:ID
优先级其次:name
优先级再次:CSS Selector
优先级最次:Xpath
link_text、class_name、tag_name 基本不用
为什么优先选择css?
1、css是配合HTML工作的,css的实现原理是匹配对象; xpath是配合xml工作的,xpath的实现原理是遍历
2、大部分人认为css的语法更加简洁明了
3、前端开发主要用的是css,不使用xpath
from selenium import webdriver
driver = webdriver.Chrome('driverpath')
其中,Chrome可以是其他浏览器,driverpath是使用的浏览器对应驱动地址
方法都是driver实例的方法
一、匹配单个元素
1、find_element_by_id 根据属性id定位,只返回匹配到的第一个元素,找不到就报错
2、find_element_by_name 根据属性name定位,只返回匹配到的第一个元素,找不到就报错
3、find_element_by_xpath 根据元素地址xpath定位,只返回匹配到的第一个元素,找不到就报错 ,xpath(ctrl+s可以打开谷歌浏览定位xpath的元素)属于万能的匹配,没有xpath找不到的元素,但是需要优化,而且慢,例如如下两种
/html/body/div[4]/div/div[1]/section/div/div[3]/div[1]/div/p[1]
//*[@id="content-area"]/div/div[3]/div[1]/div/p[1]
4、find_element_by_css_selector 根据css表达式css_selector定位,只返回匹配到的第一个元素,找不到就报错
5、find_element_by_link_text 根据链接文本(超链接的的文本)匹配,是全匹配,即链接对应文本的完整文本,不支持模糊定位
6、find_element_by_partial_link_text 根据链接文本(超链接的的文本)匹配,支持模糊匹配,即链接对应文本的完整文本
7、find_element_by_tag_name 根据属性tag_name (span)定位,只返回匹配到的第一个元素,找不到就报错
8、find_element_by_class_name 根据class_name定位,只返回匹配到的第一个元素,找不到就报错。class_name 有复合名称,当为复合名称取其中一个即可
二、匹配元素列表,返回匹配到的所有的元素列表,如果不存在,返回空列表
find_elements_by_class_name
find_elements_by_css_selector
find_elements_by_id
find_elements_by_link_text
find_elements_by_name
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_xpath
三、短匹配
from selenium.webdriver.common.by import By
ele = driver.find_elements(By.TAG_NAME, 'a')
find_element 单元素
find_elements 元素列表
这里不一定一定用BY里边的,可以直接用字符串,因为映射关系如下
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"
所以可以使用:
ele = driver.find_elements"tag name", 'a')
四、分步定位,先找到父级标签元素,再在父级标签种找需要的元素
p_ele = driver.find_element_by_class_name('mod-text-content')
s_ele = p_ele.find_element_by_tag_name('p')
五、iframe切换
内嵌网页需要切换到内部才能定位
想要切换 iframe,首先定位到它
ifa = driver.find_element_by_css_selector("iframe:nth-child(3)")
找到之后,就可以去切换了
driver.switch_to.frame(ifa)
切回到主页面
driver.switch_to.default_content()
六、 多个标签页
获取当前所有的标签页的句柄 # 句柄,就是操作系统中的 唯一资源标识符
all_handles = driver.window_handles
for handle in all_handles:
driver.switch_to.window(handle) # 切换标签页
if driver.title == "目标标签页的标题":
break
七、JS定位
上面的定位方式基本够用了,但是有的时候就是会出现一些诡异的定位失效或者定位到了点击失效的问题,这个时候如果用js进行直接执行该事件,往往就可以解决那些诡异的事情~
id定位:document.getElementById()
name定位:document.getElementsByName()
tag定位:document.getElementsByTagName()
class定位:document.getElementsByClassName()
css定位:document.querySelectorAll()
其中只有id对象用的是Element返回是单个对象,其他都是Elements返回的是一个list这点千万要注意,具体用法和上面的webdriver基础定位一样。先写好对应的js语句,可以先赋值给一个变量,然后后调用execute_script进行执行一下js就好了,下面还是结合那个百度搜索的栗子,我写的脚本,可以对应学习实验一下:
search_js = "document.getElementsByName('wd')[0].value='selenium';"
search_js2 = "document.querySelectorAll('.s_ipt')[0].value='selenium';"
button_js = "document.getElementById('su').click();"
button_js2 = "document.getElementsByClassName('s_btn')[0].click()"
driver.execute_script(search_js2)
driver.execute_script(button_js2)
八、jQuery定位
据说会jQuery定位的在定位的路上就是披襟斩棘,所向披靡如此超神的定位,还是可以了解一下的
jQuery语法是为HTML元素的选取编制的,可以对元素执行一些具体的操作
基础语法是$(selector).action()
$符号定义jQuery,selector选择器用来查询具体的HTML元素,通过action()来执行对元素的具体操作。
其中我们经常用到的action()在jq中有这么几种:
$(selector).val('input_value') 其中input_value表示要输入的文本的值
$(selector).val('') 如果为空,则执行后是清空的意思
$(selector).click() 行为也是肯定有的
让我们结合百度的栗子看一下,用jQuery的写法和js有一点点的类似,但明显简洁多了:
search_jq = "$('#kw').val('selenium')"
button_jq = "$('.s_btn').click()"
driver.execute_script(search_jq)
driver.execute_script(button_jq)
其中js 和jQuery整理自(https://blog.csdn.net/qq_32897143/article/details/80383502)

浙公网安备 33010602011771号