我正在使用Python-Webdriver自动执行“点击”操作。这是我的代码:
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.common.exceptions import InvalidSelectorException
LOGIN_BUTTON = (By.XPATH, '//a[contains(@class,"aui-nav-link login-link")]')
NEWS_OPTION = (By.ID, 'blq-nav-news')
driver = webdriver.Chrome()
driver.implicitly_wait(30)
driver.get("http://bbc.co.uk/")
myDynamicElement = driver.find_element(NEWS_OPTION)
myDynamicElement.click()
控制台会生成如下例外
raise InvalidSelectorException("Invalid locator values passed in")
selenium.common.exceptions.InvalidSelectorException: Message: Invalid locator values passed in
但是,如果我改变了行
“myDynamicElement = driver.find_element(NEWS_OPTION)”
到
“myDynamicElement = driver.find_element_by_id('blq-nav-news')”
,没有异常,脚本按预期工作。
我找出根本原因是我们不使用
find_element_by _ *
。所以我想知道这是Python-Webdriver的限制?我是否有解决方案来修复我的问题而不像我一样改变我的代码。
答案 0 :(得分:3)
根据documentation,您可以使用find_element_by_*
个快捷方式,find_element()
和find_elements()
"私有"方法直接:
除了上面给出的公共方法外,还有两个私人方法 可能对页面对象中的定位器有用的方法。这些是 两个私有方法:find_element和find_elements。
使用示例:
from selenium.webdriver.common.by import By driver.find_element(By.XPATH, '//button[text()="Some text"]') driver.find_elements(By.XPATH, '//button')
但是,在您的情况下,不是将2个参数传递给find_element()
,而是传递一个参数 - tuple
NEWS_OPTION
。你只需要将元组解压缩为位置参数:
NEWS_OPTION = (By.ID, 'blq-nav-news')
myDynamicElement = driver.find_element(*NEWS_OPTION)
或者,作为替代方案,您也可以使用关键字参数:
NEWS_OPTION = {'by': By.ID, 'value': 'blq-nav-news'}
myDynamicElement = driver.find_element(**NEWS_OPTION)
而且,每当你对事情应该如何运作有任何疑问时,只需挖掘源代码并为自己澄清。在这种情况下,请参阅find_element_by_id()
方法的actually implemented:
def find_element_by_id(self, id_):
"""Finds an element by id.
:Args:
- id\_ - The id of the element to be found.
:Usage:
driver.find_element_by_id('foo')
"""
return self.find_element(by=By.ID, value=id_)
答案 1 :(得分:1)
根据api doc隐私方法find_elements
和find_element
每个方法需要两个parameters
,而您传递的方法显然是错误的。
和
myDynamicElement = driver.find_element(NEWS_OPTION)
和
myDynamicElement = driver.find_element_by_id(' blq-nav-news')
不一样。 driver.find_element_by_id
需要一个参数,因此这项工作和find_element
需要两个参数才能失败。
所以,字面意思是你应该使用
myDynamicElement = driver.find_element(By.ID,'blq-nav-news')
修改强>
NEWS_OPTION = (By.ID, 'blq-nav-news')
将返回('id', 'blq-nav-news')
,而find_element()
期望第一个参数是By
类机制的实现,以便不仅仅是字符串来定位元素。
NEWS_OPTION = (By.ID, 'blq-nav-news')
的直接致电已向我返回tuple
,By.ID
的属性为'id'
NEWS_OPTION = (By.ID, 'blq-nav-news')
的简单打印为我提供了
('id', 'blq-nav-news')
而且,这是By
类
class By(object):
"""
Set of supported locator strategies.
"""
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"
@classmethod
def is_valid(cls, by):
for attr in dir(cls):
if by == getattr(cls, attr):
return True
return False