我正在用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包重新生成它,只是试图连接到域

其他回答

我在使用Nano库连接Couch DB时也遇到了同样的问题。我尝试使用keepaliveagent库微调连接池,它一直失败的套接字挂起消息。

var KeepAliveAgent = require('agentkeepalive');

var myagent = new KeepAliveAgent({
    maxSockets: 10,
    maxKeepAliveRequests: 0,
    maxKeepAliveTime: 240000
});

nano = new Nano({
    url : uri,
    requestDefaults : {
        agent : myagent
    }
});

经过一番努力,我终于解决了这个问题——结果发现这是一个非常非常简单的错误。我通过HTTPS协议连接到数据库,但是我一直向我的nano对象传递一个keepalive代理,作为使用这个库显示的示例创建(它们依赖于一些使用http的默认值)。

使用httpagent时做了一个简单的改变:

var KeepAliveAgent = require('agentkeepalive').HttpsAgent;

如果您正在使用node-http-proxy,请注意这个问题,这将导致套接字挂起错误:https://github.com/nodejitsu/node-http-proxy/issues/180。

为了解决这个问题,同样在这个链接中,只需在express. bodyparser()之前移动在快速路由中声明API路由(用于代理)。

已经很长时间了,但另一种情况是,在服务器端执行请求需要很长时间(超过2分钟,这是express的默认值),并且服务器端没有配置超时参数。在我的情况下,我正在做客户端->服务器->服务器请求(Node.js express),我应该在服务器和客户端上的每个请求路由器上设置超时参数。 因此,在这两个服务器中,我需要通过使用设置请求超时

req.setTimeout([your needed timeout])

在路由器上。

另一个原因可能是因为在创建服务器套接字时使用了express的应用实例而不是从const server = http.createServer(app)中创建的服务器实例。

错误的

const express = require('express');
const http = require('http');
const WebSocket = require('ws');


const app = express();

app.use(function (req, res) {
  res.send({ msg: "hello" });
});

const wss = new WebSocket.Server({ server: app }); // will throw error while connecting from client socket

app.listen(8080, function listening() {
  console.log('Listening on %d', server.address().port);
});

正确的

const express = require('express');
const http = require('http');
const WebSocket = require('ws');


const app = express();

app.use(function (req, res) {
  res.send({ msg: "hello" });
});

const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

server.listen(8080, function listening() {
  console.log('Listening on %d', server.address().port);
});

我的情况下,这不是一个错误,但预期行为chrome浏览器。Chrome保持tls连接活跃(我认为是为了速度),但node.js服务器在2分钟后停止它,你会得到一个错误。

如果你尝试GET请求使用边缘浏览器,将不会有任何错误。 如果你将关闭chrome窗口-你会得到错误马上。

那么该怎么办呢? 1)你可以过滤这些错误,因为它们不是真正的错误。 2)也许有更好的解决方案:)