系统:Windows 8.1 64 位,带有来自主页的二进制文件,版本 2.0
我有一个每行 1 个 URL 的 .txt 文件,我阅读每一行并打开页面,搜索特定的 url.match(出于隐私原因在代码中更改域) - 如果找到,打印找到的 JSON,中止请求,卸载页面。
我的 .txt 文件包含 12500 个链接,出于测试目的,我将其拆分为前 10/100/500 个 URL。
问题一:如果我尝试 10 个 url,它会打印 9,然后使用 40-50% cpu
问题2:如果我尝试 100 个 url,它会打印 98 个,之后出于任何原因使用 40-50% cpu,然后在 2-3 分钟后崩溃。
问题3: 98 个链接(打印 96,使用 40-50% cpu,然后也崩溃)和 500 个链接也是如此
TXT 文件:
https://www.dropbox.com/s/eeiy12ku5k15226/sitemaps.7z?dl=1
98、100 和 500 链接的故障转储:
https://www.dropbox.com/s/ilvbg8lv1bizjti/Crash%20dumps.7z?dl=1
console.log('Hello, world!');
var fs = require('fs');
var stream = fs.open('100sitemap.txt', 'r');
var line = stream.readLine();
var webPage = require('webpage');
var i = 1;
while(!stream.atEnd() || line != "") {
//console.log(line);
var page = webPage.create();
page.settings.loadImages = false;
page.open(line, function() {});
//console.log("opened " + line);
page.onResourceRequested = function(requestData, request) {
//console.log("BEFORE: " +requestData.url);
var match = requestData.url.match(/example.com\/ac/g)
//console.log("Match: " + match);
//console.log("Line: " + line);
//console.log("Match: " + match);
if (match != null) {
var targetString = decodeURI(JSON.stringify(requestData.url));
var klammerauf = targetString.indexOf("{");
var jsonobjekt = targetString.substr(klammerauf, (targetString.indexOf("}") - klammerauf) + 1);
targetJSON = (decodeURIComponent(jsonobjekt));
console.log(i);
i++;
console.log(targetJSON);
console.log("");
request.abort();
page.close();
}
};
var line = stream.readLine();
}
//console.log("File closed");
//stream.close();
最佳答案
并发请求
你真的不应该在循环中加载页面,因为循环是一个同步结构,而 page.open()
是异步的。这样做,你会遇到内存消耗猛增的问题,因为所有的 URL 都是同时打开的。如果列表中有 20 个或更多 URL,这将是一个问题。
函数级范围
另一个问题是 JavaScript 具有函数级范围。这意味着即使您定义了 page
while
中的变量阻止它在全局范围内可用。由于它是全局定义的,因此您会遇到 PhantomJS 的异步特性的问题。 page
page.onResourceRequested
内部函数定义很可能不一样page
用于打开触发回调的 URL。查看更多信息 here .一个常见的解决方案是使用 IIFE 绑定(bind) page
变量只能进行一次迭代,但您需要重新考虑整个方法。
内存泄漏
您还有内存泄漏,因为当 page.onResourceRequested
中的 URL 时事件不匹配,您没有中止请求并且没有清理页面实例。您可能希望对所有 URL 执行此操作,而不仅仅是与您的特定正则表达式匹配的 URL。
轻松修复
一个快速的解决方案是定义一个执行一次迭代并在当前迭代完成时调用下一次迭代的函数。您也可以重复使用一个 page
所有请求的实例。
var page = webPage.create();
function runOnce(){
if (stream.atEnd()) {
phantom.exit();
return;
}
var url = stream.readLine();
if (url === "") {
phantom.exit();
return;
}
page.open(url, function() {});
page.onResourceRequested = function(requestData, request) {
/**...**/
request.abort();
runOnce();
};
}
runOnce();
关于javascript - 当我打开太多页面并忽略最后一个 URL 时,PhantomJS 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32477578/