【问题标题】:How to use puppeteer to dump WebSocket data如何使用 puppeteer 转储 WebSocket 数据
【发布时间】:2018-06-30 17:41:18
【问题描述】:

我想在这个页面https://upbit.com/exchange?code=CRIX.UPBIT.KRW-BTC获取websocket数据,它的websocket URL是动态的,只在第一次连接时有效,第二次连接它就不会再发送数据了。

所以我想知道也许 headless chrome 可以帮助我监控 websocket 数据。

有什么想法吗?谢谢!

【问题讨论】:

    标签: websocket puppeteer google-chrome-headless


    【解决方案1】:

    您实际上不需要为此做任何复杂的事情。该 URL 虽然看起来是动态的,但通过代码也可以正常工作。它不起作用的原因是您需要了解后台发生的事情。

    首先让我们看一下网络选项卡。

    cookie 和来源可能对连接很重要。所以我们记下了这些。

    现在让我们看看套接字上的数据交换

    如果您查看帧,初始帧接收o 作为数据,这可能表明连接正在打开。然后网站向socket发送一些数据,这可能与我们要查询的内容有关。当连接暂停一段时间后,套接字接收h 作为数据。这可能表示暂停或其他情况(如第二张图片所示)

    为了得到准确的数据,我们在代码中放置了一个断点

    然后在控制台打印值

    现在我们有足够的信息可以进入编码部分。我发现下面是一个很好的 websocket 库

    https://github.com/websockets/ws

    所以我们做一个

    yarn add ws || npm install ws --save
    

    现在我们编写代码

    const WebSocket = require("ws")
    const ws = new WebSocket("wss://example.com/sockjs/299/enavklnl/websocket",null,{
        headers: {
            "Cookie":"<cookie data noted earlier>",
            "User-Agent": "<Your browser agent>"
        },
        origin: "https://example.com",
    })
    const opening_message = '["[{\\"ticket\\":\\"ram macbook\\"},{\\"type\\":\\"recentCrix\\",\\"codes\\":[\\"CRIX.UPBIT.KRW-BTC\\",\\"CRIX.BITFINEX.USD-BTC\\",\\"CRIX.BITFLYER.JPY-BTC\\",\\"CRIX.OKCOIN.CNY-BTC\\",\\"CRIX.KRAKEN.EUR-BTC\\",\\"CRIX.UPBIT.KRW-DASH\\",\\"CRIX.UPBIT.KRW-ETH\\",\\"CRIX.UPBIT.KRW-NEO\\",\\"CRIX.UPBIT.KRW-BCC\\",\\"CRIX.UPBIT.KRW-MTL\\",\\"CRIX.UPBIT.KRW-LTC\\",\\"CRIX.UPBIT.KRW-STRAT\\",\\"CRIX.UPBIT.KRW-XRP\\",\\"CRIX.UPBIT.KRW-ETC\\",\\"CRIX.UPBIT.KRW-OMG\\",\\"CRIX.UPBIT.KRW-SNT\\",\\"CRIX.UPBIT.KRW-WAVES\\",\\"CRIX.UPBIT.KRW-PIVX\\",\\"CRIX.UPBIT.KRW-XEM\\",\\"CRIX.UPBIT.KRW-ZEC\\",\\"CRIX.UPBIT.KRW-XMR\\",\\"CRIX.UPBIT.KRW-QTUM\\",\\"CRIX.UPBIT.KRW-LSK\\",\\"CRIX.UPBIT.KRW-STEEM\\",\\"CRIX.UPBIT.KRW-XLM\\",\\"CRIX.UPBIT.KRW-ARDR\\",\\"CRIX.UPBIT.KRW-KMD\\",\\"CRIX.UPBIT.KRW-ARK\\",\\"CRIX.UPBIT.KRW-STORJ\\",\\"CRIX.UPBIT.KRW-GRS\\",\\"CRIX.UPBIT.KRW-VTC\\",\\"CRIX.UPBIT.KRW-REP\\",\\"CRIX.UPBIT.KRW-EMC2\\",\\"CRIX.UPBIT.KRW-ADA\\",\\"CRIX.UPBIT.KRW-SBD\\",\\"CRIX.UPBIT.KRW-TIX\\",\\"CRIX.UPBIT.KRW-POWR\\",\\"CRIX.UPBIT.KRW-MER\\",\\"CRIX.UPBIT.KRW-BTG\\",\\"CRIX.COINMARKETCAP.KRW-USDT\\"]},{\\"type\\":\\"crixTrade\\",\\"codes\\":[\\"CRIX.UPBIT.KRW-BTC\\"]},{\\"type\\":\\"crixOrderbook\\",\\"codes\\":[\\"CRIX.UPBIT.KRW-BTC\\"]}]"]'
    ws.on('open', function open() {
        console.log("opened");
    });
    
    ws.on('message', function incoming(data) {
        if (data == "o" || data == "h") {
            console.log("sending opening message")
            ws.send(opening_message)
        }
        else {
            console.log("Received", data)
    
        }
    });
    

    然后运行我们得到的代码

    现在如果我替换

    const ws = new WebSocket("wss://example.com/sockjs/299/enavklnl/websocket",null,{
        headers: {
            "Cookie":"<cookie data noted earlier>",
            "User-Agent": "<Your browser agent>"
        },
        origin: "https://example.com",
    })
    

    const ws = new WebSocket("wss://example.com/sockjs/299/enavklnl/websocket")
    

    这意味着 cookiesorigin 从来不需要这样。但我仍然建议您使用它们

    【讨论】:

    • 如果您只想使用 puppeteer 执行此操作,那么这可能不是您要寻找的答案
    • 惊人的答案,非常详细和启发性的分析。我会在另一个问题stackoverflow.com/q/48364820/381712 下采纳你的答案,对于这个问题,我仍然想知道如何通过 Puppeteer 或无头 Chrome 转储数据
    • 有没有办法只用puppeteer 做到这一点?
    • @Stophface,puppeteer 正在自动化浏览器,所以只要你获取页面上的数据进行捕获,你就可以做到。如果没有,那么您将不得不诉诸这种方式
    • 您如何理解断点的放置位置?我在 js 文件中找不到 '.send(' 短语。
    【解决方案2】:
    const client = page._client
    
    client.on('Network.webSocketCreated', ({requestId, url}) => {
      console.log('Network.webSocketCreated', requestId, url)
    })
    
    client.on('Network.webSocketClosed', ({requestId, timestamp}) => {
      console.log('Network.webSocketClosed', requestId, timestamp)
    })
    
    client.on('Network.webSocketFrameSent', ({requestId, timestamp, response}) => {
      console.log('Network.webSocketFrameSent', requestId, timestamp, response.payloadData)
    })
    
    client.on('Network.webSocketFrameReceived', ({requestId, timestamp, response}) => {
      console.log('Network.webSocketFrameReceived', requestId, timestamp, response.payloadData)
    })
    

    直接使用 DevTools 协议 - https://chromedevtools.github.io/devtools-protocol/tot/Network#event-webSocketClosed

    【讨论】:

    • 如何用模拟数据响应?
    • 目前看来唯一的方法是拦截 websocket 连接请求并将其重定向到您自己的 websocket 服务器。也许这会有所帮助forum.katalon.com/t/…
    【解决方案3】:

    我认为 puppeteer 尚不支持此功能,但较低级别的协议支持https://chromedevtools.github.io/devtools-protocol/tot/Network/#event-webSocketFrameSenthttps://chromedevtools.github.io/devtools-protocol/tot/Network#type-WebSocketResponse。这意味着如果您愿意,您也可以在库中自己实现它。

    【讨论】:

    • 感谢您的回答,这可能是一个很好的线索,我会调查一下
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 2011-07-26
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多