【问题标题】:Using Puppeteer to collect links of a page and open those links to scrape data使用 Puppeteer 收集页面的链接并打开这些链接以抓取数据
【发布时间】:2020-09-12 00:12:15
【问题描述】:

我必须从列表中抓取产品数据,但数据位于这些产品的页面中。例如,假设我要获取产品页面的.product-image

到目前为止,代码已成功获取每个 URL 并添加到数组中,但我不确定从哪里开始,因为出于某种原因在 urls 之外使用 page 时会返回 Error: Evaluation failed: ReferenceError: page is not defined

  const page = await browser.newPage();
  page.waitForNavigation({ timeout: 0, waitUntil: "domcontentloaded" });

  await page.goto(siteSearchUrl + 1);
  await page.screenshot({ path: "carpet.png" });

  const urls = await page.evaluate(() => {
    const items = document.querySelectorAll("li.product-item");
    const productLinks = [];
    console.log(page);
    items.forEach((item) => {
      const productLink = item
        .querySelector("a.product-image") // NOT the product image, it's the link.
        .getAttribute("href");
      productLinks.push(`${siteUrl + productLink}`);
    });

    productLinks.forEach((link) => {
      page.screenshot({ path: link + ".png" });
    }, page);
  });

  await browser.close();
  return Promise.resolve(urls);
})();

我究竟如何从每个链接中收集数据?

【问题讨论】:

    标签: node.js web-scraping puppeteer


    【解决方案1】:

    不能在page.evaluate 内部使用page

    您得到ReferenceError: page is not defined,因为page.evaluate 在页面上下文中执行脚本(例如,您的console.log(page) 登录到Chromium 的控制台,而不是登录到Node 的控制台),其他puppeteer 方法(如page.screenshot)不能在客户端运行,但只能在 puppeteer 中运行。所以你需要把它移到外面。

    例如:

    const urls = await page.evaluate(() => {
      const productLinks = []
      ...
      productLinks.push(...)
      ...
      return productLinks
    })
    
    for (const url of urls) {
      await page.goto(url)
      await page.screenshot({ path: url + '.png' })
    }
    
    

    编辑

    我修正了上面的例子。您可能会发现可以更简洁地使用page.$evalpage.$$eval 来解决问题。

    const hrefs = await page.$$eval('li.product-item > a.product-image', elements => elements.map(el => el.href))
    const urls = hrefs.map(el => siteUrl + el)
    
    for (const url of urls) {
      await page.goto(url)
      await page.screenshot({ path: url + '.png' })
    }
    

    【讨论】:

    • 不会在page.evaluate() 中定义productLinks 并在之后为空而不在上下文之间传输数组吗?
    • 真的。实际上,我忘记了从页面上下文填充数组很棘手。我将重新编写我的示例以使其正常工作。
    • 感谢您的帮助!我有一个要求——你的代码会是什么样的分页?分页查询是 ?page=1。
    • 哇,我认为值得提出一个新问题,我不确定我的评论是否有助于实现您的需求。 puppeteer 并不总是尊重 URL 中的 GET 参数。如果您想在完成当前页面的抓取后翻页,您可以像真实用户一样单击下一页按钮:await page.click('.next-page-btn')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    相关资源
    最近更新 更多