You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 11:44:57