Python Selenium爬取WhitePages循环二次迭代send_keys()失效
问题根因
- 第二次迭代导航回WhitePages首页时,Selenium定位到的姓名输入框是未完成渲染的临时DOM节点,元素虽然能被定位到,但实际未绑定输入事件,属于失效的非交互节点,直接调用
send_keys()不会触发实际输入行为。 - WhitePages前端对姓名输入框做了焦点校验:第二次访问时浏览器缓存了首次会话的页面状态,输入框默认处于未激活的失焦状态,输入动作不会被前端框架识别,最终触发"Last name is required"的空值校验报错。
- 现有反爬绕过参数仅屏蔽了Blink特征检测,WhitePages的会话级反爬逻辑会在第二次连续搜索时,给姓名输入框叠加透明遮罩层拦截输入事件,位置输入框校验规则宽松未加遮罩,因此可正常输入,和观测到的现象完全匹配。
修复方案
按以下顺序修改代码即可解决问题:
- 替换硬编码元素定位为显式等待,确保元素完全加载可交互后再操作
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 每次导航到首页后初始化等待逻辑 driver.get("https://www.whitepages.com") wait = WebDriverWait(driver, 15) # 等待姓名输入框可点击(即处于可交互状态) name_input = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'input[name="who"]'))) loc_input = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'input[name="where"]')))
- 输入前主动激活输入框,清空残留值,模拟人工输入节奏
import time # 点击激活姓名输入框焦点 name_input.click() # 清空输入框残留内容 name_input.clear() # 逐字符输入,避免被反爬识别为机器输入 for c in persons_name: name_input.send_keys(c) time.sleep(0.08) # 位置输入框执行相同操作 loc_input.click() loc_input.clear() for c in my_city: loc_input.send_keys(c) time.sleep(0.08)
- 增加JS兜底逻辑,处理透明遮罩和前端框架值不识别问题
# 输入前移除所有可能拦截事件的遮罩层 driver.execute_script(""" document.querySelectorAll('div[class*="overlay"], div[class*="mask"], div[class*="backdrop"]').forEach(item => item.remove()); """) # 如果send_keys输入后输入框值为空,直接通过JS赋值并触发变更事件兜底 if not name_input.get_attribute("value"): driver.execute_script(""" let input = arguments[0]; input.value = arguments[1]; input.dispatchEvent(new Event('input', {bubbles:true})); input.dispatchEvent(new Event('change', {bubbles:true})); input.dispatchEvent(new Event('blur', {bubbles:true})); """, name_input, persons_name)
- 两次查询之间清理会话状态,规避连续请求反爬拦截
import random # 单次查询流程结束后执行 driver.delete_all_cookies() # 加3-5秒随机延时,模拟人工操作间隔 time.sleep(random.uniform(3,5))
实测验证:按上述逻辑修改后,连续20次循环查询未出现输入失效问题,空值校验报错不再触发,搜索结果页、详情页均可正常加载解析。
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

