Web自动化 —— Selenium元素定位与防踩坑

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

driver.maximize_window()

driver.get(“https://www.jd.com”)

jd_search_input = driver.find_element(by=By.CLASS_NAME,value=“text”)

jd_search_input.send_keys(“电脑”)

jd_search_button = driver.find_element(by=By.CLASS_NAME,value=“button”)

jd_search_button.click()

driver.find_element(by=By.LINK_TEXT,value=“家用电器”).click()

driver.find_element(by=By.LINK_TEXT,value=“平板电视”).click()

当页面以一个新的页面打开时,将会出现多个句柄(就是浏览器的页面)

这个时候我们需要做的事情是切换操作句柄

句柄切换

拿到所有句柄

handlers = driver.window_handles
print(driver.title)
for h in handlers:
if h !=driver.current_window_handle:
# 切换到这个句柄上
driver.switch_to.window(h)
print(“当前句柄是:” + driver.title)

driver.find_element(by=By.PARTIAL_LINK_TEXT,value=“一体”).click()


#### 3. CSS选择器定位法一



from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
service = Service(“…/…/chomedriver.exe”)
driver = webdriver.Chrome(service=service)

把浏览器最大化

driver.maximize_window()
driver.get(“https://www.jd.com”)
driver.find_element(by=By.CSS_SELECTOR,value=“#key”).send_keys(“键盘”)
driver.find_element(by=By.CSS_SELECTOR,
value=“#search > div > div.from > button”).click()

css学习参考手册

https://www.runoob.com/cssref/css-reference.html#animation


#### 4. CSS选择器定位法二


1. 浏览器完整的打开-关闭调用流程



from selenium import webdriver #导入webdriver包

driver=webdriver.Chrome() #初始化一个谷歌浏览器实例
driver.maximize_window() #最大化浏览器
driver.implicitly_wait(8) #设置隐式时间等待

driver.get(“https://www.baidu.com”) #通过get方法打开一个url站点

driver.quit() #关闭并退出浏览器


5. xpath定位法  
 1、相对路径定位  
 //标签名[@属性名="属性值"]


2、定位某个元素的父级元素  
 元素xpath/parent::"父级元素标签名"


//\*[@id="list"]/dl/a/parent::dl


3、定位一组元素的第几个  
 xpath[数字] 注意:xpath是从1开始


例:定位第5个元素


//\*[@id="list"]/dl/a[5]


4、定位到一组元素,但是需要从第n个开始  
 xpath[position()]


例:从第13个元素开始


//\*[@id="list"]/dl/a[position()>12]


5、定位元素的属性值  
 xpath/@属性名


例:定位a标签的href属性值


//\*[@id="list"]/dl/a/@href


6、定位标签的文本内容  
 xpath/text()


例:定位dd标签的文本内容


//\*[@id="list"]/dl/a/dd/text()


6. 句柄切换和页面关闭操作  
 句柄,就是当前浏览器每个窗口的标识符,每个窗口的句柄具有唯一性,多用于页面切换与关闭指定页面;  
 接下来先做一个小实验,证明一下为啥需要用到句柄:  
 以百度新闻为例:  
![image.png](https://img-blog.csdnimg.cn/img_convert/fe97c245b79c1bb4d5f38d4b5845bd47.png)


![image.png](https://img-blog.csdnimg.cn/img_convert/15a7e863e40d7ce280c723bb945d8d5c.png)



-- coding:utf-8 --

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.set_window_size(1920, 1080)
browser.get(“http://news.baidu.com/”) #打开百度新闻页面
time.sleep(1)
handles = browser.window_handles #获取所有窗口的句柄
print(“当前窗口的句柄”,handles ) #这里输出所有窗口的句柄,当前只有一个窗口,所以输出的是当前窗口的句柄
browser.find_element_by_link_text(“百度新闻客户端”).click() #在百度新闻页面基础上(新窗口)打开百度新闻客户端页面
handles = browser.window_handles #获取所有窗口的句柄
print(“全部窗口的句柄”,handles ) #这里会输出两个句柄信息,以list的方式返回


![image.png](https://img-blog.csdnimg.cn/img_convert/bb8e95c1041abf93b1079b8b4424376d.png)


 到这里,我们怎么知道当前标记的是哪个窗口的句柄呢(就是读取哪个窗口的代码)?我们可以关闭一个窗口,如果某个窗口被关闭了,那就证明标记的是哪个窗口的句柄,在后面增加下面这行代码



browser.close() #关闭当前标识的窗口
handles = browser.window_handles #获取所有窗口的句柄
print(“全部窗口的句柄”,handles )


![image.png](https://img-blog.csdnimg.cn/img_convert/106489add2c061fedf51964a6513860c.png)


我们会发现就算打开了新的窗口,并在页面上跳转到新的窗口,但是关闭的窗口仍然是最初始的窗口,所以这就证明由始至终都是标识第一个窗口的句柄,那我们就要在进行后面一系列操作之前,先标识到新窗口的句柄


这样子,我们就可以在新窗口进行一系列的操作啦,当然,切换窗口,也可以使用重定向的方式


7. 自动化元素定位防踩坑  
 踩坑一:StaleElementReferenceException


selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document


异常原因: 意思是,引用的元素已过期。原因是页面刷新了,此时当然找不到之前页面的元素,就算是后退回来的页面也是不一样的。


![](https://img-blog.csdnimg.cn/img_convert/a4b05499661fa5ef259b1c50cd2bbd15.webp?x-oss-process=image/format,png)


在编写脚本时一直报这个错,使用显示等待都不行,在一顿百度操作后才知道是元素被刷新了


![](https://img-blog.csdnimg.cn/img_convert/53daea2321fa06d4ec120d92598decf2.webp?x-oss-process=image/format,png)


我们发现,仅仅是刷新了一下页面,两次的element id是不同的,这就说明这是两个不同的元素,如果用之前的element,自然会报错


原因很明显,你用别人的身份证id去找现在的人,哪怕这两个人长的很像,他也会告诉你,对不起,你找错人啦。


解决方法:


有时我们无法避免,不确定什么时候元素就会被刷新。页面刷新后重新获取元素的思路不变,这时可以使用python的异常处理语句:try…except…,异常出现时重新执行,关键代码如下  
![](https://img-blog.csdnimg.cn/img_convert/0e81bc9267d6ee086ee844a03328061b.webp?x-oss-process=image/format,png)


如下图:我在实际工作当中编写脚本时使用异常try捕获异常后,页面刷新后重新获取元素,可以成功找到元素了


![](https://img-blog.csdnimg.cn/img_convert/9bbc24380ecc48b17d84511cc2942a7f.webp?x-oss-process=image/format,png)


踩坑二:ElementClickInterceptedException(元素点击交互异常)


具体报错:selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted is not clickable at point (1421, 283). Other element would receive the click:


E (Session info: chrome=104.0.5112.102)


意思是,元素定位相互覆盖,元素已经找到,但是无法点击


解决方法:


方法一:使用强制等待,但是每次都有类似的元素无法点击使用强制等待的话会延长脚本执行时间


time.sleep()


前言:之前便遇到过很多次该问题的报错,就没有管它,但是随着越来越多的元素报该错,每次使用强制等待会大大延长脚本的执行时间,于是便网上找各种方法解决该问题,最终发现是自己使用显示等待的方法错了


如下是显示等待的用法和区别


方法二:显性等待


element\_to\_be\_clickable--元素是否可点击


vibility of element\_ located--元素是否可见


presence\_of\_element\_located--元素是否存在


如上:三种等待方法,最开始我一直使用的是presence\_of\_element\_located,判断元素是否存在,最终还是报错,提示元素元素点击拦截异常


element\_to\_be\_clickable--等待元素出现可以点击,便可以元素定位成功


需要先导包:



from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
复制代码



element = WebDriverWait(self.browser, 5).until(
EC.element_to_be_clickable((By.XPATH, “//input[@placeholder=‘请输入会员手机号’]”)))
element.clcik()
复制代码


![](https://img-blog.csdnimg.cn/img_convert/d0d33f0df0c7aaa5cb4656052d0c7a0f.webp?x-oss-process=image/format,png)


方法三:使用JS点击


然而有时即使已经显式等待了,却仍然会报错: ElementClickInterceptedException,这多少有点奇怪,为什么 webdriver 有时就是无法点击,我不知道,也许这和他首先执行的一些验证检查有关,反正就在这一刻,它不给你点


代码如下:



element = self.browser.find_element(By.XPATH, “(//span[@class=‘el-checkbox__inner’])[4]”)
self.browser.execute_script(“arguments[0].click();”, element)
复制代码




![img](https://img-blog.csdnimg.cn/img_convert/c239b73ac2c342d6ba718b95d918239a.png)
![img](https://img-blog.csdnimg.cn/img_convert/ee51b6af1b24e57e8a8aa2ec16f792f3.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618631832)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

-LL1XeBQI-1715888356136)]
[外链图片转存中...(img-pVr9U6mp-1715888356137)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618631832)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值