如何捕获QWebEngineView发起的HTTP请求?
修复QWebEngineView请求拦截与页面渲染问题
我想把QWebEngineView在导航时发送的所有HTTP请求(GET、POST等)保存到文件,就像Firefox里「检查 > 网络 > 保存为HAR文件」那样。我试了两段代码,目前只想先打印出请求,但都有问题:
- 第一段脚本能正常显示页面,但无法拦截请求
- 第二段脚本能捕获并显示请求,但窗口无法渲染
原始代码
第一段脚本(可渲染,无拦截)
# SCRIPT 1 import sys from PyQt6.QtCore import * from PyQt6.QtWebEngineCore import * from PyQt6.QtWidgets import * from PyQt6.QtWebEngineWidgets import * class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor): def interceptRequest(self, info: QWebEngineUrlRequestInfo): print() print("interceptRequest") print(info.requestUrl()) print(info.requestMethod()) class MainWindow(QMainWindow): def __init__(self): super().__init__() interceptor = WebEngineUrlRequestInterceptor() self.profile = QWebEngineProfile.defaultProfile() self.profile.setUrlRequestInterceptor(interceptor) print(self.profile) self.browser = QWebEngineView(self.profile, parent=self) self.setCentralWidget(self.browser) self.browser.setUrl(QUrl("https://google.com")) self.show() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() app.exec()
第二段脚本(可拦截,无渲染)
# SCRIPT 2 import sys from PyQt6.QtCore import * from PyQt6.QtWebEngineCore import * from PyQt6.QtWebEngineWidgets import * from PyQt6.QtWidgets import * class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor): def interceptRequest(self, info: QWebEngineUrlRequestInfo): print() print("interceptRequest") print(info.requestUrl()) print(info.requestMethod()) class MyWebEnginePage(QWebEnginePage): def acceptNavigationRequest(self, url, _type, isMainFrame): print("acceptNavigationRequest") print(url) return QWebEnginePage.acceptNavigationRequest(self, url, _type, isMainFrame) if __name__ == "__main__": app = QApplication(sys.argv) browser = QWebEngineView() interceptor = WebEngineUrlRequestInterceptor() profile = QWebEngineProfile() profile.setUrlRequestInterceptor(interceptor) page = MyWebEnginePage(profile) page.setUrl(QUrl("https://google.com")) browser.setPage(page) browser.showMaximized() app.exec()
问题原因
- 第一段脚本问题:
QWebEngineProfile.defaultProfile()是全局默认配置,可能在你设置拦截器之前就已经被Qt内部初始化完成,此时再绑定拦截器不会生效。 - 第二段脚本问题:创建
QWebEngineProfile时未指定父对象,Python的垃圾回收机制会提前回收这个Profile对象,导致依赖它的页面无法正常渲染。
修复方案
方案一:修复第一段脚本(自定义Profile)
改用自定义Profile替代默认配置,确保拦截器在Profile被使用前就完成绑定:
import sys from PyQt6.QtCore import QUrl from PyQt6.QtWebEngineCore import QWebEngineUrlRequestInterceptor, QWebEngineUrlRequestInfo, QWebEngineProfile from PyQt6.QtWidgets import QApplication, QMainWindow from PyQt6.QtWebEngineWidgets import QWebEngineView class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor): def interceptRequest(self, info: QWebEngineUrlRequestInfo): print("\n=== 拦截到HTTP请求 ===") print(f"请求地址: {info.requestUrl().toString()}") print(f"请求方法: {info.requestMethod().data().decode()}") class MainWindow(QMainWindow): def __init__(self): super().__init__() # 创建自定义Profile并绑定父对象,避免被提前回收 self.profile = QWebEngineProfile("custom_request_profile", self) self.interceptor = WebEngineUrlRequestInterceptor() self.profile.setUrlRequestInterceptor(self.interceptor) self.browser = QWebEngineView(self) # 为浏览器页面设置自定义Profile page = self.browser.page() page.setProfile(self.profile) self.setCentralWidget(self.browser) self.browser.setUrl(QUrl("https://google.com")) self.show() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() app.exec()
方案二:修复第二段脚本(给Profile加父对象)
给QWebEngineProfile指定父对象,确保其生命周期与浏览器视图一致:
import sys from PyQt6.QtCore import QUrl from PyQt6.QtWebEngineCore import QWebEngineUrlRequestInterceptor, QWebEngineUrlRequestInfo, QWebEngineProfile from PyQt6.QtWebEngineWidgets import QWebEngineView, QWebEnginePage from PyQt6.QtWidgets import QApplication class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor): def interceptRequest(self, info: QWebEngineUrlRequestInfo): print("\n=== 拦截到HTTP请求 ===") print(f"请求地址: {info.requestUrl().toString()}") print(f"请求方法: {info.requestMethod().data().decode()}") class MyWebEnginePage(QWebEnginePage): def acceptNavigationRequest(self, url, _type, isMainFrame): print("\n=== 导航请求触发 ===") print(f"导航地址: {url.toString()}") return super().acceptNavigationRequest(url, _type, isMainFrame) if __name__ == "__main__": app = QApplication(sys.argv) browser = QWebEngineView() interceptor = WebEngineUrlRequestInterceptor() # 给Profile设置父对象为浏览器视图,防止被垃圾回收 profile = QWebEngineProfile("custom_profile", browser) profile.setUrlRequestInterceptor(interceptor) page = MyWebEnginePage(profile) page.setUrl(QUrl("https://google.com")) browser.setPage(page) browser.showMaximized() app.exec()
后续扩展(生成HAR文件)
如果要实现类似Firefox的HAR文件保存,可以在interceptRequest方法中收集请求的详细信息(如请求头、参数、响应数据等),按照HAR文件格式规范组织成JSON结构,最后写入文件即可。
内容的提问来源于stack exchange,提问作者zigma12
相关产品推荐
相关产品推荐

