我正在用Node和Cheerio构建一个网页刮板,对于某个网站,我得到以下错误(它只发生在这一个网站上,没有其他我试图刮的网站。

它每次都发生在不同的位置,所以有时是url x抛出错误,其他时候url x是好的,它是一个完全不同的url:

    Error!: Error: socket hang up using [insert random URL, it's different every time]

Error: socket hang up
    at createHangUpError (http.js:1445:15)
    at Socket.socketOnEnd [as onend] (http.js:1541:23)
    at Socket.g (events.js:175:14)
    at Socket.EventEmitter.emit (events.js:117:20)
    at _stream_readable.js:910:16
    at process._tickCallback (node.js:415:13)

这是非常棘手的调试,我真的不知道从哪里开始。首先,什么是套接字挂起错误?是404错误还是类似的错误?或者仅仅意味着服务器拒绝连接?

我在任何地方都找不到解释!

编辑:下面是(有时)返回错误的代码示例:

function scrapeNexts(url, oncomplete) {
    request(url, function(err, resp, body) {

        if (err) {
            console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
            errors.nexts.push(url);
        }
        $ = cheerio.load(body);
        // do stuff with the '$' cheerio content here
    });
}

没有直接调用关闭连接,但我使用节点请求(据我所知)使用http。get所以这是不需要的,如果我错了纠正我!

编辑2:下面是一段实际使用的代码,它会导致错误。prodURL和其他变量主要是前面定义的jquery选择器。这使用了Node的异步库。

function scrapeNexts(url, oncomplete) {
    request(url, function (err, resp, body) {

        if (err) {
            console.log("Uh-oh, ScrapeNexts Error!: " + err + " using " + url);
            errors.nexts.push(url);
        }
        async.series([
                function (callback) {
                    $ = cheerio.load(body);
                    callback();
                },
                function (callback) {
                    $(prodURL).each(function () {
                        var theHref = $(this).attr('href');
                        urls.push(baseURL + theHref);
                    });
                    var next = $(next_select).first().attr('href');
                    oncomplete(next);
                }
            ]);
    });
}

当前回答

如果您在https连接上遇到此错误,并且它立即发生,则可能是设置SSL连接有问题。

对我来说,它是这个问题https://github.com/nodejs/node/issues/9845但对你来说,它可能是其他东西。如果ssl存在问题,那么您应该能够使用nodejs tls/ssl包重新生成它,只是试图连接到域

其他回答

在我的例子中,这是因为应用程序/json响应的格式很糟糕(包含堆栈跟踪)。响应从未发送到服务器。 这对调试来说非常棘手,因为没有日志。这篇文章帮助我理解发生了什么。

扩展Blender的答案,这在很多情况下都会发生。我遇到的最常见的问题是:

服务器崩溃。 服务器拒绝您的连接,很可能被用户代理阻塞。

socketCloseListener,正如Blender的回答中所概述的那样,并不是创建挂机错误的唯一地方。

例如,可以在这里找到:

function socketOnEnd() {
  var socket = this;
  var req = this._httpMessage;
  var parser = this.parser;

  if (!req.res) {
    // If we don't have a response then we know that the socket
    // ended prematurely and we need to emit an error on the request.
    req.emit('error', createHangUpError());
    req._hadError = true;
  }
  if (parser) {
    parser.finish();
    freeParser(parser, req);
  }
  socket.destroy();
}

你可以用curl来处理从Node发出的头信息,看看你是否得到响应。如果您没有使用curl得到响应,但在浏览器中得到响应,那么您的User-Agent头很可能被阻塞。

在使用http时也会发生此错误。请求,可能您的请求还没有完成。

例子:

Const req = https。请求(options, res => {})

你总是需要添加这一行: 有了这个功能,我们将按顺序完成请求的发送。

如文献所述:

对于http.request(),必须总是调用req.end()来表示请求的结束——即使没有数据写入请求体。

我同时做web(节点)和Android开发,并一起打开Android Studio设备模拟器和docker,它们都使用端口8601,它抱怨套接字挂起错误,关闭Android Studio设备模拟器后,它在节点端工作良好。不要同时使用Android Studio设备模拟器和docker。

这给我带来了问题,因为我正在做这里列出的所有事情,但仍然抛出错误。事实证明,调用req.abort()实际上会抛出一个带有ECONNRESET代码的错误,因此您实际上必须在错误处理程序中捕获该错误。

req.on('error', function(err) {
    if (err.code === "ECONNRESET") {
        console.log("Timeout occurs");
        return;
    }
    //handle normal errors
});