"TypeError: 'str' object is not callable" using WebDriverWait for link_text in Selenium through Python

"TypeError: 'str' object is not callable" using WebDriverWait for link_text in Selenium through Python

这是我在 Stack Overflow 上的第一个 post。我一直在 SO 上浏览和搜索这个问题的所有可能答案,我想此时我应该问一个问题,因为我已经在这堵墙上呆了好几天了。我目前正在 Python 中使用 Selenium 进行网络抓取项目。我已经抓取了一个网站,目前在第二个网站上,我 运行 陷入了一个看似棘手的问题。以下代码在页面上没有任何错误 https://www.spd.de/standpunkte/:

try:
    driver.find_element_by_link_text("Familien").click()
except NoSuchElementException:
    WebDriverWait(driver, 12).until("Familien").click()

同时,以下代码在页面 https://www.spd.de/standpunkte/familie/ 上抛出错误 TypeError: 'str' object is not callable:

try:
    driver.find_element_by_link_text("Mehr erfahren").click()
except NoSuchElementException:
    WebDriverWait(driver, 12).until("Mehr erfahren").click()

错误发生在行WebDriverWait(driver, 12).until("Mehr erfahren").click()。根据我到目前为止的研究,我认为具体问题是这一行中的某些内容被解释为 str 对象,因此无法调用。在我看来,有两个问题:

  1. 我看不出这一行产生错误的任何原因,而顶部的代码在同一网站上抓取不同的页面,可以正常工作。我检查并确保页面上没有被点击的隐藏元素。

  2. 我不知道行中的什么被视为 str 对象。整条线?只是一部分吗?如果有,是哪一部分?更糟糕的是,我无法真正打破这条线来看到任何关于它的信息; print(WebDriverWait(driver, 12).until("Mehr erfahren").click())print(type(WebDriverWait(driver, 12).until("Mehr erfahren").click())) 最终都给出了错误。我能够确定 .click() 方法不是问题,因为我尝试将行设置为等于一个变量,然后与该变量交互,但仍然像以前一样在同一行上产生错误;它甚至从未使用 .click() 方法。

有什么方法可以确定该行的哪一部分被解释为 str?或者这根本就是问题所在?

这让我抓狂,非常感谢您的帮助!

我想我发现了你的问题here。来自来源

def until(self, method, message=''):
    ...

until 采用一种方法(即可调用的东西)。因此,当 driver.find_element_by_link_text("Mehr erfahren").click() 引发异常时,它将尝试调用 ...until("Mehr erfahren")...。由于 until 需要一个方法,它会尝试调用你给它的字符串 - 引发让你发疯的错误 :)

我认为 until 需要一个条件(并且 WebDriverWait 会等到该条件为真)。您只是传递一个字符串作为参数而不是条件。您需要一个条件来检查页面上是否存在该元素。

您可以使用这个 css 选择器:a[href*="familien"]

这可以用于您的两个网址。

driver.get('yourURL')
try:
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a[href*="familien"]'))).click()
except NoSuchElementException:
    # handle if the element not exist
    print('element not exist')

查看文档 here 了解如何使用 WebDriverWait

您的研究方向正确。

在您的第一个用例中,try 中的行是成功的:

driver.find_element_by_link_text("Familien").click()

因此从未调用 except 中的行:

WebDriverWait(driver, 12).until("Familien").click()

因此您看不到错误。


在您的第二个用例中,try 中的行不成功:

driver.find_element_by_link_text("Familien").click()

因此 except 中的行被称为:

WebDriverWait(driver, 12).until("Mehr erfahren").click()

导致错误:

TypeError: 'str' object is not callable

深入探讨

WebDriverWait is invoked inconjunction with expected_conditions.

您可以在以下位置找到一些详细的讨论:

现在,element_to_be_clickable() 应该在 tuple 中调用,因为它不是 函数 ,而是 class ,其中初始化器只需要 1 参数,超出 implicit self:

class element_to_be_clickable(object):
    """ An Expectation for checking an element is visible and enabled such that you can click it."""
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        element = visibility_of_element_located(self.locator)(driver)
        if element and element.is_enabled():
            return element
        else:
            return False

所以代替:

WebDriverWait(driver, 12).until("Mehr erfahren").click()

您需要(添加一个额外的括号):

WebDriverWait(driver, 12).until((EC.element_to_be_clickable(By.LINK_TEXT, "Mehr erfahren"))).click()

You can find a detailed discussions in