最大调用堆栈大小超出了Node.JS WebCrawler

时间:2015-05-09 16:00:43

标签: javascript node.js process web-crawler search-engine

我在Node.JS中编写了这个WebCrawler。它抓取页面并将其保存到Redis中。我使用setImmediate和process.nextTick,但它仍然会抛出此错误。我做错了什么?

var $, client, f, redis, request, s, urlhelper, urls, validator, _;

request = require("request");

validator = require("validator");

$ = require("cheerio");

_ = require("underscore");

s = require("underscore.string");

urlhelper = require("url");

urls = [];

redis = require("redis");

client = redis.createClient();

f = function(url) {
    return process.nextTick(function() {
        urls.push(url);
        if (validator.isURL(url) !== true) {
            return;
        }
        return request(url, function(error, response, body) {
            var title, _$;
            if (!error && response.statusCode === 200) {
                _$ = $.load(body);
                title = _$("title").text() || "";
                return client.hset(url, "title", title, function() {
                    return _.each(_$("a"), function(object) {
                        var href;
                        href = object.attribs["href"];
                        if (!validator.isURL(href)) {
                            href = urlhelper.resolve(url, href || "");
                        }
                        console.log(href);
                        return client.exists(href, function(error, reply) {
                            if (error) {
                                throw error;
                            }
                            if (reply === 1) {
                                return client.hincrby(href, "refs", 1, function() {});
                            } else {
                                return client.hmset(href, {
                                    "refs": "1",
                                    "title": ""
                                }, function() {
                                    return client.sadd("sites", href, function() {
                                        return setTimeout(function() {
                                            return f(href);
                                        }, 0);
                                    });
                                });
                            }
                        });
                    });
                });
            }
        });
    });
};

client.on("connect", function() {
    return f("http://www.apple.com");
});

我将不胜感激。

非常感谢你,

最高

1 个答案:

答案 0 :(得分:1)

你有一个递归函数,它必须在完成之前遍历整个万维网(或者至少,从www.apple.com开始可以访问所有这些函数)。除非它可以在内存中保存几十亿个网页,否则它将耗尽堆栈空间。您需要重写它,以便在某种类型的数据库中维护一个单独的页面队列 - 这不是您可以使用递归的地方。或者,您可以设置递归的最大深度。