78275


ウェブアプリの ajax 通信の内容を自動でローカルファイル等にダンプしたいです

tcpdump で特定のドメインIPがソースのパケットをファイルにダンプすればできなくはなさそうですが  
HTTP ヘッダとかを分離しないといけないので大変です

chrome の開発ツールで  
ネットワーク > XHR > Name が特定のエンドポイント  
の場合のレスポンスボディだけを  
延々とファイルに出力し続けるような簡単な方法はないでしょうか

通信するのは HTML5 (JavaScript) なのでそこに割り込むような  
chrome extension だったりブックマークレットだったりでもいいし  
ブラウザプラグインでも パケットキャプチャツールでも 実現方法は何でもいいです

* * *

ブラウジングしながら特定のレスポンスが出たのをトリガーにして処理するようなプログラムを書きたいので、とにかく手動操作なしでローカル上のプログラムからレスポンスを読める状態にしたいorレスポンスを渡したいです


CC BY-SA 4.0
2021-05-23T13:53:33.913
76026
2022-08-24T04:10:31.100
2021-06-17T06:18:01.437
3060
question
javascript html5 google-chrome
ブラウザで開いてるページの ajax 通信の内容を自動でローカルファイルに残したい


DevToolsはHARファイルのエクスポート・インポートが可能です。  
延々と出力することは出来ないですが、一定時間キャプチャしてエクスポートすることで十分であれば試してみてください。

[トラブルシューティング用のHARファイルの生成](https://support.zendesk.com/hc/ja/articles/204410413-%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E7%94%A8%E3%81%AEHAR%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E7%94%9F%E6%88%90)

>   1. Google Chromeを開き、問題が発生しているページに移動します。
>   2. 縦の省略符号ボタンを探して、「その他のツール」>「デベロッパーツール」を選択します。
>   3. 開いたパネルから、「Network」タブを選択します。
>   4.
> タブの左端にある丸い記録（）ボタンを探して、ボタンが赤くなっていることを確かめます。ボタンが灰色になっている場合、1回クリックして記録を開始します。
>   5. 「Preserve log」ボックスをチェックします。
>   6. Clearボタン（）をクリックして、「Network」タブから既存のログをすべて消去します。
>   7. ネットワークリクエストが記録されている間に、先ほど発生した問題を再現します。  
>  8.問題を再現できたら、Chromeの場合は「Download」をクリックします。ファイルに次の名前を付けてコンピュータに保存します：「HAR
> with Content」
>


CC BY-SA 4.0
2021-05-24T05:28:25.370
76037
2021-05-24T05:28:25.370
2238
76026
answer


chrome://net-export/  
これを使うのはどうですか？


CC BY-SA 4.0
2021-06-01T04:33:29.050
76240
2021-06-01T04:33:29.050
76026
answer


Windowsだったら、Fiddlerというツールはどうでしょう。

<https://www.telerik.com/fiddler/fiddler-classic>


CC BY-SA 4.0
2021-06-18T13:00:45.240
77644
2021-06-18T13:00:45.240
9575
76026
answer


[mitmproxy](https://mitmproxy.org/)の[アドオン機能](https://docs.mitmproxy.org/stable/addons-
overview/)で実現できるかと思います。

例)  
`save_body.py`:

[code]

    import mitmproxy
    def response(flow):
        if flow.request.pretty_url.startswith("https://www3.nhk.or.jp/news/special/coronavirus/data/") and flow.response.headers["content-type"].startswith("application/json"):
            with open("responses.txt","ab") as f:
                f.write(flow.response.content)
    
[/code]

確認手順:  
`mitmdump`コマンドでプロキシサーバを起動し、

[code]

    mitmdump -s save_body.py
    
[/code]

`mitmproxy` をプロキシに設定したウェブブラウザで
<https://www3.nhk.or.jp/news/special/coronavirus/data/> へアクセス。

* * *

※ Pythonの文法を知らないので次を参考にしました:

  * [Save body response from specific URL to file and decode it using mitmproxy](https://stackoverflow.com/a/48158427/4506703) \- Stack Overflow


CC BY-SA 4.0
2021-07-18T05:07:52.280
78265
2021-07-18T05:07:52.280
2808
76026
answer


> ブラウジングしながら特定のレスポンスが出たのをトリガーにして処理するようなプログラムを書きたい

と言うことでしたら、 [puppeteer](https://www.npmjs.com/package/puppeteer) などを利用して、
[Chrome DevTools Protocol の Fetch
ドメイン](https://chromedevtools.github.io/devtools-protocol/tot/Fetch/)
を直叩きして、ブラウザ内の通信を片っ端から割り込んで、 ヘッダーやボディを横取りしてしまうのが、色々潰しがきいてオススメです。

以下の node.js を使った例では、 body バイナリを UTF-8
文字列にしてコンソールに出力していますが、もちろんファイルに保存する事も可能です。  
上記目的だと、むしろファイルに保存しない方が良いのでは？と想像しています。

[code]

    const puppeteer = require('puppeteer');
    
    (async () => {
        const browser = await puppeteer.launch({ headless: false, defaultViewport: null });
        const page = (await browser.pages())[0];
        try {
            const client = await page.target().createCDPSession();
            await client.send('Fetch.enable', { 'patterns': [{ 'urlPattern': '*', 'requestStage': 'Response' }] });
            client.on('Fetch.requestPaused', async (requestEvent) => {
                const { requestId, responseStatusCode, responseHeaders } = requestEvent;
                try {
                    if (!responseStatusCode) throw `responseStatusCode: ${responseStatusCode}`;
                    const response = await client.send('Fetch.getResponseBody', { requestId });
    
                    // dump response body
                    if (response.base64Encoded) {
                        console.log(new Buffer(response.body, 'base64').toString('utf-8'));
                    } else {
                        console.log(response.body);
                    }
    
                    await client.send('Fetch.fulfillRequest', { requestId, responseCode: responseStatusCode, responseHeaders, 'body': response.body });
                } catch {
                    await client.send('Fetch.continueRequest', { requestId });
                }
            });
    
            // wait for close
            await new Promise((resolve, reject) => page.on('close', resolve));
        } finally {
            (await browser.pages()).forEach(p => p.close());
            browser.close();
        }
    })();
    
[/code]

`client.send('Fetch.enable', ...);` のところで、
[urlPattern](https://chromedevtools.github.io/devtools-
protocol/tot/Fetch/#type-RequestPattern) を適切に設定してあげれば、
特定のエンドポイントだけハンドリングすることができます。

上記例では、 Chrome をバンドルしている puppeteer を使いましたが、 例えば別途インストール済みの Chrome を使うなら
[puppeteer-core](https://www.npmjs.com/package/puppeteer-core) を使うとか、
他の言語のバインディングを使うなどと言った選択肢があります。

Chrome DevTools Protocol ないし Remote Debugging Protocol はある程度標準化された仕様なので、
puppeteer 以外でも、 Selenium v4 など他のツールからも利用可能です。


CC BY-SA 4.0
2021-07-18T10:37:40.667
78275
2021-07-18T10:49:35.523
2021-07-18T10:49:35.523
8237
8237
76026
answer