转载 白月黑羽大佬的博客 + 本人对一些问题的收集
白月黑羽
个人博客
https://www.byhy.net/tut/auto/selenium/01/
Selenium 简介
https://www.bilibili.com/video/BV1Z4411o7TA/?spm_id_from=333.999.0.0&vd_source=d171c31a396363b8ea8c0e92a59cee6b
Selenium自动化环境安装
https://www.bilibili.com/video/BV1Z4411o7TA/?p=2&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
简单示例
https://www.bilibili.com/video/BV1Z4411o7TA?p=3&vd_source=d171c31a396363b8ea8c0e92a59cee6b
在不加断点的前提下, 防止程序结束
# 防止闪退
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
driver = webdriver.Chrome(r'F:\chromedriver.exe', options=option)
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
# 指定驱动
service = Service(r'F:\chromedriver.exe')
wd = webdriver.Chrome(service=service, )
#
wd.get('https://www.baidu.com')
# 放一个input(), 拒绝程序运行完自动结束
input()
选择元素的基本方法
https://www.bilibili.com/video/BV1Z4411o7TA?p=4&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA?p=5&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA?p=6&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA?p=8&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
# 指定驱动
service = Service(r'F:\chromedriver.exe')
wd = webdriver.Chrome(service=service, )
# 调用webdriver对象的get方法, 打开指定网址
wd.get('https://www.byhy.net/_files/stock1.html')
# 根据id选择元素, 返回的就是改元素对应的webElement对象
ele = wd.find_element(by=By.ID, value='kw')
# 通过该webElement对象, 就可以对页面元素进行操作了
# 传入关键字到输入框
ele.send_keys('通讯\n') # \n 就相当于是回车, 或者不输入\n, 等于对element单击
ele = wd.find_element(by=By.ID, value='go')
ele.click()
pass
# 放一个input(), 拒绝程序运行完结束
input()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
# 指定驱动
service = Service(r'F:\chromedriver.exe')
wd = webdriver.Chrome(service=service, )
# 调用webdriver对象的get方法, 打开指定网址
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
# 根据class_name = animal, 定位到元素
eles = wd.find_elements(by=By.CLASS_NAME, value='animal')
for ele in eles:
print(ele.text)
# 根据元素标签span, 定位到内容
eles = wd.find_elements(by=By.TAG_NAME, value='span')
for ele in eles:
print(ele.text)
pass
# 放一个input(), 拒绝程序运行完结束
input()
在element内, 寻找元素
# 限制选择元素的范围是 id为container
ele = wd.find_element(by=By.ID, value='container') # type: WebElement
# 寻找container内的span
eles = ele.find_elements(by=By.TAG_NAME, value='span')
for i in eles:
print(i.text)
selenium4 选择函数的写法
https://www.bilibili.com/video/BV1Z4411o7TA?p=7&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
等待元素出现
https://www.bilibili.com/video/BV1Z4411o7TA?p=9&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
# 后续在做`find_element`和`find_elements`操作的时候, 如果找不到元素,
# 每隔半秒钟再去界面上查看一次, 直到找到该元素, 或者过了10秒最大时长
wd.implicitly_wait(10)
wd.get('https://www.byhy.net/_files/stock1.html')
ele = wd.find_element(by=By.ID, value='kw')
ele.send_keys('通讯\n')
ele = wd.find_element(by=By.ID, value='1')
print(ele.text)
操控元素的基本方法
https://www.bilibili.com/video/BV1Z4411o7TA/?p=10&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
- 单击
element.click()
- 输入框
element.send_keys()
清除原来的输入, 使用element.clear()
wd.get('https://www.byhy.net/_files/stock1.html')
ele = wd.find_element(by=By.ID, value='kw')
ele.send_keys('通讯\n')
time.sleep(1)
ele.clear()
ele.send_keys('科技\n')
- 获取元素信息
ele = wd.find_element(by=By.ID, value='1')
print(ele.text) # 打印出网页上的 文本
print(ele.get_attribute('class')) # 打印出tag里面的class name
- 获取整个元素对应的HTML
ele = wd.find_element(by=By.ID, value='1')
print(ele.get_attribute('outerHTML')) # 获取元素外部的HTML
print('*' * 30)
print(ele.get_attribute('innerHTML')) # 获取元素内部的HTML
- 获取输入框里面的文字
text
无法获得在input框中已经输入的内容, 需要通过element.get_attribute(‘value’)实现
ele = wd.find_element(by=By.ID, value='kw')
ele.send_keys('hello')
print(ele.text)
print(ele.get_attribute('value'))
通过WebElement对象的 text 属性,可以获取元素 展示在界面上的 文本内容。
但是,有时候,元素的文本内容没有展示在界面上,或者没有完全完全展示在界面上。 这时,用WebElement对象的text属性,获取文本内容,就会有问题。
出现这种情况,可以尝试使用 element.get_attribute(‘innerText’) ,或者 element.get_attribute(‘textContent’)
使用 innerText 和 textContent 的区别是,前者只显示元素可见文本内容,后者显示所有内容(包括display属性为none的部分)
css表达式 - 上
https://www.bilibili.com/video/BV1Z4411o7TA/?p=11&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA/?p=12&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA/?p=13&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA/?p=14&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
根据tag, id, class选择元素
- 根据class定位元素 ->
.
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
ele = wd.find_element(by=By.CLASS_NAME, value='plant')
ele2 = wd.find_element(by=By.CSS_SELECTOR, value='.plant') # 效果同上
print(ele.text, ele2.text)
- 根据tag
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
eles = wd.find_elements(by=By.CSS_SELECTOR, value='span')
for i in eles:
print(i.get_attribute('outerHTML'))
- 根据id定位元素 ->
#
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')
ele = wd.find_element(by=By.CSS_SELECTOR, value='#searchtext')
print(ele.get_attribute('outerHTML'))
选择子元素和后代元素
- 选择子元素
eles = wd.find_elements(by=By.CSS_SELECTOR, value='.plant > span')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
- 选择后代元素
eles = wd.find_elements(by=By.CSS_SELECTOR, value='.plant span')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
- 多重限制
eles = wd.find_elements(by=By.CSS_SELECTOR, value='#container #inner11 > span')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
根据属性选择
- css 选择器支持通过任何属性来选择元素,语法是用一个方括号 [].
eles = wd.find_elements(by=By.CSS_SELECTOR, value='[href="http://www.miitbeian.gov.cn"]')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
# 由于目标网页中只有一个href属性, 所以可以直接找href, 同上的效果
eles = wd.find_elements(by=By.CSS_SELECTOR, value='[href]')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
- 根据 标签+属性
- 当然,前面可以加上标签名的限制,比如 div[class=‘SKnet’] 表示 选择所有 标签名为div,且class属性值为SKnet的元素。
- 属性的模糊查询
- CSS 还可以选择 属性值 包含 某个字符串 的元素, 比如, 要选择a节点,里面的href属性包含了 miitbeian 字符串,就可以这样写
eles = wd.find_elements(by=By.CSS_SELECTOR, value='a[href*="miitbeian"]')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
- 指定开头
- 还可以 选择 属性值 以某个字符串 开头 的元素 a[href^=“http”]
- 根据多个属性
- 如果一个元素具有多个属性 CSS 选择器 可以指定 选择的元素要 同时具有多个属性的限制,像这样 div[class=misc][ctype=gun]
css表达式下
https://www.bilibili.com/video/BV1Z4411o7TA/?p=16&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA/?p=17&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA/?p=18&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
https://www.bilibili.com/video/BV1Z4411o7TA/?p=19&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
组选择
.plant , .animal
wd.get('https://cdn2.byhy.net/files/selenium/sample1a.html')
eles = wd.find_elements(by=By.CSS_SELECTOR, value='#t1 > span, #t1 p') # 选择`t1`里面所有的span和p标签
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
按照次序选择
- 父元素的第n个子节点
span:nth-child(2)
-> 类型是span
, 同时是父元素的第二个子结点 - 父元素的倒数第n个子节点
p:nth-last-child(1)
-> 倒数第一个子结点类型是p
- 父元素的第几个某类型的子节点
span:nth-of-type(1)
-> 父元素的第一个span结点 - 父元素的倒数第几个某类型的子节点
p:nth-last-of-type(2)
-> 父元素的倒数第二个p
标签 - 奇数节点和偶数节点
p:nth-child(even)
p:nth-child(odd)
# 选择t1下的所有奇数结点
wd.get('https://cdn2.byhy.net/files/selenium/sample1a.html')
eles = wd.find_elements(by=By.CSS_SELECTOR, value='#t1 :nth-child(odd)')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
# 选择t1下的p类型的偶数结点
eles = wd.find_elements(by=By.CSS_SELECTOR, value='#t1 p:nth-of-type(even)')
兄弟节点选择
- 相邻兄弟节点选择 -> h3 后面紧跟着的兄弟节点 span。这就是一种 相邻兄弟 关系,可以这样写
h3 + span
- 后续所有兄弟节点选择 -> 选择 h3 后面所有的兄弟节点 span,可以这样写
h3 ~ span
frame切换/窗口切换
https://www.bilibili.com/video/BV1Z4411o7TA/?p=20&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
如果我们要 操作 被嵌入的 html 文档 中的元素, 就必须 切换操作范围 到 被嵌入的文档中。
使用 WebDriver 对象的 switch_to 属性,像这样 wd.switch_to.frame(frame_reference)
其中, frame_reference 可以是 frame 元素的属性 name 或者 ID 。
wd.switch_to.frame('frame1')
, wd.switch_to.frame('innerFrame')
也可以填写frame 所对应的 WebElement 对象
wd.switch_to.frame(wd.find_element(By.TAG_NAME, "iframe"))
如果我们已经切换到某个iframe里面进行操作了,那么后续选择和操作界面元素 就都是在这个frame里面进行的。
这时候,如果我们又需要操作 主html(我们把最外部的html称之为主html) 里面的元素了呢?
怎么切换回原来的主html呢?
很简单,写如下代码即可
wd.switch_to.default_content()
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')
# 格局iframe的id切换进入iframe
# wd.switch_to.frame('frame1')
# 根据iframe标签里面的src属性 切换进入iframe
wd.switch_to.frame(wd.find_element(by=By.CSS_SELECTOR, value='[src="sample1.html"]'))
eles = wd.find_elements(by=By.CSS_SELECTOR, value='.plant')
for ele in eles:
print('-------------')
print(ele.get_attribute('outerHTML'))
# 切换到外层html
wd.switch_to.default_content()
# 打印外部的element
ele = wd.find_element(by=By.ID, value='outerbutton')
print(ele)
切换到新窗口
https://www.bilibili.com/video/BV1Z4411o7TA/?p=21&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
可以使用Webdriver对象的switch_to属性的 window方法
wd.switch_to.window(handle)
其中,参数handle需要传入什么呢?
WebDriver对象有window_handles 属性,这是一个列表对象, 里面包括了当前浏览器里面所有的窗口句柄。
# 获得所有窗口的句柄, 遍历每一个句柄, 根据title属性来判断并进入该窗口句柄
for handle in wd.window_handles:
# 先切换到该窗口
wd.switch_to.window(handle)
# 得到该窗口的标题栏字符串,判断是不是我们要操作的那个窗口
if 'Bing' in wd.title:
# 如果是,那么这时候WebDriver对象就是对应的该该窗口,正好,跳出循环,
break
为了保留原来的句柄变量
# mainWindow变量保存当前窗口的句柄
mainWindow = wd.current_window_handle
# 通过前面保存的老窗口的句柄,自己切换到老窗口
wd.switch_to.window(mainWindow)
实例
wd.get('https://www.byhy.net/tut/auto/selenium/frame/')
ele = wd.find_element(by=By.CSS_SELECTOR, value='a[href="https://cdn2.byhy.net/files/selenium/sample3.html"]')
ele.click()
# 如果后续还需要切换到主窗口操作, 可以先将window句柄保存下来
main_window_handle = wd.current_window_handle
# 通过handle的检查, 进入`白月黑羽的测试网页`窗口, 进行操作
for handle in wd.window_handles:
wd.switch_to.window(handle)
if '白月黑羽测试网页' in wd.title:
break
# 获得这个窗口的句柄
main_window_handle_2 = wd.current_window_handle
ele = wd.find_element(by=By.CSS_SELECTOR, value='a[href="http://www.bing.com"')
ele.click()
# 进入`Bing`的网页, 进行操作
for handle in wd.window_handles:
wd.switch_to.window(handle)
if 'Bing' in wd.title:
break
ele = wd.find_element(by=By.CSS_SELECTOR, value='#sb_form_q')
ele.send_keys('hello world\n')
# 切换会原来的window handle
wd.switch_to.window(main_window_handle_2)
ele = wd.find_element(by=By.CSS_SELECTOR, value='#outerbutton')
ele.click()
pass
选择框
https://www.bilibili.com/video/BV1Z4411o7TA/?p=22&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
radio框
# 获取当前选中的元素
element = wd.find_element(By.CSS_SELECTOR,
'#s_radio input[checked=checked]')
print('当前选中的是: ' + element.get_attribute('value'))
# 点选 小雷老师
wd.find_element(By.CSS_SELECTOR,
'#s_radio input[value="小雷老师"]').click()
checkbox框
# 如何勾选小雷老师
wd.get('https://cdn2.byhy.net/files/selenium/test2.html')
# 先将原来已经被选中的checkbox, 取消勾选
eles = wd.find_elements(by=By.CSS_SELECTOR, value='#s_checkbox input[checked=checked]')
for ele in eles:
ele.click()
# 在选一下小雷老师
ele = wd.find_element(by=By.CSS_SELECTOR, value='#s_checkbox input[value="小雷老师"]')
ele.click()
select框
https://www.bilibili.com/video/BV1Z4411o7TA/?p=24&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
博客内容
https://www.byhy.net/tut/auto/selenium/skills_1/
非select的下拉框, 定位&选择技巧
博客地址
https://blog.csdn.net/qsmy_an/article/details/126226992
1.问题:
遇到一个下拉框,表面显示"请选择",但是点击后下拉列表出来了同时还可以输入选择。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2CBVbrgA-1671531102515)(2022-12-20-15-57-08.png)]
既不是select也没有iframe框。
2.分析,需要四步:
①先定位[社区名称]这个框;
②调出下拉列表;
③选择某个下拉值;
④点击该值;
3.实际操作
①定位这个框,定位方法很多,大家择需选择就可以,我经常用xpath;
xpath不管是觉得路径还是相对路径,无所谓好坏,能解决了问题就可以。有些元素吧,确实不好定位啊。
②用键盘向下键,调出下拉框;
③把要选择的值标红显示;
④js点击操作;
# 代码如下:
#红色框线定位[社区名称]
ele6 = self.driver. \
find_element_by_xpath(
'XXXXX'
)
self.driver.execute_script(
"arguments[0].setAttribute('style',arguments[1]);",
ele6,
"border:2px solid red;"
)
time.sleep(1)
#按向下键调起下拉列表
ele6.send_keys(Keys.ARROW_DOWN)
time.sleep(1)
#给要选择的值标红框
ele7 = self.driver.find_element_by_xpath(
'XXXXXX'
)
self.driver.execute_script(
"arguments[0].setAttribute('style',arguments[1]);",
ele7,
"border:2px solid red;"
)
time.sleep(1)
#点击:[1000076|测试001]这个选项
xp = 'XXXXXXX'
button = self.driver.find_element_by_xpath(xp)
self.driver.execute_script("arguments[0].click();",button)
time.sleep(1)
实战技巧
博客内容
https://www.byhy.net/tut/auto/selenium/skills_2/
ActionChain
https://www.bilibili.com/video/BV1Z4411o7TA/?p=25&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
冻结页面
https://www.bilibili.com/video/BV1Z4411o7TA/?p=26&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
弹出对话框
https://www.bilibili.com/video/BV1Z4411o7TA/?p=27&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
Alert
Confirm
Prompt
其他技巧
窗口大小
获取当前窗口标题
获取当前窗口URL地址
截屏
手机模式
上传文件
自动化Edge浏览器
Xpath选择器
博客地址: https://www.byhy.net/tut/auto/selenium/xpath_1/
Xpath语法简介
https://www.bilibili.com/video/BV1Z4411o7TA?p=28&vd_source=d171c31a396363b8ea8c0e92a59cee6b
绝对路径选择
从根节点开始的,到某个节点,每层都依次写下来,每层之间用 / 分隔的表达式,就是某元素的 绝对路径
上面的xpath表达式 /html/body/div ,就是一个绝对路径的xpath表达式, 等价于 css表达式 html>body>div
自动化程序要使用Xpath来选择web元素,应该调用 WebDriver对象的方法 find_element_by_xpath 或者 find_elements_by_xpath,像这样:
elements = driver.find_elements(By.XPATH, "/html/body/div")
相对路径选择
有的时候,我们需要选择网页中某个元素, 不管它在什么位置 。
比如,选择示例页面的所有标签名为 div 的元素,如果使用css表达式,直接写一个 div 就行了。
那xpath怎么实现同样的功能呢? xpath需要前面加 // , 表示从当前节点往下寻找所有的后代元素,不管它在什么位置。
所以xpath表达式,应该这样写: //div
‘//’ 符号也可以继续加在后面,比如,要选择 所有的 div 元素里面的 所有的 p 元素 ,不管div 在什么位置,也不管p元素在div下面的什么位置,则可以这样写 //div//p
对应的自动化程序如下
elements = driver.find_elements(By.XPATH, "//div//p")
如果使用CSS选择器,对应代码如下
elements = driver.find_elements(By.CSS_SELECTOR,"div p")
如果,要选择 所有的 div 元素里面的 直接子节点 p , xpath,就应该这样写了 //div/p
如果使用CSS选择器,则为 div > p
通配符
如果要选择所有div节点的所有直接子节点,可以使用表达式 //div/*
- 是一个通配符,对应任意节点名的元素,等价于CSS选择器 div > *
代码如下:
elements = driver.find_elements(By.XPATH, "//div/*")
for element in elements:
print(element.get_attribute('outerHTML'))
根据属性选择
https://www.bilibili.com/video/BV1Z4411o7TA/?p=29&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
Xpath 可以根据属性来选择元素。
根据属性来选择元素 是通过 这种格式来的 [@属性名=‘属性值’]
注意:
属性名注意前面有个@
属性值一定要用引号, 可以是单引号,也可以是双引号
根据id属性选择
选择 id 为 west 的元素,可以这样 //*[@id=‘west’]
根据class属性选择
选择所有 select 元素中 class为 single_choice 的元素,可以这样 //select[@class=‘single_choice’]
如果一个元素class 有多个,比如
<p id="beijing" class='capital huge-city'>
北京
</p>
如果要选 它, 对应的 xpath 就应该是 //p[@class=“capital huge-city”]
不能只写一个属性,像这样 //p[@class=“capital”] 则不行
根据其他属性
同样的道理,我们也可以利用其它的属性选择
比如选择 具有multiple属性的所有页面元素 ,可以这样 //*[@multiple]
属性值包含字符串
要选择 style属性值 包含 color 字符串的 页面元素 ,可以这样 //[contains(@style,‘color’)]
要选择 style属性值 以 color 字符串 开头 的 页面元素 ,可以这样 //[starts-with(@style,‘color’)]
要选择 style属性值 以 某个 字符串 结尾 的 页面元素 ,大家可以推测是 //*[ends-with(@style,‘color’)], 但是,很遗憾,这是xpath 2.0 的语法 ,目前浏览器都不支持
按次序选择
https://www.bilibili.com/video/BV1Z4411o7TA/?p=30&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
某类型 第几个 子元素
比如
要选择 p类型第2个的子元素,就是
//p[2]
注意,选择的是 p类型第2个的子元素 , 不是 第2个子元素,并且是p类型 。
注意体会区别
再比如,要选取父元素为div 中的 p类型 第2个 子元素
//div/p[2]
第几个子元素
也可以选择第2个子元素,不管是什么类型,采用通配符
比如 选择父元素为div的第2个子元素,不管是什么类型
//div/*[2]
某类型 倒数第几个 子元素
当然也可以选取倒数第几个子元素
比如:
选取p类型倒数第1个子元素
//p[last()]
选取p类型倒数第2个子元素
//p[last()-1]
选择父元素为div中p类型倒数第3个子元素
//div/p[last()-2]
范围选择
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]
为什么不是 last()-3 呢? 因为
last() 本身代表最后一个元素
last()-1 本身代表倒数第2个元素
last()-2 本身代表倒数第3个元素
组选择、父节点、兄弟节点
https://www.bilibili.com/video/BV1Z4411o7TA?p=31&vd_source=d171c31a396363b8ea8c0e92a59cee6b
组选择
css有组选择,可以同时使用多个表达式,多个表达式选择的结果都是要选择的元素
css 组选择,表达式之间用 逗号 隔开
xpath也有组选择, 是用 竖线 隔开多个表达式
比如,要选所有的option元素 和所有的 h4 元素,可以使用
//option | //h4
等同于CSS选择器
option , h4
再比如,要选所有的 class 为 single_choice 和 class 为 multi_choice 的元素,可以使用
//*[@class='single_choice'] | //*[@class='multi_choice']
等同于CSS选择器
.single_choice , .multi_choice
选择父节点
xpath可以选择父节点, 这是css做不到的。
某个元素的父节点用 /..
表示
比如,要选择 id 为 china 的节点的父节点,可以这样写 //*[@id='china']/..
。
当某个元素没有特征可以直接选择,但是它有子节点有特征, 就可以采用这种方法,先选择子节点,再指定父节点。
还可以继续找上层父节点,比如 //*[@id='china']/../../..
兄弟节点选择
前面学过 css选择器,要选择某个节点的后续兄弟节点,用 波浪线
xpath也可以选择 后续 兄弟节点,用这样的语法 following-sibling::
比如,要选择 class 为 single_choice 的元素的所有后续兄弟节点 //*[@class='single_choice']/following-sibling::*
等同于CSS选择器 .single_choice ~ *
如果,要选择后续节点中的div节点, 就应该这样写 //*[@class='single_choice']/following-sibling::div
xpath还可以选择 前面的 兄弟节点,用这样的语法 preceding-sibling::
比如,要选择 class 为 single_choice 的元素的所有前面的兄弟节点 //*[@class='single_choice']/preceding-sibling::*
而CSS选择器目前还没有方法选择前面的 兄弟节点
通过文本内容定位元素
from selenium.webdriver.common.by import By
# 方式1:通过文本内容精准定位元素
driver.find_element(By.XPATH, '//div[text()="文本内容"]')
# 方式2:通过文本内容模糊定位元素
driver.find_element(By.XPATH, '//div[contains(text(), "文本内容")]')
selenium 注意点
https://www.bilibili.com/video/BV1Z4411o7TA?p=32&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
我们来看一个例子
我们的代码:
先选择示例网页中,id是china的元素
然后通过这个元素的WebElement对象,使用find_elements_by_xpath,选择里面的p元素,
# 先寻找id是china的元素
china = wd.find_element(By.ID, 'china')
# 再选择该元素内部的p元素
elements = china.find_elements(By.XPATH, '//p')
# 打印结果
for element in elements:
print('----------------')
print(element.get_attribute('outerHTML'))
运行发现,打印的 不仅仅是 china内部的p元素, 而是所有的p元素。
要在某个元素内部使用xpath选择元素, 需要 在xpath表达式最前面加个点 。
像这样
elements = china.find_elements(By.XPATH, './/p')
当然也可以一步直接写完
//*[@id='china']/p
这个问题只有xpath有, CSS没有这个问题
selenium自动化EDGE浏览器
https://www.bilibili.com/video/BV1Z4411o7TA?p=33&spm_id_from=pageDriver&vd_source=d171c31a396363b8ea8c0e92a59cee6b
Xpath click点击无效怎么办
https://blog.csdn.net/Beyond_F4/article/details/111615170
通过CSS定位, 通过JS执行
js = 'document.querySelector("#login-form > div.fm-btn > button").click();'
self.chrome.execute_script(js)
python selenium设置chrome的下载路径
https://www.cnblogs.com/linwenbin/p/10361986.html
from selenium import webdriver
import time
def set_chrome_pref():
chromeOptions = webdriver.ChromeOptions()
prefs = {"download.default_directory":"D:\"}
chromeOptions.add_experimental_option("prefs", prefs)
driver = webdriver.Chrome(chrome_options=chromeOptions)
time.sleep(10)