如何修改Selenium代码,避免谷歌检测无头模式下的自动化脚本?
谷歌无头模式下Selenium登录被检测的问题解决
问题描述
我有一段可正常运行的Selenium代码,用于登录谷歌账号,但启用headless(无头)模式后会被谷歌检测到。我已尝试添加User-Agent、设置窗口尺寸,但均无效果。
原代码如下:
# import required modules from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service # Enter your email address and password between the quotations mark mail_address = 'my email' password = 'password' # Create chrome instance opt = Options() # Disable google from detected the bot opt.add_argument('--disable-blink-features=AutomationControlled') # Maximize the browser opt.add_argument('--start-maximized') driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=opt) # Open the login Page driver.get('https://accounts.google.com/ServiceLogin?hl=en&passive=true&continue=https://www.google.com/&ec=GAZAAQ') # Enter the email address driver.find_element(By.ID, "identifierId").send_keys(mail_address) # click Next driver.find_element(By.ID, "identifierNext").click() # Wait for 10 seconds driver.implicitly_wait(10) driver.find_element( By.XPATH, '//*[@id="password"]/div[1]/div/div[1]/input').send_keys(password) # Wait for 10 seconds driver.implicitly_wait(10) # Click next driver.find_element(By.ID, "passwordNext").click() # wait for 2 seconds driver.implicitly_wait(8)
添加的无头模式配置:
options.add_argument('--headless') options.add_argument('--no-sandbox')
谷歌检测自动化脚本的核心方式
- 浏览器特征识别:Selenium驱动会在浏览器环境中留下专属标记,比如
window.navigator.webdriver属性(即使禁用AutomationControlled,无头模式下仍存在差异);默认无头模式的User-Agent会带有HeadlessChrome标识,直接暴露自动化属性。 - 行为模式差异:自动化脚本的输入、点击速度均匀无波动,缺少人类操作的随机性(比如停顿、鼠标移动轨迹);交互流程过于机械,不符合正常用户的操作逻辑。
- 运行环境差异:无头模式下部分JavaScript API返回值与正常浏览器不一致;缺少真实用户环境的历史痕迹(如Cookie、本地存储记录)。
无头模式下的解决方案
针对你的场景,需要从配置优化和行为模拟两方面入手:
1. 完善Chrome无头模式配置
补充以下参数,让无头浏览器更接近真实环境:
opt.add_argument('--headless=new') # 使用新版无头模式,行为更贴近正常浏览器 opt.add_argument('--disable-gpu') opt.add_argument('--disable-dev-shm-usage') # 设置与真实浏览器一致的User-Agent,避免包含Headless标识 opt.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") # 模拟正常屏幕尺寸 opt.add_argument('--window-size=1920,1080') # 隐藏自动化相关开关 opt.add_experimental_option("excludeSwitches", ["enable-automation"]) opt.add_experimental_option('useAutomationExtension', False)
2. 修改脚本,模拟人类操作行为
- 用
WebDriverWait显式等待替代固定时长的隐式等待,避免机械的时间间隔; - 添加随机停顿和鼠标移动轨迹,模拟真实用户的操作节奏;
修改后的完整代码:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.action_chains import ActionChains import time import random mail_address = 'my email' password = 'password' opt = Options() # 无头模式核心配置 opt.add_argument('--headless=new') opt.add_argument('--no-sandbox') opt.add_argument('--disable-gpu') opt.add_argument('--disable-dev-shm-usage') # 模拟真实User-Agent opt.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") opt.add_argument('--window-size=1920,1080') # 隐藏自动化特征 opt.add_argument('--disable-blink-features=AutomationControlled') opt.add_experimental_option("excludeSwitches", ["enable-automation"]) opt.add_experimental_option('useAutomationExtension', False) driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=opt) wait = WebDriverWait(driver, 15) actions = ActionChains(driver) driver.get('https://accounts.google.com/ServiceLogin?hl=en&passive=true&continue=https://www.google.com/&ec=GAZAAQ') # 输入邮箱:模拟鼠标移动+随机停顿 email_input = wait.until(EC.visibility_of_element_located((By.ID, "identifierId"))) actions.move_to_element(email_input).pause(random.uniform(0.5, 1.5)).perform() email_input.send_keys(mail_address) # 点击下一步:添加随机停顿 next_btn = wait.until(EC.element_to_be_clickable((By.ID, "identifierNext"))) actions.move_to_element(next_btn).pause(random.uniform(0.3, 1.0)).click().perform() # 输入密码:等待元素可见+模拟交互 password_input = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="password"]/div[1]/div/div[1]/input'))) actions.move_to_element(password_input).pause(random.uniform(0.5, 1.5)).perform() password_input.send_keys(password) # 完成登录:模拟点击前停顿 login_btn = wait.until(EC.element_to_be_clickable((By.ID, "passwordNext"))) actions.move_to_element(login_btn).pause(random.uniform(0.3, 1.0)).click().perform() time.sleep(random.uniform(2, 5)) driver.quit()
额外注意事项
- 避免短时间内频繁用同一账号登录,谷歌会根据登录频率、IP地址触发风险检测;
- 若仍被限制,可尝试使用代理IP模拟不同地区访问;
- 不要硬编码账号密码,建议通过环境变量或加密存储读取,提升安全性。
内容的提问来源于stack exchange,提问作者Shatha Al-Bajly
相关产品推荐
相关产品推荐

