使用Python SeleniumBase执行脚本时如何解决script timeout错误?
问题描述
作为Python新手,使用SeleniumBase库进行网站爬取时,间歇性运行fetch脚本遇到如下问题:当请求响应时间超过约950毫秒时,会抛出script timeout错误,但浏览器网络面板中能正常看到fetch的响应;响应延迟低于950毫秒时,代码运行完全正常。尝试给脚本添加超时设置但未生效,推测是操作方式有误。
代码片段
script = """ return new Promise((resolve, reject) => { var csrf = document.querySelector('meta[name="csrf-token"]').content; var obj; fetch("MyUrl", { 'headers': { 'accept': '/', 'accept-language': 'en-US,en;q=0.9', 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 'sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'x-csrf-token': csrf, 'x-requested-with': 'XMLHttpRequest' }, 'referrer': 'MyUrl', 'referrerPolicy': 'strict-origin-when-cross-origin', 'body': 'consularid=3&exitid=1&servicetypeid=1&calendarType=2&totalperson=1', 'method': 'POST', 'mode': 'cors', 'credentials': 'include' }) .then(res => res.text()) .then(data => { obj = data; resolve(obj); }) .catch(error => { reject(error); }); }); """ obj_variable = sb.execute_script(script)
错误信息
Message: script timeout (Session info: chrome=116.0.5845.141) Stacktrace: GetHandleVerifier [0x00007FF61E0352A2+57122] (No symbol) [0x00007FF61DFAEA92] (No symbol) [0x00007FF61DE7E25D] (No symbol) [0x00007FF61DEEF314] (No symbol) [0x00007FF61DED6FDA] (No symbol) [0x00007FF61DEEEB82] (No symbol) [0x00007FF61DED6DB3] (No symbol) [0x00007FF61DEAD2B1] (No symbol) [0x00007FF61DEAE494] GetHandleVerifier [0x00007FF61E2DEF82+2849794] GetHandleVerifier [0x00007FF61E331D24+3189156] GetHandleVerifier [0x00007FF61E32ACAF+3160367] GetHandleVerifier [0x00007FF61E0C6D06+653702] (No symbol) [0x00007FF61DFBA208] (No symbol) [0x00007FF61DFB62C4] (No symbol) [0x00007FF61DFB63F6] (No symbol) [0x00007FF61DFA67A3] BaseThreadInitThunk [0x00007FFAFEF07614+20] RtlUserThreadStart [0x00007FFB007C26B1+33]
解决方案
1. 调整SeleniumBase的脚本超时时间
execute_script方法支持传入timeout参数(单位:秒),用来覆盖默认的短超时限制。把超时时间设置得足够长,比如10秒:
obj_variable = sb.execute_script(script, timeout=10)
2. 给Fetch请求本身添加超时控制
使用浏览器原生的AbortController给fetch请求单独设置超时,避免因为Selenium的超时提前终止脚本。修改你的JS脚本如下:
return new Promise((resolve, reject) => { var csrf = document.querySelector('meta[name="csrf-token"]').content; // 创建AbortController,设置10秒超时(可根据需求调整) const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); fetch("MyUrl", { 'headers': { 'accept': '/', 'accept-language': 'en-US,en;q=0.9', 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 'sec-ch-ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'x-csrf-token': csrf, 'x-requested-with': 'XMLHttpRequest' }, 'referrer': 'MyUrl', 'referrerPolicy': 'strict-origin-when-cross-origin', 'body': 'consularid=3&exitid=1&servicetypeid=1&calendarType=2&totalperson=1', 'method': 'POST', 'mode': 'cors', 'credentials': 'include', 'signal': controller.signal // 关联AbortController信号 }) .then(res => res.text()) .then(data => { clearTimeout(timeoutId); // 请求成功,清除超时定时器 resolve(data); }) .catch(error => { clearTimeout(timeoutId); if (error.name === 'AbortError') { reject(new Error('Fetch请求超时')); } else { reject(error); } }); });
3. 双重保障(推荐)
同时设置execute_script的超时和fetch自身的超时,既避免Selenium提前终止脚本,也能主动控制请求的最长等待时间,更稳妥。
内容的提问来源于stack exchange,提问作者Mohammad Jami
相关产品推荐
相关产品推荐

