javascript - 当我打开太多页面并忽略最后一个 URL 时,PhantomJS 崩溃

标签 javascript crash phantomjs httprequest

系统: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/

相关文章:

javascript - 使用 JSONP 通过 GAS 创建 Web 服务

javascript - 将鼠标悬停在图标上时按钮文本模糊

Azure - ASP.NET Core FileNotFoundException

android - 不幸的是,该应用已停止

java - 如何从 Selenium/Ghostdriver 将参数传递给 PhantomJS 脚本

javascript - CasperJS/PhantomJS ES6 Promise Polyfill

javascript - 为什么原型(prototype)考虑对象而不是函数

javascript - 休息 api session

iphone - UIColor功能崩溃

android - 锁定Android手机时出现致命信号11