Cheerionetworking抓取错误

我正在努力为所有教授提供http://www.ratemyprofessors.com/ 。 我的代码似乎得到以下错误:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 1: node::Abort() [node] 2: 0x10d3f9c [node] 3: v8::Utils::ReportApiFailure(char const*, char const*) [node] 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [node] 5: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [node] 6: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [node] 7: 0x292aec062bf Aborted 

我不知道我做了什么导致这个错误,但可能是因为我的循环? 我需要循环超过一千万页,但我不知道为什么它甚至给我这个只有10循环的错误。 这里是代码:

 var express = require('express'); var path = require('path'); var request = require('request'); var cheerio = require('cheerio'); var fs = require('fs'); var app = express(); var count = 1; var url; while(count != 10){ url = "http://www.ratemyprofessors.com/ShowRatings.jsp?tid=" + count; request(url, function(err, resp, body){ var $ = cheerio.load(body); if($('.error').text().substring(0, 14) == "Page Not Found"){ console.log("hello"); count++; return; }else{ console.log($('.error').text().substring(0, 14) ); var pfname = $('.pfname'); var plname = $('.plname'); var professorName = pfname.text().replace(/\s/g, '') + " " +plname.text().replace(/\s/g, ''); console.log(professorName); console.log(url); count++; } return; }) } app.listen(3000, function(){ console.log("server is now listening"); }) 

你可能会做超过10个循环。 您只在请求的callback中递增计数,这可能在请求发送后的几百毫秒内发生。 在那个时候,你的while循环会尽可能快地发送请求。

这可能会更好,如果你只是使用一个普通的for循环而不是一个while循环。

你应该创build一个URL数组,然后用Cheerio遍历该数组。 这段代码应该让你开始,虽然它可以使用很多的改进。 最后的超时是这样的url可以完成填充。

 var request = require('request'); var cheerio = require('cheerio'); var url; var urls = []; for (i = 1; i < 10; i++) { url = 'http://www.ratemyprofessors.com/ShowRatings.jsp?tid=' + i; urls.push(url); } function done() { var arrayLength = urls.length; var promiseArray = []; for (var i = 0; i < arrayLength; i++) { request(urls[i], function(err, resp, body) { var $ = cheerio.load(body); if ( $('.error') .text() .substring(0, 14) == 'Page Not Found' ) { console.log('hello'); return; } else { console.log( $('.error') .text() .substring(0, 14) ); var pfname = $('.pfname'); var plname = $('.plname'); var professorName = pfname.text().replace(/\s/g, '') + ' ' + plname.text().replace(/\s/g, ''); console.log(professorName); console.log(url); } return; }); } } setTimeout(function() { done(); }, 3000); console.log(urls); 

我认为拉斐尔是正确的,因为你正在做的方式超过10循环,因为直到请求的callback计数不增加。 你可以通过使用像async.whilst这样的方法来解决这个问题,它允许你在while循环中连续运行asynchronous代码:

 const request = require('request') const async = require('async') let count = 1 const test = () => count < 10 const iteratee = callback => { const url = 'http://www.ratemyprofessors.com/ShowRatings.jsp?tid=' + count request(url, (error, response, body) => { if (error) return callback(error) // do other stuff here count++ callback() }) } const done = error => { // all done } async.whilst(test, iteratee, done) 

无论如何,这可能是更安全和更负责任的,因为你正在阻止向服务器发出并发请求(想象如果你刚刚同时向同一个地方发送了1000万个HTTP请求 – 不好)。 如果你想做并发请求,你可以考虑使用像async.map或者async.each这样的“并行”方法,像瓶颈一样使用速率限制器。