You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Qt连接Headless Chrome获取XHR请求响应体(无需Fiddler)

不用Fiddler,用Qt连接Headless Chrome获取XHR响应体的方法

嘿,这个需求完全可以通过**Chrome DevTools Protocol(CDP)**来实现——Headless Chrome本身就支持通过这个协议暴露调试接口,Qt刚好能借助WebSocket和它建立通信,直接监听并抓取请求的响应体,全程不需要第三方抓包工具。下面给你一步步拆解实现思路和关键代码:

步骤1:启动开启CDP端口的Headless Chrome

首先你需要启动Headless Chrome时指定调试端口,这样Qt才能连接上它。在命令行执行:

chrome --headless=new --remote-debugging-port=9222 --disable-gpu

参数说明:

  • --headless=new:启用新版的无头模式(比旧版更稳定)
  • --remote-debugging-port=9222:指定CDP的调试端口,你可以改成其他未被占用的端口
  • --disable-gpu:禁用GPU加速,避免无头模式下的潜在问题

步骤2:用Qt获取CDP的WebSocket调试地址

Headless Chrome启动后,会在http://localhost:9222/json暴露当前所有调试目标的信息。你需要用Qt的QNetworkAccessManager请求这个接口,解析出目标页面的webSocketDebuggerUrl——这就是后续WebSocket连接的地址。

示例代码片段:

QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, &QNetworkAccessManager::finished, this, [=](QNetworkReply *reply) {
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray data = reply->readAll();
        QJsonArray jsonArray = QJsonDocument::fromJson(data).array();
        if (!jsonArray.isEmpty()) {
            QString wsUrl = jsonArray.first().toObject().value("webSocketDebuggerUrl").toString();
            // 拿到WebSocket地址后,下一步就是建立连接
            connectToCDP(wsUrl);
        }
    }
    reply->deleteLater();
});
manager->get(QNetworkRequest(QUrl("http://localhost:9222/json")));

步骤3:通过Qt WebSocket连接CDP并启用网络监听

拿到WebSocket地址后,用Qt的QWebSocket建立连接,连接成功后发送CDP的Network.enable命令,开启网络事件的监听。之后就能捕获所有请求的响应事件了。

示例代码:

// 可以在类中声明一个QSet来暂存待获取响应体的XHR请求ID
QSet<QString> m_pendingXhrRequests;

void connectToCDP(const QString &wsUrl) {
    QWebSocket *webSocket = new QWebSocket();
    connect(webSocket, &QWebSocket::connected, this, [=]() {
        // 发送Network.enable命令,开启网络监听
        QJsonObject enableCmd;
        enableCmd["id"] = 1;
        enableCmd["method"] = "Network.enable";
        webSocket->sendTextMessage(QJsonDocument(enableCmd).toJson(QJsonDocument::Compact));
    });

    // 监听CDP返回的消息
    connect(webSocket, &QWebSocket::textMessageReceived, this, [=](const QString &message) {
        QJsonObject msgObj = QJsonDocument::fromJson(message.toUtf8()).object();
        // 处理Network.responseReceived事件:记录请求ID,判断是否是XHR
        if (msgObj.value("method").toString() == "Network.responseReceived") {
            QJsonObject params = msgObj.value("params").toObject();
            QJsonObject response = params.value("response").toObject();
            QString requestId = params.value("requestId").toString();
            // 过滤XHR类型的请求
            if (response.value("type").toString() == "XHR") {
                m_pendingXhrRequests.insert(requestId);
            }
        }
        // 处理Network.loadingFinished事件:触发获取响应体的命令
        else if (msgObj.value("method").toString() == "Network.loadingFinished") {
            QString requestId = msgObj.value("params").toObject().value("requestId").toString();
            if (m_pendingXhrRequests.contains(requestId)) {
                // 发送Network.getResponseBody命令获取响应体
                QJsonObject getBodyCmd;
                getBodyCmd["id"] = 2;
                getBodyCmd["method"] = "Network.getResponseBody";
                getBodyCmd["params"] = QJsonObject({{"requestId", requestId}});
                webSocket->sendTextMessage(QJsonDocument(getBodyCmd).toJson(QJsonDocument::Compact));
                m_pendingXhrRequests.remove(requestId);
            }
        }
        // 处理Network.getResponseBody的返回结果
        else if (msgObj.value("id").toInt() == 2) {
            QJsonObject result = msgObj.value("result").toObject();
            QString body = result.value("body").toString();
            bool isBase64 = result.value("base64Encoded").toBool();
            if (isBase64) {
                // 如果是base64编码,解码成原始内容
                body = QString::fromUtf8(QByteArray::fromBase64(body.toUtf8()));
            }
            // 这里就是你要的XHR响应体了,可以做后续处理
            qDebug() << "XHR Response Body:" << body;
        }
    });

    webSocket->open(QUrl(wsUrl));
}

注意事项

  • 确保你的Qt项目已经添加了WebSocket模块,在.pro文件中加上QT += websockets
  • CDP的命令和事件可以参考官方的API列表,比如你还可以过滤特定URL的请求,或者监听请求发送事件
  • 处理响应体时要注意编码,如果base64Encoded为true,一定要先解码再使用
  • 记得在程序退出时关闭WebSocket连接,避免资源泄漏

内容的提问来源于stack exchange,提问作者Семен Сырцов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:28:30