首页 > 解决方案 > 使用 Puppeteer,您将如何映射一组链接,它将转到数组中的第一个链接,关闭该选项卡,然后重复?

问题描述

我目前有它转到我输入的第一个链接,如下所示

(async () => {
  let funkoUrl = "https://www.cardboardconnection.com/brand/funko/funko-pop";
  let browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null,
  });

  let page = await browser.newPage();

  await page.goto(funkoUrl), { waitUntil: "networkidle2" };

然后我运行这段代码来获取我需要去的链接数组

let links = await page.evaluate(() => {
    let url = document.querySelector(
      "#productListing > div:nth-child(1) > div.brandproductDescription > h2 > a"
    ).href;

    links = Array.from(
      document.querySelectorAll(
        "#productListing div.brandproductDescription > h2 > a"
      )
    ).map((link) => link.href);

    return links;
  });
  console.log(links.length);

links.length = 745 个链接。然后我需要单独打开每个链接,我可以在其中清理数据,然后关闭该选项卡,然后转到数组中的下一个链接。目前,它会一次打开所有选项卡,然后让我闲置或崩溃服务器。

我目前有这个来处理链接数组

links.forEach(async (link) => {
    try {
      const newPage = await browser.newPage();

      await newPage.goto(link);

      const data = await newPage.evaluate(() => {
        const headline = document.querySelector("h1").innerText;

        const titles = Array.from(
          document.querySelectorAll(".entry h3")
        ).filter((title) => title.innerText !== "");

        const pageData = titles.map((title) => ({
          title: title.innerText,
          image: title.nextElementSibling.nextElementSibling.querySelector(
            "img"
          ).dataset.src,
        }));

        return (data = {
          headline,
          pageData,
        });
      });

      console.log(data);
    } catch (err) {
      console.error(err);
    } finally {
      await newPage.close();
    }
    console.log(link);
  });

还有什么可以起作用的,而不是获取一系列链接,单击第一个链接并在新选项卡中打开它,清理数据,关闭页面,然后单击页面上的第二个链接以获取我需要的下一个链接去重复一遍。关于如何有效地进行这项工作的任何想法?

标签: javascriptnode.jsarraysweb-scrapingpuppeteer

解决方案


在 forEach 循环中使用 await 不会像您预期的那样工作,这就是为什么它一次打开所有链接,而是尝试使用 for..of。

for(let link of links){
    try {
      const newPage = await browser.newPage();

      await newPage.goto(link);

      const data = await newPage.evaluate(() => {
        const headline = document.querySelector("h1").innerText;

        const titles = Array.from(
          document.querySelectorAll(".entry h3")
        ).filter((title) => title.innerText !== "");

        const pageData = titles.map((title) => ({
          title: title.innerText,
          image: title.nextElementSibling.nextElementSibling.querySelector(
            "img"
          ).dataset.src,
        }));

        return (data = {
          headline,
          pageData,
        });
      });

      console.log(data);
    } catch (err) {
      console.error(err);
    } finally {
      await newPage.close();
    }
    console.log(link);
}

推荐阅读