gpt4 book ai didi

javascript - 缓慢循环页面并使用 puppeteer 提取数据

转载 作者:搜寻专家 更新时间:2023-11-01 00:47:25 30 4
gpt4 key购买 nike

我有一张看起来像那样的 table 。名称列中的所有名称都是导航到下一页的链接。

|---------------------|------------------|
| NAME | ID |
|---------------------|------------------|
| Name 1 | 1 |
|---------------------|------------------|
| Name 2 | 2 |
|---------------------|------------------|
| Name 3 | 3 |
|---------------------|------------------|

我正在尝试获取链接,从中提取数据,然后返回到表中。但是,表中有超过 4000 条记录,所有处理速度都非常慢(每条记录大约 1000 毫秒)

这是我的代码:

//Grabs all table rows.
const items = await page.$$(domObjects.itemPageLink);

for (let i = 0; i < items.length; i++) {
await page.goto(url);
await page.waitForSelector(domObjects.itemPageLink);
let items = await page.$$(domObjects.itemPageLink);

const item = items[i];

let id = await item.$eval("td:last-of-type", node => node.innerText.split(",").map(item => item.trim()));
let link = await item.$eval("td:first-of-type a", node => node.click());

await page.waitForSelector(domObjects.itemPageWrapper);
let itemDetailsPage = await page.$(domObjects.itemPageWrapper);

let title = await itemDetailsPage.$eval(".page-header__title", title => title.innerText);
console.log(title);
console.log(id);
}

有没有办法加快这个速度,这样我就可以更快地一次获得所有结果?我想将其用于我的 API。

最佳答案

这里有一些小的代码改进和一项主要改进。

小改进:使用更少的 puppeteer 操纵函数

微小的改进归结为尽可能少地使用 puppeteer 操作功能。您使用的大多数 puppeteer 函数都是通过 WebSocket 将数据从 Node.js 环境发送到浏览器环境。虽然这只需要几毫秒,但从长远来看,这些毫秒显然会累加起来。有关这方面的更多信息,您可以查看 this question询问使用 page.evaluate 与使用更多 puppeteer 函数的区别。

这意味着,为了优化您的代码,您可以在页面内部使用 querySelector,而不是多次运行 item.$eval。另一个优化是直接使用page.waitForSelector的结果。该函数将在 Node 出现时返回该 Node 。因此,您以后无需再通过page.$查询。

这些只是微小的改进,可能会略微提高爬行速度。

主要改进:使用 puppeteer 池

现在,您正在使用一个浏览器和一个页面来抓取多个 URL。您可以通过使用 puppeteer 资源池并​​行抓取多个 URL 来提高脚本的速度。 puppeteer-cluster允许你做到这一点(免责声明:我是作者)。该库接受一项任务并将其并行应用于多个 URL。

您可以使用的并行实例的数量取决于您的 CPU、内存和吞吐量。您可以使用的越多,您的爬行速度就越好。

代码示例

下面是一个最小的示例,调整您的代码以提取相同的数据。该代码首先设置一个具有一个浏览器和四个页面的集群。之后,定义一个任务函数,该函数将为每个排队的对象执行。

在此之后,集群的一个页面实例用于从初始页面中提取 ID 和 URL。赋予 cluster.queue 的函数从页面中提取 ID 和 URL,并调用 cluster.queue 对象为 { id: ..., url : ... 。对于每个排队的对象,执行 cluster.task 函数,然后提取标题并将其打印在传递的 ID 旁边。

// Setup your cluster with 4 pages
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_PAGE,
maxConcurrency: 4,
});

// Define the task for the pages (go the the URL, and extract the title)
await cluster.task(async ({ page, data: { id, url } }) => {
await page.goto(url);
const itemDetailsPage = await page.waitForSelector(domObjects.itemPageWrapper);
const title = await itemDetailsPage.$eval('.page-header__title', title => title.innerText);
console.log(id, url);
});

// use one page of the cluster, to extract the links (ignoring the task function above)
cluster.queue(({ page }) => {
await page.goto(url); // URLs is given from outside
// Extract the links and ids from the initial page by using a page of the cluster
const itemData = await page.$$eval(domObjects.itemPageLink, items => items.map(item => ({
id: item.querySelector('td:last-of-type').split(',').map(item => item.trim()),
url: item.querySelector('td:first-of-type a').href,
})));
// Queue the data: { id: ..., url: ... } to start the process
itemData.forEach(data => cluster.queue(data));
});

关于javascript - 缓慢循环页面并使用 puppeteer 提取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57871135/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com