我大约有5000个链接,我需要对所有链接进行爬网。所以我想知道有没有比这更好的方法了。这是我的代码。
let urls = [ 5000 urls go here ];
const doms = await getDoms(urls);
// processing and storing the doms
getDoms = (urls) => {
let data = await Promise.all(urls.map(url => {
return getSiteCrawlPromise(url)
}));
return data;
}
getSiteCrawlPromise = (url) => {
return new Promise((resolve, reject) => {
let j = request.jar();
request.get({url: url, jar: j}, function(err, response, body) {
if(err)
return resolve({ body: null, jar: j, error: err});
return resolve({body: body, jar: j, error: null});
});
})
}
是否存在在promise中实现的机制,因此可以将作业分配到多个线程和进程。然后整体返回输出? 而且我不想将网址分成较小的片段并处理这些片段
答案 0 :(得分:2)
Promise对象表示异步操作的最终完成(或失败)及其结果值。
Promise中没有内置的机制来“将作业分为多个线程和进程”。如果必须这样做,则必须将urls数组分段为较小的数组,并将分段后的数组同时排队到单独的搜寻器实例上。
但是,绝对不需要这样做,因为您使用的是node-js和node-crawler,因此可以使用node-crawler的maxConnections
选项。 这就是它的构建目的,最终结果将是相同的。您将在多个线程上搜寻url,而不会在手动分块和处理多个搜寻器实例上浪费时间和精力,也不必依赖任何并发库。
答案 1 :(得分:1)
至少到现在,Java尚未内置这种机制。
您可以使用提供更多功能的第三方Promise库,例如Bluebird,在其中可以利用它们的并发功能:
const Promise = require('bluebird');
// Crawl all URLs, with 10 concurrent "threads".
Promise.map(arrayOfUrls, url => {
return /* promise for crawling the url */;
}, { concurrency: 10 });
另一种选择是使用专用的限制库(我强烈推荐bottleneck),该库可让您表达任何通用的速率限制。在这种情况下,语法将类似于您已经拥有的语法:
const Bottleneck = require('bottleneck');
const limit = new Bottleneck({ maxConcurrent: 10 });
const getCallSitePromise = limit.wrap(url => {
// the body of your getCallSitePromise function, as normal
});
// getDoms stays exactly the same
您可以自己解决此问题,但是带上一个(或两个!)库将为您节省很多代码。