当我打开太多页面并忽略最后一个URL时,PhantomJS崩溃了
PhantomJS crashes when I open too many pages and ignores the last URL
系统:Windows 8.1 64位,带有二进制文件,版本2.0
我有一个.txt文件,每行有一个URL,我阅读每一行并打开页面,搜索特定的URL。match(代码中由于隐私原因更改了域名)-如果找到,打印找到的JSON,中止请求,卸载页面。我的.txt文件包含12500个链接,出于测试目的,我将其分成前10/100/500个url。
问题1:如果我尝试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具有函数级作用域。这意味着即使在while
块内部定义page
变量,它也是全局可用的。由于它是全局定义的,因此您会遇到PhantomJS的异步特性的问题。page.onResourceRequested
函数定义中的page
很可能与用于打开触发回调的URL的page
不同。点击这里了解更多。一个常见的解决方案是使用IIFE将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();
- 如何使用JQuery提取URL中最后一个/分隔符之前的最后一个值
- Regex:使用javascript测试最后一个单词后的url中是否存在最后一个斜杠
- 使用JavaScript匹配URL中的最后一个单词
- 如何获取去除不需要的字符的url的最后一个元素
- 将 URL 的最后一个字符串与 Li 的 ID 名称进行比较
- 正则表达式获取 / 和 / 之间的 URL 中的最后一个单词
- 获取 URL 中的最后一个数字
- 想要更改url最后一个参数
- 提取 URL 的最后一个字符串
- 使用JS获取最后一个历史项目URL
- Raphael JS上的rect点击重定向到url会获取所有矩形的最后一个url
- 替换URL中最后一个字符之后的所有内容
- 使用jQuery从URL获取最后一个字符串
- 自定义正则表达式过滤掉最后一个url路径中的ID
- 我如何得到最后2个数字从一个url到一个变量使用javascript
- onbeforerequest只重定向最后一个URL
- 当我打开太多页面并忽略最后一个URL时,PhantomJS崩溃了
- 截断动态url中最后一个单词后的字符串
- 如果URL的最后一个斜杠后面存在字符串,则捕获该值;如果不是,捕获最后一个斜杠之前的值(javascript)
- 获取ajax使用的最后一个重定向URL;如果用户单击浏览器后退按钮,则打开它