当使用Node和jsdom到蜘蛛网站时,会导致内存不足

我试图从我已经存储在一个数组中的一堆HTML页面中拉出一个string。 我有以下代码:

const jsdom = require('jsdom') desc('Import pages'); task('handleSpots', [], function (params) { allSpots.forEach(function(spotUrl){ handleSpot(spotUrl) }) }); function handleSpot (href) { jsdom.env( href, ["http://code.jquery.com/jquery.js"], function (err, window) { if (err) { console.log(host+href+" "+err) return } const data = {url: host+href} data['name'] = window.$("h1.wanna-item-title-title a").text() console.log(data['name']) window.close() } ); } 

allSpots数组中有大约600个URL。 当我运行这个我得到一堆错误:

 /the_hook/index.html Error: read ECONNRESET 

这发生了一堆的url,一些名字被显示,最后我得到这个错误。

 <--- Last few GCs ---> 80660 ms: Scavenge 1355.3 (1460.0) -> 1355.3 (1460.0) MB, 2.3 / 0 ms (+ 1.4 ms in 1 steps since last GC) [allocation failure] [incremental marking delaying mark-sweep]. 82149 ms: Mark-sweep 1355.3 (1460.0) -> 1354.8 (1460.0) MB, 1488.7 / 0 ms (+ 2.8 ms in 2 steps since start of marking, biggest step 1.4 ms) [last resort gc]. 83657 ms: Mark-sweep 1354.8 (1460.0) -> 1354.6 (1460.0) MB, 1508.2 / 0 ms [last resort gc]. <--- JS stacktrace ---> ==== JS stack trace ========================================= Security context: 0x38f1b4237339 <JS Object> 1: create [native v8natives.js:~755] [pc=0x22e6902f1923] (this=0x38f1b4236b61 <JS Function Object (SharedFunctionInfo 0x38f1b4236ad1)>,an=0x1590d58f6941 <an Object with map 0x1b19e3c1e251>,aD=0x38f1b4204131 <undefined>) 2: arguments adaptor frame: 1->2 3: createImpl [/Users/craig/Programming/node_wannasurf_importer/node_modules/jsdom/lib/jsdom/living/generated/Text.js:~90] [pc=0x22e... FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory Abort trap: 6 

只有在allSpots数组中有超过125个项目时才会发生这种情况。 less于这一切,一切工作正常。

我对节点相当陌生,但我假设Javascript试图同时获得太多的这些页面,并最终耗尽内存。 理想情况下,我可以写一些处理100的东西,等到完成后再移动到下一个100。

我试过这个:async.eachLimit(allSpots,100,handleSpot)但是,只处理第一个100然后停止。

我也试过:async.eachSeries(allSpots,handleSpot)但是这只处理第一个url并停止。

我有点死路一条,所以我会很感激任何人都可以给我的build议。 谢谢,

克雷格

我决定放弃jsdom,并用cheerio和httpsreplace,这样我可以对请求过程有更多的控制。 然后,我研究了如何同步请求每个url(在请求上使用on('end')),然后开始在一个循环中处理urls,所以循环次数是并发进程的数量。

代码如下:

 const https = require('https'); const cheerio = require('cheerio') desc('Import pages'); task('handleSpots', [], function (params) { var totalLoop = 10; for( var i = 0; i < totalLoop; i++ ) { handleSpotAndNext() } }); function handleSpotAndNext() { spot = allSpots.pop() https.get(spot,function(res){ var chunks = ''; res.on('data',function(d){ chunks += d; }); res.on('end',function(){ console.log(spotData(chunks, spot)) if(allSpots.length){ handleSpotAndNext(); } }) }) } function spotData(spotHtml, url) { $ = cheerio.load(spotHtml) const data = {url: url} data['name'] = $("h1.wanna-item-title-title a").text() return data } 

这是我想出来的,但如果你看到这个,可以想到一个更优雅的解决scheme,这将是很高兴收到你的来信。