我正在学习如何使用 ChromeDriver 在 Python 3.9.2 上使用 Selenium 自动浏览网站,但我被困在 GitHub 的登录页面,这是我正在练习的网站。
这是我的代码用于自动登录:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)
browser = webdriver.Chrome(chrome_options)
browser.get("https://github.com")`
sign_in_link = browser.find_element(By.LINK_TEXT, "Sign in")
sign_in_link.click()
username_box = browser.find_element(By.ID, "login_field")
username_box.send_keys("<username>")
password_box = browser.find_element(By.NAME, "password")
password_box.send_keys("<password>")
password_box.submit()
现在,当我执行此代码时,这是我得到的异常:
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: {"method":"css selector", "selector":"\[id="login_field"\]"}
我尝试将
(By.ID, "login_field")
替换为
(By.NAME, "login")
,但我仍然得到相同的异常,说它找不到元素。当我检查网页上的元素时,它显示以下内容:
<input type="text" name="login" id="login_field" class="form-control input-block js-login- field" autocapitalize="off" autocorrect="off" autocomplete="username" autofocus="autofocus" required="required">
我相信我为函数 find_element() 使用了正确的参数,但 Selenium 找不到这些元素,但如果我手动登录,它工作正常。 我还尝试使用完整的 XPath 作为函数 find_element() 的参数,如下所示:
username_box = browser.find_element(By.XPATH, "/html/body/div\[1\]/div\[3\]/main/div/div\[4\]/form/input\[3\]")
第一次运行代码时有效,但当我再次尝试时,抛出相同的异常,表示找不到元素。关于如何成功地一致地自动登录有什么想法吗?
你所面临的问题是,GitHub的登录页面需要一些时间来加载,而你的Selenium脚本试图在页面完全加载之前找到元素。这就是为什么你有时会在第一次运行时侥幸成功,因为网络和计算机的速度在不同的时间点上有所不同。
你可以通过几种方法解决这个问题:
1. 使用 WebDriverWait:
这是推荐的解决方案。
WebDriverWait
允许你等待一个特定的条件被满足,然后再继续执行脚本。在这种情况下,你可以等到用户名输入框出现。
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
# ...你的代码...
sign_in_link.click()
# 等待用户名输入框出现
username_box = WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.ID, "login_field"))
)
username_box.send_keys("<username>")
# 密码输入框也需要等待
password_box = WebDriverWait(browser, 10).until(
EC.presence_of_element_located((By.NAME, "password"))
)
password_box.send_keys("<password>")
password_box.submit()
这段代码将等待最多10秒,等待ID为 "login_field" 的元素出现在页面上,然后再继续执行。
2. 使用 time.sleep():
这是一种不太优雅的解决方案,但它在某些情况下也可以奏效。
time.sleep()
会暂停你的脚本执行一段时间,这可以给页面加载时间。
import time
# ...你的代码...
sign_in_link.click()
# 等待5秒
time.sleep(5)
username_box = browser.find_element(By.ID, "login_field")
username_box.send_keys("<username>")
# ...你的代码...
关于使用XPath的说明:
虽然使用XPath可以找到元素,但它非常脆弱,因为HTML结构的任何微小变化都会导致你的脚本失败。最好是使用更可靠的定位器,比如ID、名称或CSS选择器。
通过使用
WebDriverWait
或者在必要时添加
time.sleep()
,你应该能够解决这个问题,让你的脚本更可靠地运行。