QWebView 拦截http请求,获取post数据
QWebView作为QT中自带的浏览器控件,使用简单方便,而功能强大。并且很容易通过扩展实现一些定制化需求。
实际业务中遇到一个需求:需要加载某个网页,待用户选择表单选项并提交之后,拦截HTTP请求,获取其Post数据,加以修改 后重新提交请这求。
查阅QT的官方文档,并没有找到相关功能可以实现,而网上这方面的资料也是少之又少,所以特意整理出来方便大家。
注意事项:
QWebView只在QT5.5以下的版本中存在,在QT5.6之上的版本中已经被QWebEngineView取代。
另外,QT的MINGW版本中也没有webenginewidgets模块,需要自己编译MSVC版本自带此模块。
示例中使用QT版本号:Qt 5.5.1 (MSVC 2013, 32 bit)
几个主要函数:
1.void QWebPage::setNetworkAccessManager(QNetworkAccessManager * manager)
void QWebPage::setNetworkAccessManager(QNetworkAccessManager * manager)
Sets the QNetworkAccessManager manager responsible for serving network requests for this QWebPage.
Note: It is currently not supported to change the network access manager after the QWebPage has used it. The results of doing this are undefined.
See also networkAccessManager().
通过这个函数将manager设置成我们自己子类化之后的QNetworkAccessManager,方便拦截。
2.virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0)
QNetworkReply * QNetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0)
Returns a new QNetworkReply object to handle the operation op and request req. The device outgoingData is always 0 for Get and Head requests, but is the value passed to post() and put() in those operations (the QByteArray variants will pass a QBuffer object).
The default implementation calls QNetworkCookieJar::cookiesForUrl() on the cookie jar set with setCookieJar() to obtain the cookies to be sent to the remote server.
The returned object must be in an open state.
通过重写此子类化函数,我们在自己的子类化的类中既可以获取到我们想要的内容。
此函数的三个参数:
参数1:OPeration op是一个枚举类型,对应定义值如下:
我们想要的post请求对应的op=4.
参数2:QNetWorkRequest& req.请求对象,包含URL,设置的其他head选项。
参数3:QIODevice* outgongingData 。这个参数只有当是post或者put请求时才有内容,其他情况下值为0.
以登陆百度账户为例:
在调试窗口可看到拦截的内容:
代码:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWebView>
#include <QUrl>
#include <QVBoxLayout>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QWebView* m_pWebView;
QWidget *centralWidget;
QVBoxLayout *verticalLayout_2;
QVBoxLayout *verticalLayout;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <mnetworkaccessmanager.h>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
m_pWebView = new QWebView(this);
QNetworkAccessManager *oldManager = m_pWebView->page()->networkAccessManager();
MNetworkAccessManager *newManager = new MNetworkAccessManager(oldManager, this);
m_pWebView->page()->setNetworkAccessManager(newManager);
m_pWebView->page()->setForwardUnsupportedContent(true);
m_pWebView->load(QUrl("https://www.baidu.com/"));
this->setCentralWidget(m_pWebView);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
}
#ifndef MNETWORKACCESSMANAGER_H
#define MNETWORKACCESSMANAGER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QNetworkRequest>
class MNetworkAccessManager : public QNetworkAccessManager
{
Q_OBJECT
public:
explicit MNetworkAccessManager(QNetworkAccessManager *manager, QObject *parent);
protected:
QNetworkReply * createRequest(QNetworkAccessManager::Operation operation,
const QNetworkRequest &request, QIODevice *device);
};
#endif // MNETWORKACCESSMANAGER_H
#include "mnetworkaccessmanager.h"
#include "QDebug"
#include <QBuffer>
MNetworkAccessManager::MNetworkAccessManager(QNetworkAccessManager *manager, QObject *parent)
{
setCache(manager->cache());
setCookieJar(manager->cookieJar());
setProxy(manager->proxy());
setProxyFactory(manager->proxyFactory());
}
QNetworkReply *MNetworkAccessManager::createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice *device)
{
if(device)
{
qDebug()<<(int)operation<<request.url();
//qDebug()<<device->readAll();
//这里读取过之后 QIODevice 就不管用了,要重新设置,不然网站接收不到请求
QByteArray bytes=device->readAll();
qDebug()<<bytes;
QBuffer * pDeVice=new QBuffer(this);
pDeVice->setData(bytes);
return QNetworkAccessManager::createRequest(operation, request, pDeVice);
}
else
{
return QNetworkAccessManager::createRequest(operation, request, device);
}
}
参考:
https://blog.csdn.net/davidsu33/article/details/51058905
完整工程:https://download.csdn.net/download/lacoucou/10440360
上一篇: 数据库索引采用B树和B+树的原因
推荐阅读
-
js发送请求方法(js发送post请求获取数据)
-
Scrapy-Redis结合POST请求获取数据的方法示例
-
js发送请求方法(js发送post请求获取数据)
-
php获取通过http协议post提交过来xml数据及解析xml
-
Android拦截并获取WebView内部POST请求参数的实现方法
-
解决Vue axios post请求,后台获取不到数据的问题方法
-
微信小程序授权 获取用户的openid和session_key【后端使用java语言编写】,我写的是get方式,目的是测试能否获取到微信服务器中的数据,后期我会写上post请求方式。
-
spring boot拦截器中获取request post请求中的参数
-
微信小程序wx.request使用POST请求时后端无法获取数据解决办法
-
Java进阶篇5_SpringMVC的简介、SpringMVC的组件解析、SpringMVC的数据响应、SpringMVC获取请求数据、SpringMVC拦截器、SpringMVC异常处理机制