Selenium+Chrome无头模式下Upstox自动登录异常求助
问题:Chrome无头模式下Upstox自动登录无法触发OTP发送及页面跳转
环境配置:
- Chrome浏览器 123.0.6312.58
- chromedriver 123.0.6312.58
- Selenium 4.14.0
现象:
- 用Chrome无头模式访问
https://login.upstox.com,输入手机号后点击「获取OTP」按钮,无法向手机发送OTP,页面也不跳转;但非无头模式运行完全正常。 - Firefox无头模式在Windows环境可用,但Linux环境下同样失效;尝试Edge浏览器无头模式也未解决问题。
原代码:
import os from selenium import webdriver from selenium.webdriver.common.by import By import time from datetime import datetime import requests def init_chrome_webdriver(): from selenium.webdriver.chrome.service import Service driver_path = os.path.join(os.getcwd(),'chromedriver.exe') service = Service(executable_path=driver_path,log_output="chromedriver.log") options = webdriver.ChromeOptions() options.add_argument("--headless=new") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") return webdriver.Chrome(service=service, options=options) def automatic_login(config): url='https://login.upstox.com' driver = init_chrome_webdriver() driver.get(url) time.sleep(5) phone = driver.find_element(By.TAG_NAME,"input") phone.send_keys(config['phone']) page = driver.find_element(By.TAG_NAME,"body") page.screenshot("before.png") time.sleep(5) next = driver.find_element(By.ID,"getOtp") next.click() time.sleep(5) page = driver.find_element(By.TAG_NAME,"body") page.screenshot("after.png") driver.quit() if __name__=='__main__': creds = {} creds['pass'] = '' creds['phone'] = 'xxxxxxxx' #Replace with phone number automatic_login(creds)
解决方案
核心原因是Upstox的登录页面通过检测浏览器特征(如UA标识、窗口参数、自动化痕迹)拦截无头模式的自动化操作。以下是针对性修复:
1. 模拟真实浏览器特征
修改init_chrome_webdriver函数,添加窗口大小和真实UA,避免被识别为无头浏览器:
options.add_argument("--window-size=1920,1080") options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")
2. 禁用自动化检测标识
Chrome默认会暴露自动化相关特征,需要手动禁用:
options.add_argument("--disable-blink-features=AutomationControlled") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False)
3. 替换强制等待为显式等待
原代码的time.sleep()不稳定,改用Selenium显式等待确保元素加载完成后再操作,避免因页面未渲染完成导致点击失效:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待手机号输入框可交互 phone = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.TAG_NAME, "input")) ) # 等待获取OTP按钮并点击 get_otp_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, "getOtp")) ) get_otp_btn.click() # 等待OTP输入框出现,验证页面跳转 WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, "input[placeholder='Enter OTP']")) )
4. Linux环境额外配置
如果在Linux服务器运行,需安装浏览器依赖库:
# Chrome依赖 sudo apt-get install -y libnss3 libgconf-2-4 libxss1 libappindicator1 libindicator7 # Firefox依赖 sudo apt-get install -y libdbus-glib-1-2
修改后的完整代码
import os 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 def init_chrome_webdriver(): from selenium.webdriver.chrome.service import Service driver_path = os.path.join(os.getcwd(),'chromedriver.exe') service = Service(executable_path=driver_path,log_output="chromedriver.log") options = webdriver.ChromeOptions() options.add_argument("--headless=new") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") # 模拟真实浏览器参数 options.add_argument("--window-size=1920,1080") options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36") # 禁用自动化检测 options.add_argument("--disable-blink-features=AutomationControlled") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) return webdriver.Chrome(service=service, options=options) def automatic_login(config): url='https://login.upstox.com' driver = init_chrome_webdriver() driver.get(url) # 等待手机号输入框加载完成 phone = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.TAG_NAME, "input")) ) phone.send_keys(config['phone']) page = driver.find_element(By.TAG_NAME,"body") page.screenshot("before.png") # 等待并点击获取OTP按钮 get_otp_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, "getOtp")) ) get_otp_btn.click() # 验证页面跳转至OTP输入页 try: WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, "input[placeholder='Enter OTP']")) ) print("OTP页面加载成功") except Exception as e: print(f"页面跳转失败: {e}") page = driver.find_element(By.TAG_NAME,"body") page.screenshot("after.png") driver.quit() if __name__=='__main__': creds = {} creds['pass'] = '' creds['phone'] = 'xxxxxxxx' # 替换为真实手机号 automatic_login(creds)
内容的提问来源于stack exchange,提问作者Ramesh N
相关产品推荐
相关产品推荐

