【发布时间】:2018-04-28 07:54:22
【问题描述】:
我正在尝试使用一定数量的选项卡来打开和操作这些选项卡,同时等待网络 IO 加速我对域的抓取过程。
我已经通过在通道上侦听的工作池解决了 Go 中的相同问题,但我不确定如何在 Node.js 和 Puppeteer 中解决相同的问题。
我的猜测是循环通过
async function nextPage() {
try {
for (var link of uncrawledLinks.keys()) {
if (runningThreads < maxThreads) {
var page = await browser.newPage();
console.log("nextPage() # runningThreads: " + runningThreads + " # uncrawledLinks.size: " + uncrawledLinks.size);
//debugger;
crawlPage(page, link);
}
}
当我将“maxthreads”增加到高于 1 时可能会产生问题,但直到现在我无法解决问题。
当我将它设置为高于 1 时出现的问题是链接被抓取两次(但不是每个链接,只有大约 90% 的链接),所以我得到重复,这使得爬虫无法使用。
我曾考虑过使用 Redis 或 SQLite 之类的数据库,但我想先解决问题而不使用它以更好地理解问题(直到现在我还没有性能/内存问题,所以在内存中进行操作是不行的问题)。
可运行的示例代码:
'use strict';
const puppeteer = require('puppeteer');
const url = require('url');
// start URL
const startUrlObj = url.parse("http://example.de/");
const startUrlDomain = startUrlObj.protocol + "//" + startUrlObj.hostname;
const startUrl = url.format(startUrlObj);
let browser;
let pages = [];
let uncrawledLinks = new Map();
let crawledLinks = [];
let runningThreads = 0;
const maxThreads = 1;
start();
async function start() {
console.log("Starting Crawler");
browser = await puppeteer.launch();
console.log("Finished initializing browser object");
uncrawledLinks.set(startUrl, "");
nextPage();
};
async function crawlPage(page, link) {
try {
console.log("starting crawl for: " + link);
runningThreads++;
const response = await page.goto(link, {
waitUntil: 'networkidle2',
timeout: 30000
});
// find all links in the form <a href="xxx">
const hrefs = await page.$$eval('a', as => as.map(a => a.href));
hrefs.forEach(function(foundLink, key) {
if (foundLink.startsWith(startUrlDomain)) {
var tempUrl = url.parse(foundLink);
// remove #asd and ?param1=y values from URL
tempUrl.hash = null;
tempUrl.search = null;
var tempLink = url.format(tempUrl);
//console.log(url.format(tempLink));
if (crawledLinks.includes(tempLink) === false) {
if (tempLink.endsWith(".html") === true) {
uncrawledLinks.set(tempLink, "false");
//pages.push(tempLink);
}
}
}}, hrefs)
//console.log("Found new links: " + i + " # " + link);
// crawling queues
uncrawledLinks.delete(link);
crawledLinks.push(link);
} catch (error) {
// Log errors
console.error(error);
} finally {
runningThreads--;
await page.close();
await nextPage();
}
}
async function nextPage() {
try {
for (var link of uncrawledLinks.keys()) {
if (runningThreads < maxThreads) {
var page = await browser.newPage();
//console.log("nextPage() # runningThreads: " + runningThreads + " # uncrawledLinks.size: " + uncrawledLinks.size);
//debugger;
crawlPage(page, link);
}
}
} catch (error) {
console.error(error);
} finally {
if (uncrawledLinks.size === 0 && runningThreads === 0) {
console.log("Finished crawling");
console.log(crawledLinks);
await browser.close();
}
}
}
【问题讨论】:
标签: node.js multithreading tabs puppeteer