我在Python3上遇到PyQt5的QWebEngineUrlRequestInterceptor问题,更重要的是setHttpHeader函数。这是我的代码:
class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
def __init__(self, parent=None):
super().__init__(parent)
def interceptRequest(self, info):
info.setHttpHeader("X-Frame-Options", "ALLOWALL")
print(info.requestUrl())
不幸的是,使用这个函数的正确方法似乎绝对无处可去,因此我不得不求助于尝试我能想到的所有可能方法,但无济于事。
我也尝试用QByteArray
包围setHttpHeader的参数,这导致QByteArray给我这个投诉......
Traceback (most recent call last):
File "test.py", line 30, in interceptRequest
info.setHttpHeader(QByteArray("X-Frame-Options"), QByteArray("ALLOWALL"))
TypeError: arguments did not match any overloaded call:
QByteArray(): too many arguments
QByteArray(int, str): argument 1 has unexpected type 'str'
QByteArray(Union[QByteArray, bytes, bytearray]): argument 1 has unexpected type 'str'
我还尝试使用.encode('ascii')
甚至.encode('utf-8')
对字符串进行编码。虽然都没有引发错误,但标题也拒绝更改,这使我相信返回的值与函数不兼容。
更新:即使QByteArray(b"X-Frame-Options")
也未设置标头。 js: Refused to display 'https://www.google.co.uk/?gfe_rd=cr&dcr=0&ei=rX2gWtDJL8aN8Qfv3am4Bw' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.
是我从WebEngine获得的错误。
要添加的注释,我100%确定正在调用interceptRequest
。我可以看到终端中print
电话的输出。
[更新链接]处的完整MCVE代码:https://paste.ee/p/Y0mRs
答案 0 :(得分:3)
首先,问题是为什么现有代码不起作用?
class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
def __init__(self, parent=None):
super().__init__(parent)
def interceptRequest(self, info):
info.setHttpHeader("X-Frame-Options", "ALLOWALL")
print(info.requestUrl())
现在,当您安装UrlRequestInterceptor
时,它无论如何都是请求拦截器。由WebEngineView
发起的请求通过此传递,您可以使用它做很多事情
现在,当您拥有info.setHttpHeader("X-Frame-Options", "ALLOWALL")
时,它会将其添加到请求中而不是响应中。这可以通过将网址更改为http://postman-echo.com/get
来验证,您将得到以下回复
{
"args": {
},
"headers": {
"host": "postman-echo.com",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip, deflate",
"cookie": "sails.sid=s%3AXNukTzCE5ucYNEv_NB8ULCf4esVES3cW.%2BmpA77H2%2F%2B6YcnypvZ7I8RQFvVJrdOFs8GD%2FPymF0Eo",
"if-none-match": "W/\"1e1-rYSDjZun8qsI1ZojoxMuVg\"",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.10.1 Chrome/61.0.3163.140 Safari/537.36",
"x-frame-options": "ALLOW",
"x-forwarded-port": "80",
"x-forwarded-proto": "http"
},
"url": "http://postman-echo.com/get"
}
但是在响应方面没有任何改变,你仍然拥有原始请求实际返回的内容。
使用QWebView
,可以安装QNetworkAccessManager
并返回带有修改后回复的QNetworkReply
。
How to write content to QNetworkReply (was: QWebview with generated content)
但是,如果您阅读了Porting from Qt WebKit to Qt WebEngine指南,则需要注意一个重要的区别
Qt WebEngine不与QNetworkAccessManager交互
某些Qt网络类如QAuthenticator被重用于它们的接口,但与Qt WebKit不同,Qt WebEngine有自己的HTTP实现,无法通过QNetworkAccessManager。
仍支持QNetworkAccessManager的信号和方法已移至QWebEnginePage类。
我挖了许多线程,要求采用响应修改方法。不幸的是,所有人都没有回答
Capture server response with QWebEngineView
QWebEngineView modify web content before render
https://forum.qt.io/topic/81450/capture-client-request-headers-with-qwebengineview
Intercept AJAX POST request and read data using QWebEngine?
所以这不容易。但是我认为有一种解决方法可行,但我无法验证它
方法是添加新的scheme
网址处理程序
self.conn_handler = AppSchemeHandler()
self.profile.installUrlSchemeHandler("conapp".encode(), self.conn_handler)
self.webpage = MyQWebEnginePage(self.profile, self.view)
现在我们更新拦截器,以便修改google url以将请求重定向到我们的处理程序
class WebEngineUrlRequestInterceptor(QWebEngineUrlRequestInterceptor):
def __init__(self, parent=None):
super().__init__(parent)
def interceptRequest(self, info):
info.setHttpHeader(b'x-frame-options', b'ALLOW')
print(info.requestUrl())
if str(info.requestUrl().host()) == "google.com":
url = info.requestUrl().toString()
item = url.split("/")[-1]
info.redirect(QUrl(r"conapp://webresource?url=" + url))
然后在我们的方案处理程序
中class AppSchemeHandler(QWebEngineUrlSchemeHandler):
def __init__(self, parent=None):
super().__init__(parent)
def requestStarted(self, request):
url = request.requestUrl().toString().replace("conapp://webresource?url=", "")
response = QWebEngineHttpRequest(QUrl(url))
# Do something here which returns the response back to the url
我们阅读回复并将其发回的部分是我还没有找到任何地方的例子