Python/WebKit代码遗漏<tbody>标签求助:动态JS渲染异常
解决PyQt5渲染页面时缺失内容的幽灵数据问题
我之前处理过几乎一模一样的问题,你碰到的这个「幽灵数据」本质是页面动态渲染的时机问题——你的代码在页面初始加载完成就立刻抓取HTML,但表格的<tbody>内容是JavaScript后续动态生成的,这时候还没来得及渲染出来。
问题根源
QWebPage的loadFinished信号只是表示页面的初始HTML和静态资源加载完成,但很多现代页面会在这之后通过AJAX请求数据、DOM操作等方式动态生成内容。你的代码在loadFinished触发后立即调用toHtml(),自然拿不到还没被JS注入的<tbody>及其内容。
解决方案:等待JS完成渲染
这里有两种可靠的处理方式,你可以根据需求选择:
1. 固定延迟等待(简单直接)
给页面留足够的时间让JS执行完成,用QTimer.singleShot设置延迟后再抓取HTML:
import sys from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWebKitWidgets import QWebPage from PyQt5.QtWidgets import QApplication class Render(QWebPage): def __init__(self, url, wait_ms=3000): self.app = QApplication(sys.argv) QWebPage.__init__(self) self.wait_ms = wait_ms self.loadFinished.connect(self._on_load_finished) self.mainFrame().load(QUrl(url)) self.app.exec_() def _on_load_finished(self, result): # 延迟指定毫秒后再获取渲染完成的HTML QTimer.singleShot(self.wait_ms, self._extract_html) def _extract_html(self): self.frame = self.mainFrame() self.result = self.frame.toHtml() self.app.quit() url = 'https://cib.societegenerale.com/fileadmin/indices_feeds/ti_screen/index.html' # 可以根据页面加载速度调整等待时间,比如4000ms renderer = Render(url, wait_ms=4000) print(renderer.result)
2. 监听目标元素(精准可靠)
如果固定延迟不够稳定(比如网络波动导致加载速度变化),可以通过执行JS检查目标元素(<tbody>)是否存在,确认后再抓取HTML:
import sys from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWebKitWidgets import QWebPage from PyQt5.QtWidgets import QApplication class Render(QWebPage): def __init__(self, url): self.app = QApplication(sys.argv) QWebPage.__init__(self) self.loadFinished.connect(self._start_checking) self.mainFrame().load(QUrl(url)) self.app.exec_() def _start_checking(self, result): # 每隔500ms检查一次tbody是否存在 self.check_timer = QTimer() self.check_timer.timeout.connect(self._verify_tbody) self.check_timer.start(500) def _verify_tbody(self): # 执行JavaScript检查目标元素是否存在 tbody_exists = self.mainFrame().evaluateJavaScript( "document.querySelector('#watchlistTable tbody') !== null" ) if tbody_exists: self.check_timer.stop() self._extract_html() def _extract_html(self): self.frame = self.mainFrame() self.result = self.frame.toHtml() self.app.quit() url = 'https://cib.societegenerale.com/fileadmin/indices_feeds/ti_screen/index.html' renderer = Render(url) print(renderer.result)
额外建议
QtWebKit是比较老旧的模块了,对现代JavaScript的支持有限。如果你的项目可以升级,建议换成PyQt5中的QtWebEngineWidgets模块,它基于Chromium内核,对动态页面的渲染兼容性更好。
内容的提问来源于stack exchange,提问作者Josh Pilson
相关产品推荐
相关产品推荐

