首页 > 解决方案 > 与单独运行相比,为什么异步运行多个数据抓取任务需要更多时间?

问题描述

我在 Node.JS 中使用 puppeteer 来运行一个数据抓取任务,该任务试图一次从多个页面获取数据。每个页面都有一个选项卡式结构,我需要从 4 个选项卡中获取数据。我单击一个选项卡并使用“等待”从选项卡获取数据。最后,我将获得的数据写入excel文件。除了完成所需的时间外,代码可以正常工作。如果我为单个 URL 运行代码,则需要 7 到 10 秒来获取每个 URL 的数据并将其写入 Excel 文件。但是,如果我在“for”循环中运行 16 个 URL 的代码,则几乎需要 30 到 33 秒。我认为完成这项工作需要不到 12 秒的时间,因为它是异步运行的。在一个 for 循环中运行 16 个任务期间,CPU 中的所有线程都被占用 100%。代码太长,我这里只写代码结构:

由于我不知道如果任务失败如何重复任务,我编写了 2 个 try-catch 结构,因为它们是嵌套的。

for (i = 0; i < URL.length; i++) {
    try {
        UpdateTable(URL[i], i, 1);
    } catch (e) {
        try {
            UpdateTable(URL[i], i, 2);
        } catch (e) {
            UpdateTable(URL[i], i, 3);
        }
    }
}

async function UpdateTable(URL, ii, Ind) {
    return new Promise((resolve, reject) => {
        var temp = [];
        temp = (async () => {
            console.time(("i: " + ii + ": " + Ind).toString());
            console.timeLog("i: " + ii + ": " + Ind);
            try {
                const browser = await puppeteer.launch({headless: true});
                const page = await browser.newPage();
                await page.goto(URL); //Bourse


                //Tab 1:
                await page.evaluate(() => {
                    document.getElementsByClassName('torq')[0].click();
                })
                await page.waitForSelector("tr.ev", {visible: true}).then(() => {
                });

                var temp = [];
                var temp_1col = [];
                var temp1_1col = [];
                temp = await page.evaluate(() => {
                //
                //
                //
                //
                //
                }
                
                
                //Tab 2:
                await page.evaluate(() => {
                    document.getElementsByClassName('vio')[0].click();
                })
                await page.waitForSelector("div.CalMon", {visible: true}).then(() => {
                });

                var temp1 = [];
                temp1 = await page.evaluate(() => {
                //
                //
                //
                //
                //
                }
                
                
                //Tab 3:
                await page.evaluate(() => {
                    document.querySelectorAll('a.re')[0].click();
                })
                var tt = await page.evaluate(() => {
                    return document.getElementById("d12").innerText;
                })

                while (tt === undefined || tt === "") {
                    tt = await page.evaluate(() => {
                        return document.getElementById("d12").innerText;
                    })
                }

                var temp2 = [];
                temp2 = await page.evaluate(() => {
                //
                //
                //
                //
                //
                }
                
                //Tab 4:
                await page.evaluate(() => {
                    document.querySelectorAll('a.ye')[0].click();
                })
                await page.waitForXPath("//div[@class='Main']//span//tr[5]//td[2]", {visible: true}).then(() => {
                });

                var temp4 = await page.evaluate(() => {
                //
                //
                //
                //
                //
                }
                
                
                //Writing to Excel file Using: "exceljs" module:
                const sheet8 = workbook3.addWorksheet("Adjusted");
                sheet8.views = [{rightToLeft: true}];
                sheet8.addRows(temp_adj);
                
                await browser.close();
                console.timeEnd(("i: " + ii + ": " + Ind).toString());
                return temp;
                } catch (e) {
                    console.log("Error In: " + URL);
            }
        })();
    });
}
                            

我测量了每个循环完成的时间:

i: 0: 1: 0.065ms
i: 1: 1: 0.020ms
i: 2: 1: 0.004ms
i: 3: 1: 0.004ms
i: 4: 1: 0.028ms
i: 5: 1: 0.007ms
i: 6: 1: 0.003ms
i: 7: 1: 0.018ms
i: 8: 1: 0.018ms
i: 9: 1: 0.005ms
i: 10: 1: 0.003ms
i: 11: 1: 0.003ms
i: 12: 1: 0.003ms
i: 13: 1: 0.003ms
i: 14: 1: 0.003ms
i: 15: 1: 0.003ms
i: 13: 1: 13728.609ms
i: 0: 1: 14846.398ms
i: 15: 1: 14857.476ms
i: 4: 1: 18383.652ms
i: 6: 1: 18504.466ms
i: 10: 1: 22255.862ms
i: 5: 1: 29188.227ms
i: 7: 1: 29187.398ms
i: 14: 1: 30093.722ms
i: 8: 1: 30297.994ms
i: 2: 1: 30381.256ms
i: 1: 1: 30426.768ms
i: 11: 1: 30644.432ms
i: 12: 1: 30677.942ms
i: 3: 1: 30689.566ms
i: 9: 1: 30710.694ms

正如您在时间日志中看到的,URL[13] 需要 13728.609 毫秒,而如果我运行此 URL 的代码,则只需 8000 毫秒。为什么与单个任务相比,一起运行 16 个任务需要更多时间?为什么异步运行需要 30710.694 毫秒,而任务所需的最长时间低于 10000 毫秒?

如果你能帮助我解决这个挑战,我将不胜感激。

标签: node.jsasynchronouspuppeteer

解决方案


在类似的情况下,我观​​察到内存耗尽并且系统开始交换。在内存和磁盘之间移动数据很慢,而且很快就达到了似乎需要永远完成的地步。100% 的 CPU 利用率很好,但也要注意使用了多少内存。


推荐阅读