正如 Puppeteer 获取 http 请求的响应 一文里提到的方法,除了获取 HTTP 响应以外,还能获取 WebSocket 响应。因为有些页面通过 WebSocket 实现异步传输,仅仅从HTTP通道上获取响应是不够的,如何使用 Puppeteer 得到 WebSocket 响应内容,本文讨论一种方法。
基本原理
截止目前,Puppeteer 没有提供原生的用于处理 WebSocket 的 API 接口。只能通过更底层的 Chrome DevTool Protocol (CDP) 协议获得。
Puppeteer 使用 CDPSession
对象处理 CDP 协议相关
获取 WebSocket 响应
下面这段代码可以将接收到的 WebSocket 响应打印在控制台上:
// 打开浏览器,打开新页面
browser = await puppeteer.launch()
page = await browser.newPage()
// 创建 CDP 对象
const client = await page.target().createCDPSession()
// 打开网络跟踪,允许网络事件通知到浏览器
await client.send('Network.enable')
// 订阅收到 WebSocket 的事件,响应包含在 params 参数中
client.on('Network.webSocketFrameReceived',
function(params){
console.log(params.response.payloadData)
}
})
// 开始浏览
await page.goto(url)
上面这段代码首先启用了网络跟踪 Network.enable
,再订阅了 Network.webSocketFrameReceived
事件,当有进来的 WebSocket 帧时会触发,注意:包括握手、心跳帧,都会触发该事件。
其他事件
下面这段代码,可以观察到 WebSocket 的各种事件:
browser = await puppeteer.launch()
page = await browser.newPage()
const client = await page.target().createCDPSession()
await client.send('Network.enable')
client.on('Network.webSocketCreated',
function(params){
console.log(`创建 WebSocket 连接:${params.url}`)
}
)
client.on('Network.webSocketClosed',
function(params){
console.log(`WebSocket 连接关闭`)
}
)
client.on('Network.webSocketFrameSent',
function(params){
console.log(`发送 WebSocket 消息:${params.response.payloadData}`)
}
)
client.on('Network.webSocketFrameReceived',
function(params){
console.log(`收到 WebSocket 消息:${params.response.payloadData}`)
}
)
client.on('Network.webSocketWillSendHandshakeRequest',
function(params){
console.log(`准备发送 WebSocket 握手消息`)
}
)
client.on('Network.webSocketHandshakeResponseReceived',
function(params){
console.log(`接收到 WebSocket 握手消息`)
}
)
// 开始浏览
await page.goto(url)
Promise 化
外面包一层 Promise 后,可以方便的使用 await 得到响应结果,放在其他的同步语句中。具体来说,首先准备类似下面的函数:
function getWebSocketResponse(resolve, reject){
client.on('Network.webSocketFrameReceived', (params)=>{
resolve(params.response.payloadData)
})
}
然后在测试用例里可以像下面这么写:
describe('获取ws响应', function() {
it('检查 ws 响应中的值', async function(){
//其他语句
wsResponse = new Promise(getWebSocketResponse)
await page.goto(url, {waitUntil: 'networkidle0'})
response = await wsResponse
expect(response).to.equal(someValue)
})
})
这样,测试用例就可以写的很简洁、易读。
(完)
如果您对本文有疑问或者寻求合作,欢迎 联系邮箱 。邮箱已到剪贴板
标签: PUPPETEER
给个免费的赞吧~
精彩评论
本站 是个人网站,采用 署名协议 CC-BY-NC 授权。
欢迎转载,请保留原文链接 https://www.lfhacks.com/tech/puppeteer-websocket/ ,且不得用于商业用途。