页面收到的 HTTP 响应,用 Chrome 的开发者工具 DevTool 很容易能看到,但是如何以运行程序的方法,从 Chrome 中取得呢?本文讨论一种可行的方法。 基本原理 页面实体 Page,收到响应后,会触发 ‘reponse’ 事件,并且得到 响应实体 response,里面包含各类响应信息。 处理事件 下面这段代码可以将页面接收到的响应信息打印出来: // 打开浏览器,打开新页面 browser = await puppeteer.launch() page = await browser.newPage() // 订阅 reponse 事件,参数是一个 reponse 实体 page.on('response', function (response){ console.log(response.url()) } }) // 开始浏览 await page.goto(url) 上面的代码将每条响应的URL地址打印出来 响应的其他属性 响应的信息,可以从 response 实体提供的各类方法得到,比如 page.on('response', function (response){ console.log(response.url()) //显示响应的 URL,字符串 console.log(response.headers()) //显示响应的header对象 console.log(response.text()) //显示响应的body,Promise console.log(response.status()) //显示响应的状态码,数值型 console.log(response.ok()) //显示响应是否成功,布尔值 console.log(response.request()) //显示响应对应的 request 对象 } }) 响应的body 这里详细讨论如何获取 响应的 body. 从 上节 看出, response.text() 可以返回响应的body,但仅仅返回一个 Promise ,还需要稍微处理才能真正得到响应的内容。 基本用法 page.on('response', function (response){ response.text().then((body)=>{ console.log(body) }) } }) Promise 化 将上面的基本用法,包一层 Promise 后,可以用 await 方便的得到响应的body,具体来说,首先准备如下的函数: function getResponseBody(resolve, reject){ page.on('response', async function(response){ resolve(await response.text()) }) } 然后在测试用例里可以像下面这么写: describe('获取响应', function() { it('检查响应 body 中的值', async function(){ //其他语句 waitForResponse = new Promise(getResponseBody) await page.goto(url, {waitUntil: 'networkidle0'}) response = await waitForResponse expect(response).to.equal(someValue) }) }) 这样,测试用例就可以写的很简洁、易读。 过滤响应 上节的方法 中使用的Promise 在第一条响应产生后立即resolve,但是我们往往只关心我们期待的某一条响应,所以需要结合 reponse 的其他方法,达到过滤响应的目的。 比如,我们希望过滤从 /some/api 返回的响应,那么上面的 getResponseBody 函数可以这么写: function getResponseBody(resolve, reject){ page.on('response', async function(response){ if(response.url().includes('/some/api')){ resolve(await response.text()) } }) } WebSocket 响应 除了 HTTP 响应以外,如何获取 WebSocket 响应的方法,见 Puppeteer 获取 WebSocket 响应 一文