javascript 点击添加10到网站后如何等待网站加载新组件

mm9b1k5b  于 2023-02-28  发布在  Java
关注(0)|答案(1)|浏览(95)

我有问题beacuse我想等待我的第二个函数和louch它只有在所有组件加载到网站上。在函数瓦尔我点击按钮显示更多的内容,我想等待。

const puppeteer = require('puppeteer');
const fs = require('fs');
(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--window-size=1600,1200',
    ],
    defaultViewport: null,
  });
  const page = await browser.newPage();
  await page.goto(
    'https://www.gelbeseiten.de/suche/friseur/bundesweit?umkreis=4000',
    {
      waitUntil: 'networkidle2',
    }
  );

  async function getData() {
    return await page.evaluate(function () {
      const value = document.getElementById('mod-TrefferlisteInfo').innerText;
      function val() {
        for (var i = 50; i < 49951; i += 10) {
          document.getElementById('mod-LoadMore--button').click();
        }
      }

      function second() {
        val();
        function getData() {
          const liTag = document.querySelectorAll(
            '.mod-AdresseKompakt__phoneNumber'
          );
          let data = [];
          liTag.forEach((number) => {
            data.push(number.innerText);
          });
          return data;
        }
        return getData();
      }
      return second();
    });
  }
  const writeStream = fs.createWriteStream('data.csv');
  writeStream.write(`id, phone number\n`);
  await getData();
  setTimeout(async () => {
    const value = await getData();
    for (i = 0; i < value.length; ++i) {
      writeStream.write(`${i},${value[i]},\n`);
    }
  }, 600000);
})();

我特灵了DOMContentLoadedwindow.onload,但这不起作用。我不知道我需要等待他们的API结束作业?

sqxo8psd

sqxo8psd1#

首先,我会避免过早的抽象,直到你建立了正确性。过早地分解函数会使调试和理解代码变得更困难,特别是如果你是异步编程的新手。
其次,这是一个巨大的数据量,所以一次计算10条记录要花很长时间才能达到50k,我看不出有什么明显的方法可以解决这个问题,但是可以尝试下面的代码:

const fs = require("node:fs/promises");
const puppeteer = require("puppeteer"); // ^19.6.3

const url = "https://www.gelbeseiten.de/suche/friseur/bundesweit?umkreis=4000";

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  await page.setRequestInterception(true);
  const allowed = [
    url,
    "https://wwa.wipe.de/wwa.js",
    "https://www.gelbeseiten.de/ajaxsuche",
    "https://www.gelbeseiten.de/webgs/js/trefferliste_below.js?1676928398396",
  ];
  page.on("request", req => {
    allowed.includes(req.url()) ? req.continue() : req.abort();
  });
  await page.goto(url, {waitUntil: "domcontentloaded"});
  const btn = await page.waitForSelector("#mod-LoadMore--button");
  const sel = ".mod-AdresseKompakt__phoneNumber";

  for (;;) {
    const length = (await page.$$(sel)).length;
    await page.$eval("#mod-LoadMore--button", el => el.click());

    try {
      await page.waitForFunction(
        `document.querySelectorAll("${sel}").length !== ${length}`,
        {polling: "mutation", timeout: 10_000}
      );
    }
    catch (err) {}
  }

  const data = await page.$$eval(sel, els => els.map(e => e.textContent));
  await fs.writeFile("data.json", JSON.stringify(data));
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

您可以将循环更改为for (let i = 0; i < 10; i++) {},以获取前几个块用于测试。
由于屏幕上的50k元素可能会很慢,另一种方法是删除已经抓取的元素,并可选地写入磁盘。

const url = "https://www.gelbeseiten.de/suche/friseur/bundesweit?umkreis=4000";

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  await page.setRequestInterception(true);
  const allowed = [
    url,
    "https://wwa.wipe.de/wwa.js",
    "https://www.gelbeseiten.de/ajaxsuche",
    "https://www.gelbeseiten.de/webgs/js/trefferliste_below.js?1676928398396",
  ];
  page.on("request", req => {
    allowed.includes(req.url()) ? req.continue() : req.abort();
  });
  await page.goto(url, {waitUntil: "domcontentloaded"});
  const btn = await page.waitForSelector("#mod-LoadMore--button");
  const sel = ".mod-AdresseKompakt__phoneNumber";

  for (;;) {
    const length = (await page.$$(sel)).length;
    await page.$eval("#mod-LoadMore--button", el => el.click());

    try {
      await page.waitForFunction(
        `document.querySelectorAll("${sel}").length !== ${length}`,
        {polling: "mutation", timeout: 10_000}
      );
    }
    catch (err) {}
  }

  const data = await page.$$eval(sel, els => els.map(e => e.textContent));
  await fs.writeFile("data.json", JSON.stringify(data));
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

我写JSON是因为JS似乎没有原生的CSV编写器,但这只是表面上的变化。最好使用PapaParse这样的库,而不是自己用字符串模板滚动它。如果任何数据意外地包含逗号,您的CSV将无效。
我还没有完全验证这些脚本,并且remove()版本在开始时丢失了一些数据,但希望它们能为您提供一些工作基础。

相关问题