首页 > 解决方案 > 网页抓取时如何提高效率?

问题描述

我有一个节点脚本,它不断地抓取网站列表以获取信息。我想尝试提高脚本的效率;但是,nodejs a 是单线程运行时。但在幕后,nodejs 是多线程的,允许异步代码。有没有办法利用这一点来提高效率?如果没有,替代方案?

现在脚本同步运行。我尝试过混合使用同步和异步代码,但我总是用尽堆栈。示例代码不包含用于抓取数据或检查数据的逻辑,因为它是不相关的。

const request = require('request-promise');
const cheerio = require('cheerio');

const siteList = require('./websites.json');

async function scrapePage(link)
{
    let $, data = {};

    $ = await request({
        uri: link,
        transform: (body) => { return cheerio.load(body) },
        connection : 'keep-alive',
    });

    // Scrape data using cheerio

    return data;
}

async function scrapePages()
{
    for(let site of siteList)
    {
        let data = await scrapePage(site.url);

        // Check data for favored result
    }

    // Tail call to reuse stack space
    return scrapePages();
}

scrapePages();

对于质疑抓取范围的个人,网站列表不到 100 个。

标签: javascriptnode.jsweb-scraping

解决方案


您现在的代码将等待scrapePage()完成:

let data = await scrapePage(site.url);

如果您想一次抓取多个页面,请更改for循环的工作方式。.forEach()例如,在阵列上使用。

为了便于控制同时操作的数量,请考虑使用 await-semaphore 之类的包。

https://www.npmjs.com/package/await-semaphore

然后,你可以做这样的事情......

import {Semaphore} from 'await-semaphore';
const semaphore = new Semaphore(10); // 10 operations at a time

// Then, inside a loop...
semaphore.use(() => {
  // do your work here
});

推荐阅读