Puppeteer 与 Chrome 控制台记录不同的行为

Puppeteer vs Chrome console log different behaviour

我想从一个页面收集一些信息。首先,我检查 Chrome inspect 和 console 如何找到正确的值,一切正常。然后我将代码粘贴到 puppeteer、cheerio 环境中,由于某些原因我无法收集正确的数据。

这是在 chrome 中工作的部分:

const modellek = $('[columntype="model"] > section > ul > li').map(function() {
                 return ($(this).text())});

console.log(modellek)
["txt1","txt2","txt3","txt4"...]

JS脚本如下:

const puppeteer = require("puppeteer");
const cheerio = require("cheerio");

async function scrapHome(url){
    try{
        const browser = await puppeteer.launch({headless: false});
        const page = await browser.newPage();
    
        await page.setViewport({width: 1366, height: 768});
        await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108'); 
        

        const html = await page.evaluate(() => document.body.innerHTML);
        const $ = await cheerio.load(html);
        await page.goto(url);

             
        const models= $('[columntype="model"] > section > ul > li').map(function() {
                      return ($(this).text().get())});

        console.log(models)

    } catch (err) {
        console.error(err);
    };
};

scrapHome("https://example.com/");

但结果是一个空数组:[].

我也尝试了 waitForSelector,但在那种情况下没有任何响应。

page
    .waitForSelector('[columntype="model"]')
    .then(() => $('[columntype="model"] > section > ul > li').map(function() {
                      console.log ($(this).text())
     }));

知道如何获取请求的信息吗?

首先你需要实际去一个页面

await page.goto(url);

然后才获取该页面的 HTML:

const html = await page.evaluate(() => document.body.innerHTML);

此外,根据您使用的网站,当您立即加载网页时,这些 模型 可能不可用(例如,如果它们已生成使用 js 脚本或通过 ajax).

加载

在这种情况下,您应该等待所需的元素出现在页面上:

await page.waitForSelector('[columntype="model"] > section > ul > li');
const html = await page.evaluate(() => document.body.innerHTML);

在 chrome 控制台中你会做:

$$('[columntype="model"] > section > ul > li').map(li => li.innerText)

在 Puppeteer 中你会做:

page.$$eval('[columntype="model"] > section > ul > li', lis => lis.map(li => li.innerText))