我正在用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);
                }
            ]);
    });
}

当前回答

另一个值得一提的情况(对于Linux和OS X)是,如果您使用像https这样的库来执行请求,或者如果您传递https://..。作为本地服务实例的URL,您将使用端口443,这是一个保留的私有端口,您可能会在Socket挂起或ECONNREFUSED错误中结束。

相反,使用端口3000,f.e.,并执行http请求。

其他回答

另一个原因可能是因为在创建服务器套接字时使用了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);
});

另一个值得一提的情况(对于Linux和OS X)是,如果您使用像https这样的库来执行请求,或者如果您传递https://..。作为本地服务实例的URL,您将使用端口443,这是一个保留的私有端口,您可能会在Socket挂起或ECONNREFUSED错误中结束。

相反,使用端口3000,f.e.,并执行http请求。

我使用带有x.509证书身份验证的axios

我的请求是这样的。

 async function callService() {

     const httpsAgent = new https.Agent({
         cert: fs.readFileSync('client.crt'),
         key: fs.readFileSync('client.key'),
         ca: fs.readFileSync('ca.crt'),
     });

     try {
         const result = await axios.post(
             'https://example.com/test/', 
             {"topic": 'home'}, 
             { httpsAgent: httpsAgent }
         );
     }
     catch (error) {
         console.log('error:', error)
     }

}

client.crt 
-----BEGIN CERTIFICATE-----
MIIDWjC....cME70g==
-----END CERTIFICATE-----

client.key
-----BEGIN RSA PRIVATE KEY-----
oBXxnIVby...qvdSsQ==
-----END RSA PRIVATE KEY-----

ca.crt
-----BEGIN CERTIFICATE-----
MIIDQ...8SQvvG5
-----END CERTIFICATE-----

我得到了错误:

Error: socket hang up
at connResetException (internal/errors.js:609:14)
at TLSSocket.socketOnEnd (_http_client.js:458:23)
at TLSSocket.emit (events.js:326:22)

解决方案:

我发现我使用的证书是无效的。: -)

在我的情况下,问题仅仅是因为返回状态代码102的响应(Processing…)

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