页面加载时,我试图等待页面发出的某些AJAX请求,然后返回其响应的JSON正文。即使在侦听器中满足“响应”事件的条件之后,我的代码也不会停止遍历每个响应。
找到要返回的响应后,如何捕获响应中的JSON,停止执行进一步加载页面的操作,然后返回JSON?
async function runScrape() {
const browser = await browserPromise;
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
await page.setDefaultTimeout(60000);
let apiResponse;
page.on('response', async response => {
let url = await response.url();
let status = await response.status();
console.info(status + " NETWORK CALL: " + url);
if ( url.match(requestPattern) ) {
apiResponse = await response.text();
await page.evaluate(() => window.stop());
}
});
await page.goto(req.query.url);
console.log("API RESPONSE:\n" + apiResponse);
return apiResponse
}}
===更新===
这是最终起作用的解决方案。由于要抓取页面的特定行为,因此似乎需要此方法。
async function runScrape() {
const browser = await browserPromise;
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
await page.setDefaultTimeout(60000);
await page.setRequestInterception(true);
let JSONResponse;
page.on('response', async response => {
if ( !JSONResponse && response.url().match(requestPattern) ) {
JSONResponse = await response.text();
}
});
page.on('request', request => {
if (request.resourceType() === 'image' || request.resourceType() === 'stylesheet') request.abort()
else request.continue()
});
await page.goto(scrapeURL, {waitUntil: 'networkidle2'});
await page.close();
return JSONResponse
}
runScrape()
.then( response => {
res.setHeader("content-type", "application/json");
res.status(200).send(response);
})
.catch(err => {
let payload = {"errorType": err.name, "errorMessage": err.message+"\n"+err.stack};
console.error(JSON.stringify(payload));
res.status(500).json(payload);
});
答案 0 :(得分:0)
我将其简化为一个page.on('response'...
,在这里我们用String.includes()
寻找所需的请求模式。
确定响应后,我们可以使用await page.evaluate(() => window.stop())
模拟浏览器的“停止加载此页面” 按钮。 window.stop()
方法不会关闭浏览器,只是停止网络请求。
let resp
page.on('response', async response => {
if (response.url().includes(requestPattern)) {
resp = await response.json()
await page.evaluate(() => window.stop())
}
})
await page.goto(req.query.url, { waitUntil: 'networkidle0' } )
console.log(resp)
为避免undefined
响应,应在waitUntil: 'networkidle0'
上使用page.goto()
设置,有关选项请参见the docs。您之所以拥有undefined
,是因为默认情况下,在页面上触发load
事件时,操纵up的人认为该页面已加载(这是waitUntil
的默认设置)。因此,如果认为页面已加载,但是队列中仍然有网络连接,并且尚未找到您的请求模式:该脚本将从goto
继续到console.log
。因此,您可以等待所有网络请求完成,以确保请求已被注册。
networkidle0
:当至少有500毫秒的网络连接不超过0个时,请考虑完成导航。
请注意::通过设置networkidle,您将无法在满足请求模式条件后断开连接,因此您无法停止响应的计划。
我建议中止那些不需要的resourceType
,这样可能会产生与停止请求类似的结果:
例如:
将其放在page.on('response', async response => {...
块结束之后。
await page.setRequestInterception(true)
page.on('request', request => {
if (request.resourceType() === 'image' || request.resourceType() === 'stylesheet') request.abort()
else request.continue()
})
如果知道不需要哪些连接,也可以在request.url().includes(unwantedRequestPattern)
条件下使用它。