Python Selenium无头Chrome登录StoryWeaver(React)遇TimeoutException
无头模式下Selenium无法定位StoryWeaver登录模态框输入字段
我编写了自动化下载StoryWeaver PDF的脚本,流程如下:
- 访问React渲染的首页 https://storyweaver.org.in/en/
- 点击「Log in」打开React模态框
- 填写邮箱和密码
- 等待跳转至
/en/library页面 - 收集前10个故事链接并逐个点击下载PDF
该脚本在可见Chrome窗口中运行完全正常,但切换到无头模式后,总会在等待邮箱输入字段出现时触发TimeoutException:
selenium.common.exceptions.TimeoutException: Message: Stacktrace: chromedriver … raise TimeoutException(message, screen, stacktrace)
已尝试的解决方法:
- 切换
--headless、--headless=new两种无头引擎 - 设置窗口大小为
--window-size=1920,1080 - 在定位元素前添加
time.sleep(5) - 尝试多种选择器:
By.ID("user_email")、By.NAME("user[email]")、By.CSS_SELECTOR('input[type="email"]') - 用requests+BeautifulSoup通过CSRF token登录,返回500/CSRF错误
- 尝试导出可见Selenium的Cookie到requests.Session(若能正常登录则可用于PDF下载)
问题集中在这段代码的超时:
wait.until( EC.visibility_of_element_located((By.CSS_SELECTOR, 'input[type="email"]')) ).send_keys(EMAIL)
解决方案
核心修复思路
无头模式下Chrome的渲染环境与可见窗口存在细微差异,主要问题为用户代理不完整和未等待模态框容器完全加载,针对性修复如下:
- 使用完整的主流浏览器用户代理字符串,避免被网站识别为异常请求
- 先等待登录模态框的容器元素加载完成,再定位内部输入字段
- 移除固定
time.sleep,改用显式等待保证元素加载的可靠性
修改后的完整代码
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC EMAIL = "you@example.com" PASSWORD = "yourpassword" opts = Options() opts.add_argument("--headless=new") opts.add_argument("--no-sandbox") opts.add_argument("--disable-dev-shm-usage") opts.add_argument("--window-size=1920,1080") # 使用完整的Chrome用户代理 opts.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") opts.add_argument("--enable-javascript") driver = webdriver.Chrome(options=opts) wait = WebDriverWait(driver, 25) driver.get("https://storyweaver.org.in/en/") # 等待并点击登录链接 wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "Log in"))).click() # 先等待登录模态框容器加载完成 wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div[role='dialog']"))) # 定位并填写邮箱 email_input = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input[type='email']"))) email_input.send_keys(EMAIL) # 定位并填写密码 password_input = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "input[type='password']"))) password_input.send_keys(PASSWORD) # 点击登录按钮 submit_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[type='submit']"))) submit_btn.click() # 等待登录成功跳转至文库页面 wait.until(EC.url_contains("/en/library")) # 后续收集故事链接及下载PDF的逻辑...
额外优化建议
如果仍出现检测问题,可添加opts.add_argument("--disable-blink-features=AutomationControlled")绕过网站自动化检测;登录成功后直接用Selenium处理PDF下载,无需切换到requests,避免Cookie同步问题。
内容的提问来源于stack exchange,提问作者Mohammad Malik
相关产品推荐
相关产品推荐

