Python Selenium提取元素文本的for循环耗时过长如何优化
问题根因
这段列表推导执行慢是必然结果:Selenium 中每调用一次 WebElement 的 .text 属性,都会单独向浏览器驱动发送一次跨进程HTTP请求,300个元素就对应300次独立IO请求,累计耗时自然会被拉到秒级,和Python本身的循环执行速度没有关系。
不要尝试用多线程并行读取元素.text提速,浏览器驱动对请求的处理基本是串行的,多线程只会增加额外开销,不会降低总耗时。
最优解决方案:通过JS批量提取文本,一次性返回结果
不要逐个元素调用.text,直接通过execute_script执行原生JavaScript,在浏览器渲染进程侧一次性遍历所有目标元素、提取文本值拼成数组返回,全程只有1次驱动通信请求,300个元素的提取耗时通常会降到10ms级别。
直接替换transValues函数中的对应逻辑即可:
def transValues(): global vatual while True: try: # 单次JS请求批量拉取所有目标文本,避免逐元素通信开销 vatual = driver.execute_script(""" const elements = document.getElementsByClassName('roulette-history-item__value-textsiwxWvFlm3ohr_UMS23f'); return Array.from(elements).map(el => el.textContent.trim()); """) console_print(vatual[0]) except: console_print("Erro ao transformar valores... persist") pass
提示:JS中
textContent和Selenium原生.text的返回规则略有差异,如果需要完全匹配Selenium.text的可见文本过滤逻辑,可以把JS里的el.textContent.trim()替换为el.innerText.trim(),执行速度依然比逐元素调用.text快几十倍。
额外优化点(修复现有代码的隐性问题)
- 三个线程直接读写
temp/vatual等全局变量没有加线程锁,很容易触发读写竞态:比如getValues还没完成元素列表赋值,transValues就开始读取,会拿到不完整数据甚至偶发抛错,给共享变量的读写加轻量线程锁即可解决。 getValues中对相同class的元素重复发起了两次查询(temp和vold使用的是完全相同的选择器),属于无意义的驱动IO开销,删除重复查询逻辑可直接减少一半对应步骤的耗时。- 高频轮询场景下,JS原生的
getElementsByClassName接口查询速度比querySelectorAll快30%以上,优先使用前者能进一步压缩采集耗时。
内容的提问来源于stack exchange,提问作者Gustavo Araújo
相关产品推荐
相关产品推荐

