Python Selenium在JS管控乐天登录页自动输入失效的解决方案
乐天登录页Selenium输入失效解决方案
原有方案失效原因
element.send_keys('txt')失效:乐天登录页做了自动化行为检测,常规send_keys触发的事件链不完整,且如果未做webdriver痕迹隐藏,站点会直接拦截所有自动化操作;若元素未完成加载、被透明遮罩遮挡,也会导致输入无响应。driver.execute_script("arguments[0].setAttribute('value', 'txt')", email)失效:该方法仅直接修改DOM的value属性,不会触发输入框绑定的keydown/input/change等原生事件,站点前端校验逻辑无法感知到输入动作,提交时会判定输入为空。
可落地的有效方案(按成功率从高到低排序)
方案1:CDP层原生键盘输入(推荐,和真实物理输入无差异)
通过Chrome DevTools Protocol直接在浏览器层面派发键盘按下、抬起事件,绕过前端所有自动化事件检测,是目前反爬严格站点输入成功率最高的方案。
前置需要先隐藏webdriver特征:
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time import random # 启动配置:隐藏自动化特征 options = Options() options.add_argument("--disable-blink-features=AutomationControlled") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option("useAutomationExtension", False) driver = webdriver.Chrome(options=options) # 注入脚本移除navigator.webdriver标记 driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})" }) # CDP输入方法 def cdp_type(text): for char in text: # 按键按下 driver.execute_cdp_cmd("Input.dispatchKeyEvent", { "type": "keyDown", "text": char, "key": char, "code": f"Key{char.upper()}" if char.isalpha() else char, "windowsVirtualKeyCode": ord(char.upper()) if char.isalpha() else ord(char) }) time.sleep(0.05 + 0.15 * random.random()) # 按键抬起 driver.execute_cdp_cmd("Input.dispatchKeyEvent", { "type": "keyUp", "key": char, "code": f"Key{char.upper()}" if char.isalpha() else char, "windowsVirtualKeyCode": ord(char.upper()) if char.isalpha() else ord(char) }) time.sleep(0.05 + 0.1 * random.random()) # 操作流程 driver.get("目标乐天登录页地址") wait = WebDriverWait(driver, 10) # 等待输入框可点击,先点击聚焦 email_input = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='username']"))) ActionChains(driver).move_to_element(email_input).click().pause(0.3).perform() # 调用CDP输入 cdp_type("你的账号邮箱")
方案2:JS注入触发完整原生事件链
如果不想用CDP,可以通过JS手动模拟真实用户输入的全量事件,让站点校验逻辑感知到输入动作,比直接修改value属性的成功率高很多:
def js_input(element, input_text): driver.execute_script(""" const target = arguments[0]; const text = arguments[1]; // 聚焦元素,清空原有值 target.focus(); target.value = ''; // 逐字输入,触发完整事件链 for (let i = 0; i < text.length; i++) { target.value += text[i]; // 依次派发所有和输入相关的原生事件 ['keydown', 'keypress', 'input', 'keyup'].forEach(evtName => { const evt = new Event(evtName, {bubbles: true, cancelable: true}); target.dispatchEvent(evt); }); } // 输入完成后触发change事件 target.dispatchEvent(new Event('change', {bubbles: true})); """, element, input_text) # 调用方式:等待元素加载完成后直接调用 # js_input(email_input, "你的账号邮箱")
方案3:模拟真人逐字输入
在隐藏webdriver特征的前提下,放弃整段文本直接send_keys,模拟真人逐字输入+随机间隔,绕过行为检测:
# 先点击聚焦输入框 ActionChains(driver).click(email_input).pause(0.2).perform() input_content = "你的账号邮箱" for c in input_content: ActionChains(driver).send_keys(c).pause(0.1 + 0.2*random.random()).perform()
注意事项
- 必须加显式等待,等页面完全渲染、输入框处于可交互状态再操作,不要页面刚加载就执行输入
- 如果页面存在前置滑块验证、透明遮罩层,需要先完成验证、移除遮罩再操作输入框
- 测试阶段尽量不要使用无头模式,部分反爬规则会直接拦截无头环境下的所有输入行为
内容的提问来源于stack exchange,提问作者naohide_a
相关产品推荐
相关产品推荐

