首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >waitForResponse()超时,但page.on(' response ')找到响应

waitForResponse()超时,但page.on(' response ')找到响应
EN

Stack Overflow用户
提问于 2022-03-16 19:29:11
回答 1查看 2.7K关注 0票数 3

我正试图从一个网页上得到一个XHR的响应。我找到了

代码语言:javascript
运行
复制
await page.waitForResponse(url);

代码语言:javascript
运行
复制
await page.waitForResponse((res) => {
  if (res.url() === myUrl) return true;
});

方法,但它总是对我试图得到的url响应超时。

但是,如果我

代码语言:javascript
运行
复制
page.on('response', (res) => {
  if (res.url() === myUrl) {
    // do what I want with the response
  }
})

找到正确的响应,我可以检索数据。

经过一些调试后,waitForResponse()似乎没有返回任何XHR /res。

有什么想法吗?

编辑:示例。在这种情况下,它需要使用puppeteer-extra-plugin-stealthpuppeteer-extra包,否则,该URL将返回状态代码'403':

代码语言:javascript
运行
复制
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
import UserAgent from 'user-agents';
import puppeteer from 'puppeteer-extra';
import { Page } from 'puppeteer';

const wantedUrl = 'https://www.nike.com.br/DataLayer/dataLayer';

const workingFunction = async (page: Page) => {
    let reqCount = 0;
    let resCount = 0;

    page.on('request', req => {
        reqCount++;
        if (req.url() == wantedUrl) {
            console.log('The request I need: ', req.url());
            console.log(reqCount);
        }
    });
    page.on('response', async res => {
        resCount++;
        if (res.url() == wantedUrl) {
            console.log('The response I need:', await res.json());
            console.log(resCount);
        }
    });

    await page.goto('https://www.nike.com.br/tenis-nike-sb-dunk-low-pro-unissex-153-169-229-284741', {
        timeout: 0,
    });
};

const notWorkingFunction = async (page: Page) => {
    let resCount = 0;
    await page.goto('https://www.nike.com.br/tenis-nike-sb-dunk-low-pro-unissex-153-169-229-284741');
    const res = await page.waitForResponse(
        res => {
            resCount++;
            console.log(res.url());
            console.log(resCount);
            if (res.url() === wantedUrl) {
                return true;
            }
            return false;
        },
        { timeout: 0 }
    );

    return res;
};

(async () => {
    puppeteer.use(StealthPlugin());
    const browser = await puppeteer.launch({});
    const page = await browser.newPage();
    const userAgent = new UserAgent({ deviceCategory: 'desktop' });
    await page.setUserAgent(userAgent.random().toString());

    try {
        // workingFunction(page);
        const res = await notWorkingFunction(page);
    } catch (e) {
        console.log(e);
    }
})();
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-18 01:33:55

page.on版本之所以工作,是因为它在执行导航之前设置了请求/响应处理程序。另一方面,waitForResponse版本一直等到"load"事件触发(page.goto()的默认解析点),然后才开始跟踪调用page.waitForResponse. MDN says of the load event的响应。

整个页面加载完后会触发load事件,包括所有依赖的资源,如样式表和图像。这与DOMContentLoaded形成了鲜明的对比,后者在加载页面DOM后立即触发,而无需等待资源完成加载。

基于此,我们可以推断,当load事件触发和waitForResponse函数最终开始侦听流量时,它已经错过了所需的响应,因此它只是等待了很久!

解决方案是在page.waitForResponse调用之前(或者在同一时间)为goto创建承诺,以便在启动导航时不会丢失任何通信量。

我还建议在"domcontentloaded"调用中使用goto"domcontentloaded"在木偶词典中使用不足--当你只是在寻找一种资源的时候,等待所有资源的到来是没有意义的。默认的"load"或经常使用的"networkidleN"设置更适合于用例,比如截取页面时,您希望整个页面看起来像用户所看到的那样。要明确的是,这不是解决问题的方法,只是一个优化,而且从文档中看也不太明显,这是合适的。

下面是一个很小的例子(我使用的是JS,而不是TS):

代码语言:javascript
运行
复制
const puppeteer = require("puppeteer-extra"); // ^3.2.3
const StealthPlugin = require("puppeteer-extra-plugin-stealth"); // ^2.9.0
const UserAgent = require("user-agents"); // ^1.0.958

puppeteer.use(StealthPlugin());

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  const userAgent = new UserAgent({deviceCategory: "desktop"});
  await page.setUserAgent(userAgent.random().toString());
  const url = "https://www.nike.com.br/tenis-nike-sb-dunk-low-pro-unissex-153-169-229-284741";
  const wantedUrl = "https://www.nike.com.br/DataLayer/dataLayer";
  const [res] = await Promise.all([
    page.waitForResponse(res => res.url() === wantedUrl, {timeout: 90000}),
    page.goto(url, {waitUntil: "domcontentloaded"}),
  ]);
  console.log(await res.json());
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71503214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档