【问题标题】:Selenium can't find element by class nameSelenium 无法按类名找到元素
【发布时间】:2020-03-05 12:38:45
【问题描述】:

我想用 Python 向this webpage 发送消息。

就是说用 Python 做以下事情:

这就是我使用 Selenium 尝试以下脚本的原因:

#!/usr/bin/env python3

from selenium import webdriver


api_location = 'http://iphoneapp.spareroom.co.uk'
api_search_endpoint = 'flatshares'
api_details_endpoint = 'flatshares'

location = 'http://www.spareroom.co.uk'
details_endpoint = 'flatshare/flatshare_detail.pl?flatshare_id='

def contact_room(room_id):
    url = '{location}/{endpoint}/{id}?format=json'.format(location=api_location, endpoint=api_details_endpoint, id=room_id)
    print(url)
    driver_path = 'C:\Program Files\chromedriver'
    driver = webdriver.Chrome(executable_path = driver_path )  # Optional argument, if not specified will search path.
    # Go to your page url
    driver.get(url)
    # Get button you are going to click by its id ( also you could use find_element_by_css_selector to get element by css selector)
    button_element = driver.find_element_by_class_name('button button--wide')
    button_element.click()

但它返回:

contact_room(14110387)

(roo_env) (base) C:\Users\antoi\Documents\Programming\roomfinder>python test_message.py
http://iphoneapp.spareroom.co.uk/flatshares/14110387

DevTools listening on ws://127.0.0.1:51038/devtools/browser/401513e8-f221-47f1-ba6b-a7b7f598d839
Traceback (most recent call last):
  File "test_message.py", line 24, in <module>
    contact_room(14110387)
  File "test_message.py", line 21, in contact_room
    button_element = driver.find_element_by_class_name('button button--wide')
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 564, in find_element_by_class_name
    return self.find_element(by=By.CLASS_NAME, value=name)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 978, in find_element
    'value': value})['value']
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".button button--wide"}
  (Session info: chrome=77.0.3865.120)

虽然访问消息页面的按钮属于button button--wide 类。其实在源码中有:

<a class="button button--wide" data-ga-event-category="Listing Details" data-ga-event-action="clicked" data-ga-event-label="contact-box-email" href="/flatshare/flatshare_detail.pl?flatshare_id=14110387&amp;mode=contact&amp;submode=byemail&amp;flatshare_type=offered&amp;search_id=896264077&amp;search_results=%2Fflatshare%2F%3Fsearch_id%3D896264077%26&amp;city_id=9&amp;featured=&amp;alert_id=&amp;alert_type=&amp;upgrade_required=0&amp;" title="Email advertiser" rel="nofollow"><span><i class="far fa-envelope"></i>&nbsp;&nbsp;Message</span></a>

正在尝试find_element_by_css_selector('.button.button--wide')

不幸的是,它告诉我我无法与元素交互:

(roo_env) (base) C:\Users\antoi\Documents\Programming\roomfinder>python test_message.py
http://iphoneapp.spareroom.co.uk/flatshares/14110387

DevTools listening on ws://127.0.0.1:52677/devtools/browser/4965ddbe-4b24-4ae7-a7f5-e44a8cbf2eef
Traceback (most recent call last):
  File "test_message.py", line 25, in <module>
    contact_room(14110387)
  File "test_message.py", line 23, in contact_room
    button_element.click()
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click
    self._execute(Command.CLICK_ELEMENT)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\ProgramData\Anaconda3\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
  (Session info: chrome=77.0.3865.120)

【问题讨论】:

  • 按类名查找显然是错误的。您应该始终使用 css。
  • 嗨!你试过我更新的答案吗?任何更新?谢谢。
  • @RatmirAsanov 还没有,我走了。会的,谢谢你的帮助

标签: python python-3.x selenium


【解决方案1】:

正确的 CSS 选择器是:.button.button--wide:

所以,在你的情况下,它将是:

...
button_element = driver.find_element_by_css_selector(".button.button--wide")
...

UPD:另外,您可以尝试使用显式等待定位元素:

from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

...
button_element = ui.WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".button.button--wide")))
button_element.click()

完全可以工作的代码是:

from selenium import webdriver
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By


API_LOCATION = "http://iphoneapp.spareroom.co.uk"
API_DETAILS_ENDPOINT = "flatshares"
ID = "14110387"
URL = "{location}/{endpoint}/{id}".format(
    location=API_LOCATION, endpoint=API_DETAILS_ENDPOINT, id=ID)

DRIVER = webdriver.Chrome()
DRIVER.get(URL)
ui.WebDriverWait(DRIVER, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "a.button.button--wide"))).click()

希望对你有帮助!

【讨论】:

  • 哦,你确定吗?我得到selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified
  • @IggyPass,我稍微改变(扩展)了我的答案。请检查一下。
  • @IggyPass,CSS 选择器是正确的(根据您提供的元素 HTML ——见上面的截图)。任何更新?谢谢。
  • @IggyPass,我看到了您的最后一条错误消息。我更新的答案必须解决您的问题。谢谢。
  • 谢谢,不幸的是我收到了selenium.common.exceptions.TimeoutException: Message:
【解决方案2】:

您在浏览器中获取 json 的原因是您在函数中传递了错误的参数值。 您提供了api_details_endpoint 这个变量而不是details_endpoint。 第二件事是 class_name 有 11 个元素可以获得唯一的使用父元素。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

api_location = 'http://iphoneapp.spareroom.co.uk'
api_search_endpoint = 'flatshares'
api_details_endpoint = 'flatshares'

location = 'http://www.spareroom.co.uk'
details_endpoint = 'flatshare/flatshare_detail.pl?flatshare_id='

def contact_room(room_id):
    url = '{location}/{endpoint}/{id}?format=json'.format(location=api_location, endpoint=details_endpoint, id=room_id)
    print(url)
    driver_path = 'C:\Program Files\chromedriver'
    driver = webdriver.Chrome(executable_path = driver_path )  # Optional argument, if not specified will search path.
    # Go to your page url
    driver.get(url)
    WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"li.emailadvertiser > .button.button--wide"))).click()
    # Get button you are going to click by its id ( also you could use find_element_by_css_selector to get element by css selector)
    # button_element = driver.find_element_by_class_name('button button--wide')
    # button_element.click()

contact_room(14110387)

【讨论】:

    【解决方案3】:

    你可以试试这个通过xpath获取元素(更简单):

    看看这个帖子:Is there a way to get the XPath in Google Chrome?

    button_element = driver.find_element_by_xpath('your_xpath')
    button_element.click()
    

    【讨论】:

      【解决方案4】:

      该元素可能未加载,因此可能会出现no such element 错误。你可以添加

      driver.implicitly_wait(15)
      

      在搜索元素之前的行。 (在这种情况下,在driver.find_element_by_class_name('button button--wide') 行之前。)

      别担心,它不会等待 15 秒。每当加载元素时,selenium 都会找到它。

      【讨论】:

        猜你喜欢
        • 2020-05-19
        • 1970-01-01
        • 1970-01-01
        • 2023-01-06
        • 2021-06-23
        • 1970-01-01
        • 2021-06-28
        • 1970-01-01
        相关资源
        最近更新 更多