python - 如何在 selenium 中的 python 中使用相同的 xpath 访问第二个元素
问题描述
我的意思是我正在使用的网站有 2 个名为省的下拉菜单,其 ID 完全相同,所以我如何告诉 python 我想选择哪个下拉菜单。当然,这是假设问题是 python 总是选择它看到的第一个 id
from selenium import webdriver
from selenium.webdriver.support.ui import Select
# There are two dropmenu with the same xpath. first time it works fine
# 2nd time it throws an error about element not interactable
Prov = Select(web.find_element_by_xpath('//*[@id="province"]'))
Prov.select_by_index(2)
def Start():
# once opened it will fill in the confirm your age
Day = Select(web.find_element_by_xpath('//*[@id="bday_day"]'))
Day.select_by_index(2)
Month = Select(web.find_element_by_xpath('//*[@id="bday_month"]'))
Month.select_by_index(4)
Month = Select(web.find_element_by_xpath('//*[@id="bday_year"]'))
Month.select_by_index(24)
Prov = Select(web.find_element_by_xpath('//*[@id="province"]'))
Prov.select_by_index(5)
Button = web.find_element_by_xpath('//*[@id="popup-subscribe"]/button')
Button.click()
# have to go through select your birthday
Start()
# 2 seconds is enough for the website to load
time.sleep(2)
# this throws and error.
Prov = Select(web.find_element_by_xpath('//*[@id="province"]'))
Prov.select_by_index(5)
解决方案
硒具有功能
find_element_by_...
没有s
文字element
只得到第一个元素find_elements_by_...
用s
in wordelements
获取所有元素
Selenium 文档:4. 定位元素¶
因此,您可以将所有元素作为列表获取(即使 HTML 中只有一个元素)
(如果没有元素,那么您将获得空列表)
elements = web.find_elements_by_xpath('//*[@id="province"]')
然后切片
first = elements[0]
second = elements[1]
last = elements[-1]
list_first_and_second = elements[:1]
编辑:
您也可以尝试直接在 xpath 中切片
(它从一开始计数,而不是零)
'//*[@id="province"][2]'
或者可能
'(//*[@id="province"])[2]'
但我从来没有用它来确认它是否会起作用。
顺便提一句:
所有人ID
都应该有唯一的名字——你不应该重复 ID。
如果您检查文档4. Locating Elements¶那么您会看到word中find_element_by_id
没有 char - 获取第一个也是唯一具有某些 ID 的元素 - 但word中没有with char - 获取多个具有某些 ID 的元素。s
element
find_elements_by_id
s
elements
编辑:
代码中带有示例 HTML 的最小工作代码
from selenium import webdriver
from selenium.webdriver.support.ui import Select
html = '''
<select id="province">
<option value="value_A">A</options>
<option value="value_B">B</options>
</select>
<select id="province">
<option value="value_1">1</options>
<option value="value_2">2</options>
</select>
'''
driver = webdriver.Firefox()
driver.get("data:text/html;charset=utf-8," + html)
all_elements = driver.find_elements_by_xpath('//*[@id="province"]')
first = all_elements[0]
second = all_elements[1]
prov1 = Select(first)
prov2 = Select(second)
print('--- first ---')
for item in prov1.options:
print('option:', item.text, item.get_attribute('value'))
for item in prov1.all_selected_options:
print('selected:', item.text, item.get_attribute('value'))
print('--- second ---')
for item in prov2.options:
print('option:', item.text, item.get_attribute('value'))
for item in prov2.all_selected_options:
print('selected:', item.text, item.get_attribute('value'))
编辑:
有两个province
。
当您使用find_element
in时,Start
您会首先province
出现在弹出窗口中 - 您可以填写它。当您单击按钮时,它会关闭此弹出窗口,但不会首先province
从 HTML 中删除 - 它只会隐藏它。
稍后,当您使用时,find_element
您会再次province
在隐藏的弹出窗口中再次出现 - 这次它不可见并且无法使用它 - 这会产生错误。你必须province
像这个例子中那样使用第二个。
from selenium import webdriver
from selenium.webdriver.support.ui import Select
import time
def Start():
# once opened it will fill in the confirm your age
Day = Select(web.find_element_by_xpath('//*[@id="bday_day"]'))
Day.select_by_index(2)
Month = Select(web.find_element_by_xpath('//*[@id="bday_month"]'))
Month.select_by_index(4)
Month = Select(web.find_element_by_xpath('//*[@id="bday_year"]'))
Month.select_by_index(24)
# it uses first `province`
Prov = Select(web.find_element_by_xpath('//*[@id="province"]'))
Prov.select_by_index(5)
Button = web.find_element_by_xpath('//*[@id="popup-subscribe"]/button')
Button.click()
web = webdriver.Firefox()
web.get('https://www.tastyrewards.com/en-ca/contest/fritolaycontest/participate')
# have to go through select your birthday
Start()
# 2 seconds is enough for the website to load
time.sleep(2)
# `find_elements` with `s` - to get second `province`
all_province = web.find_elements_by_xpath('//*[@id="province"]')
second_province = all_province[1]
Prov = Select(second_province)
Prov.select_by_index(5)
推荐阅读
- vba - 使用输入框限制 excel VBA 数字游戏中的尝试
- python - 您可以在 Python 函数中动态分配变量吗?
- python - 如何在 QGraphicsview 内继续绘制透明线而不重叠?
- javascript - 如何使用 U64 参数从 js 调用 NEAR 智能合约?
- python-3.x - 我可以使用默认值注册一个设置,然后在模型的字段中使用该设置吗?
- c# - 运行json代码时出错不会转换
- node.js - 如何使用 sendgrid 检查节点 js 中是否存在电子邮件
- sql - How to union a data set with a specific rule
- c++ - 结束迭代器在非连续 C++ 容器中指向哪里?
- rust - 在谓词失败后,在迭代器中获取一个额外元素的规范方法是什么?