Node.js Puppeter:返回AJAX响应的JSON响应

Node.js Puppeter:返回AJAX响应的JSON响应,node.js,puppeteer,Node.js,Puppeteer,在加载页面时,我试图等待页面发出的某个AJAX请求,然后返回其响应的JSON正文。我的代码不会停止遍历每个响应,即使在侦听器中满足“response”事件的条件之后也是如此 一旦找到要返回的响应,如何从响应中捕获JSON,停止执行页面进一步加载,并返回JSON async function runScrape() { const browser = await browserPromise; const context = await browser.createIncognit

在加载页面时,我试图等待页面发出的某个AJAX请求,然后返回其响应的JSON正文。我的代码不会停止遍历每个响应,即使在侦听器中满足“response”事件的条件之后也是如此

一旦找到要返回的响应,如何从响应中捕获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);
});

我将把它简化为一个
页面。在('response')…
上,我们正在寻找所需的请求模式

一旦识别出响应,我们就可以用
wait page.evaluate(()=>window.Stop())
模拟浏览器的“停止加载此页面”按钮。该方法不会关闭浏览器,只会停止网络请求

let resp
page.on('response',异步响应=>{
if(response.url().includes(requestPattern)){
resp=wait response.json()
等待page.evaluate(()=>window.stop())
}
})
wait page.goto(req.query.url,{waitill:'networkidle0'})
控制台日志(resp)
编辑: 为了避免
未定义的
响应,您应该在
页面上使用
waitill:'networkidle0'
设置。转到()
,请参阅关于选项。由于默认情况下,当页面上触发
加载
事件时,傀儡玩家会考虑加载页面(这是
waitill
的默认设置)。因此,如果页面被视为已加载,但队列中仍有网络连接,并且尚未找到您的请求模式:脚本将从
转到
控制台.log
。因此,您可以通过等待所有网络请求完成,确保请求在发生之前已注册

<代码> NETWorkDeL0:考虑导航不超过0个网络连接至少500毫秒时完成。

请注意:通过设置networkidle,您将无法在满足请求模式条件后断开连接,因此您停止响应的计划将不可能实现

我建议中止那些不需要的请求,就像这样,您可能会得到与停止请求类似的结果:

例如:

将其放在
页面的正后方。在('response',async response=>{…
块结束

wait page.setRequestInterception(true)
第页('request',request=>{
if(request.resourceType()=='image'| | request.resourceType()=='stylesheet')request.abort()
else请求。继续()
})

如果您知道哪些连接是不需要的,那么也可以将它与
请求.url()一起使用。includes(unwantedRequestPattern)
条件一起使用。

我将把它简化为一个
页面。在('response')…
上,我们正在使用它查找所需的请求模式

一旦识别出响应,我们就可以用
wait page.evaluate(()=>window.Stop())
模拟浏览器的“停止加载此页面”按钮。该方法不会关闭浏览器,只会停止网络请求

let resp
page.on('response',异步响应=>{
if(response.url().includes(requestPattern)){
resp=wait response.json()
等待page.evaluate(()=>window.stop())
}
})
wait page.goto(req.query.url,{waitill:'networkidle0'})
控制台日志(resp)
编辑: 为了避免
未定义的
响应,您应该在
页面上使用
waitill:'networkidle0'
设置。转到()
,请参阅关于选项。由于默认情况下,当页面上触发
加载
事件时,傀儡玩家会考虑加载页面(这是
waitill
的默认设置)。因此,如果页面被视为已加载,但队列中仍有网络连接,并且尚未找到您的请求模式:脚本将从
转到
控制台.log
。因此,您可以通过等待所有网络请求完成,确保请求在发生之前已注册

<代码> NETWorkDeL0:考虑导航不超过0个网络连接至少500毫秒时完成。

请注意:通过设置networkidle,您将无法在满足请求模式条件后断开连接,因此您停止响应的计划将不可能实现

我建议中止那些不需要的请求,就像这样,您可能会得到与停止请求类似的结果:

例如:

将其放在
页面的正后方。在('response',async response=>{…
块结束

wait page.setRequestInterception(true)
第页('request',request=>{
if(request.resourceType()=='image'| | request.resourceType()=='stylesheet')request.abort()
else请求。继续()
})

如果您知道哪些连接不需要,也可以将其与
请求.url()一起使用。includes(unwantedRequestPattern)
条件一起使用。

谢谢@theDavidBarton,即使在
等待页面之后,我仍然会收到来自页面的响应。评估(()=>window.stop())
正在运行。我意识到他们相应的请求可能是在window.stop()运行之前启动的,但似乎仍有很多事情发生。此外,我一直看到JSON响应未定义。我还尝试了
wait response.text()
,尽管response.status()==200。是否有某些原因导致我的代码没有加载响应的正文?请参阅我的更新。很遗憾,您不能同时执行这两项操作。或者