使用Python+Selenium在Palo Alto网站触发2FA邮件遇按钮定位问题
问题描述
我正在编写脚本从Palo Alto Networks网站下载文件,脚本已成功输入用户名和密码,但进入2FA验证环节后,无法通过Selenium定位并点击“Send me the code”按钮,运行时抛出TimeoutException错误。
现有脚本:
import os from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from dotenv import dotenv_values # Load the .env file into a variable config = dotenv_values(".env") # Read username and password from the environment file username = config['USERNAME'] password = config['PASSWORD'] # URL of the Palo Alto login page url = "https://sso.paloaltonetworks.com/" # Path to your WebDriver (download the appropriate one for your browser) # For Chrome, download from https://sites.google.com/chromium.org/driver/ # webdriver_path = r"c:\Users\tdadmin\Documents\Python\PaloAlto\RegListDownload\chromedriver-win64\chromedriver.exe" # Create a new instance of the Chrome driver driver = webdriver.Chrome() try: # Open the login page driver.get(url) # Find the username input field and fill them username_field = driver.find_element(By.ID, "idp-discovery-username") username_field.send_keys(username) # Submit the username username_field.send_keys(Keys.RETURN) # Wait for the password field to load WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "okta-signin-password")) ) # Find the password input field and fill them password_field = driver.find_element(By.ID, "okta-signin-password") password_field.send_keys(password) # Submit the password password_field.send_keys(Keys.RETURN) # Wait for the 2FA page to load WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".button .button-primary")) ) # Press the button to send the e-mail send_2FA = driver.find_element(By.CSS_SELECTOR, ".button .button-primary") send_2FA.click(); # Provide an opportunity for the user to enter 2FA code manually # input("Please enter your 2FA code, then press Enter to continue...") # You may need to locate and interact with the "Submit" button after entering 2FA code # For example: # submit_button = driver.find_element(By.ID, "submit_button_id") # submit_button.click() # Now, you can perform actions on the authenticated session # (e.g., navigate to the desired page and download a file) finally: # Close the browser window driver.quit()
按钮的XPath:/html/body/div/div[2]/div/div[2]/div[1]/main/div[2]/div/div/form/div[2]/input
错误信息:
File "C:\Users\<user>\Documents\Python\PaloAlto\RegListDownload\Lib\site-packages\selenium\webdriver\support\wait.py", line 105, in until raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException: Message: Stacktrace: GetHandleVerifier [0x00007FF745682142+3514994] (No symbol) [0x00007FF7452A0CE2] (No symbol) [0x00007FF7451476AA] (No symbol) [0x00007FF745191860] (No symbol) [0x00007FF74519197C] (No symbol) [0x00007FF7451D4EE7] (No symbol) [0x00007FF7451B602F] (No symbol) [0x00007FF7451D28F6] (No symbol) [0x00007FF7451B5D93] (No symbol) [0x00007FF745184BDC] (No symbol) [0x00007FF745185C64] GetHandleVerifier [0x00007FF7456AE16B+3695259] GetHandleVerifier [0x00007FF745706737+4057191] GetHandleVerifier [0x00007FF7456FE4E3+4023827] GetHandleVerifier [0x00007FF7453D04F9+689705] (No symbol) [0x00007FF7452AC048] (No symbol) [0x00007FF7452A8044] (No symbol) [0x00007FF7452A81C9] (No symbol) [0x00007FF7452988C4] BaseThreadInitThunk [0x00007FF9712A7AC4+20] RtlUserThreadStart [0x00007FF97404A351+33]
解决办法
1. 修正元素定位规则
你当前使用的CSS选择器.button .button-primary是后代选择器,若按钮的类是button button-primary(多类名),正确的写法应该是.button.button-primary(无空格)。另外也可以用更精准的定位方式:
- 基于按钮文本/属性的XPath:
WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, "//input[@value='Send me the code']")) ) send_2FA = driver.find_element(By.XPATH, "//input[@value='Send me the code']") send_2FA.click() - 修正后的CSS选择器:
WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, ".button.button-primary")) ) send_2FA = driver.find_element(By.CSS_SELECTOR, ".button.button-primary") send_2FA.click()
2. 等待元素可点击而非仅存在
presence_of_element_located只检查元素是否存在于DOM,但元素可能未加载完成或处于不可点击状态。换成element_to_be_clickable确保元素可交互:
WebDriverWait(driver, 15).until( EC.element_to_be_clickable((By.XXX, "XXX")) # 替换为正确的定位符 )
3. 检查是否存在iframe
若2FA按钮嵌套在iframe中,需先切换到iframe才能定位元素:
# 等待iframe加载并切换 WebDriverWait(driver, 10).until( EC.frame_to_be_available_and_switch_to_it((By.ID, "iframe-id")) # 替换为实际iframe的定位符 ) # 定位并点击按钮 send_2FA = driver.find_element(By.XPATH, "//input[@value='Send me the code']") send_2FA.click() # 操作完成后切回主文档 driver.switch_to.default_content()
4. 延长等待时间
网络延迟可能导致页面加载缓慢,将等待时间从10秒延长至15-20秒:
WebDriverWait(driver, 20).until(...)
5. 用键盘操作替代点击
若点击无效,尝试用键盘事件触发按钮:
send_2FA.send_keys(Keys.RETURN)
6. 处理页面遮挡元素
页面可能存在cookie提示、加载弹窗等遮挡按钮,需先关闭这些元素:
# 示例:关闭cookie提示 try: cookie_button = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.ID, "accept-cookies")) ) cookie_button.click() except: pass # 无提示则跳过
内容的提问来源于stack exchange,提问作者Bokkie
相关产品推荐
相关产品推荐

