我试图从网络服务中抓取一些URL,它的工作完美,但我需要从同一个网络服务中抓取10,000个页面。
我是通过创建多个phantomJS进程来实现的,它们每个都打开并评估不同的URL(它是相同的服务,我所做的只是网站URL中的一个参数)。
问题是我不想一次打开10,000个页面,因为我不希望他们的服务崩溃,我也不希望我的服务器崩溃。
我试图制作一些打开/评估/插入ToDB~10页的逻辑,然后睡1分钟左右。
让我们说这就是我现在所拥有的:
var numOfRequests = 10,000; //Total requests
for (var dataIndex = 0; dataIndex < numOfRequests; dataIndex++) {
phantom.create({'port' : freeport}, function(ph) {
ph.createPage(function(page) {
page.open("http://..." + data[dataIncFirstPage], function(status) {
我想在中间插入一些像:
if(dataIndex % 10 == 0){
sleep(60); //I can use the sleep module
}
我尝试放置sleepJS的每个地方程序都会永远崩溃/冻结/循环......
知道我应该尝试什么吗?
我尝试将上面的代码放在for循环之后的第一行,但这不起作用(可能是因为等待触发的回调函数..)
如果我把它放在phantom.create()
回调中也不起作用..
答案 0 :(得分:1)
意识到NodeJS是异步运行的,并且在for循环中,每个方法调用都是一个接一个地执行。 phantom.create
调用立即接近,然后for循环的下一个循环开始。
要回答你的问题,你需要在phantom.create
块末尾的sleep命令,仍然在for循环中。像这样:
var numOfRequests = 10000; // Total requests
for( var dataIndex = 0; dataIndex < numOfRequests; dataIndex++ ) {
phantom.create( { 'port' : freeport }, function( ph ) {
// ..whatever in here
} );
if(dataIndex % 10 == 0){
sleep(60); //I can use the sleep module
}
}
另外,请考虑使用包来帮助解决这些控制流问题。异步是一个很好的,has a method, eachLimit
将同时运行多个进程,达到极限。便利!您需要为要运行的每个迭代创建一个输入对象数组,如下所示:
var dataInputs = [ { id: 0, data: "/abc"}, { id : 1, data : "/def"} ];
function processPhantom( dataItem, callback ){
console.log("Starting processing for " + JSON.stringify( dataItem ) );
phantom.create( { 'port' : freeport }, function( ph ) {
// ..whatever in here.
//When done, in inner-most callback, call:
//callback(null); //let the next parallel items into the queue
//or
//callback( new Error("Something went wrong") ); //break the processing
} );
}
async.eachLimit( dataInputs, 10, processPhantom, function( err ){
//Can check for err.
//It is here that everything is finished.
console.log("Finished with async.eachLimit");
});
睡一分钟并不是一个坏主意,但是以10人为一组,这需要1000分钟,超过16小时!只有在队列中有空间时才能更方便地调用 - 并确保记录正在处理的请求并完成。