我正在使用Node和Cheerio构建一个web scraper,对于某个网站,我遇到了以下错误(它只发生在这个网站上,没有其他我试图抓取.
它每次都发生在不同的位置,所以有时它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)
Run Code Online (Sandbox Code Playgroud)
调试非常棘手,我真的不知道从哪里开始.首先,什么IS插座挂断错误?是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
});
}
Run Code Online (Sandbox Code Playgroud)
没有直接调用来关闭连接,但我正在使用Node Request它(据我所知)使用http.get所以这不是必需的,如果我错了,请纠正我!
编辑2:这是一个导致错误的实际使用中的代码.prodURL其他变量主要是前面定义的jquery选择器.这使用asyncNode 的库.
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);
}
]);
});
}
Run Code Online (Sandbox Code Playgroud)
Eye*_*Eye 141
socket hang up抛出时有两种情况:
当您作为客户端向远程服务器发送请求时,并未收到任何及时响应.您的套接字已结束,会引发此错误.您应该捕获此错误并决定如何处理它:是否重试请求,将其排队等待以后等.
当您作为服务器(可能是代理服务器)从客户端接收请求,然后开始对其进行操作(或将请求中继到上游服务器),并且在准备响应之前,客户端决定取消/中止请求.
此堆栈跟踪显示客户端取消请求时发生的情况.
Trace: { [Error: socket hang up] code: 'ECONNRESET' }
at ClientRequest.proxyError (your_server_code_error_handler.js:137:15)
at ClientRequest.emit (events.js:117:20)
at Socket.socketCloseListener (http.js:1526:9)
at Socket.emit (events.js:95:17)
at TCP.close (net.js:465:12)
Run Code Online (Sandbox Code Playgroud)
线路http.js:1526:9指向socketCloseListener@Blender上面提到的相同,特别是:
// This socket error fired before we started to
// receive a response. The error needs to
// fire on the request.
req.emit('error', createHangUpError());
...
function createHangUpError() {
var error = new Error('socket hang up');
error.code = 'ECONNRESET';
return error;
}
Run Code Online (Sandbox Code Playgroud)
如果客户端是浏览器中的用户,则这是典型情况.加载某些资源/页面的请求需要很长时间,用户只需刷新页面即可.此类操作会导致上一个请求中止,这会在服务器端抛出此错误.
由于此错误是由客户端的意愿引起的,因此他们不希望收到任何错误消息.因此,无需将此错误视为关键.只是忽略它.这是因为在这样的错误上res,客户端监听的套接字虽然仍然可写,但却被破坏了.
console.log(res.socket.destroyed); //true
Run Code Online (Sandbox Code Playgroud)
所以,除了显式关闭响应对象之外,没有必要发送任何内容:
res.end();
Run Code Online (Sandbox Code Playgroud)
但是,如果您是已经将请求转发给上游的代理服务器,您应该做的就是中止您对上游的内部请求,表明您对响应缺乏兴趣,这反过来会告诉上游服务器,或许,停止昂贵的操作.
Ble*_*der 48
看看来源:
function socketCloseListener() {
var socket = this;
var parser = socket.parser;
var req = socket._httpMessage;
debug('HTTP socket close');
req.emit('close');
if (req.res && req.res.readable) {
// Socket closed before we emitted 'end' below.
req.res.emit('aborted');
var res = req.res;
res.on('end', function() {
res.emit('close');
});
res.push(null);
} else if (!req.res && !req._hadError) {
// This socket error fired before we started to
// receive a response. The error needs to
// fire on the request.
req.emit('error', createHangUpError());
req._hadError = true;
}
}
Run Code Online (Sandbox Code Playgroud)
当服务器从不发送响应时,将发出该消息.
sil*_*orb 44
值得一提的一个案例是:当使用Express从Node.js连接到Node.js时,如果我没有用"/"前缀请求的URL路径,我会得到"socket hang up".
Aek*_*pen 25
我require('http')以前使用https服务,它显示" socked hang up".
然后我使用require('https'),它正在工作.
小智 24
下面是一个简单的例子,当我错过在下面的示例中添加注释代码时,我得到了相同的错误.取消注释代码req.end()将解决此问题.
var fs = require("fs");
var https = require("https");
var options = {
host: "en.wikipedia.org",
path: "/wiki/George_Washington",
port: 443,
method: "GET"
};
var req = https.request(options, function (res) {
console.log(res.statusCode);
});
// req.end();
Run Code Online (Sandbox Code Playgroud)
Sly*_*Sly 15
扩展Blender的答案,这在许多情况下都会发生.我遇到的最常见的是:
User-Agent.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();
}
Run Code Online (Sandbox Code Playgroud)
您可以尝试curl使用从Node发出的标题,并查看是否在那里得到响应.如果您没有收到回复curl,但确实在浏览器中收到了回复,那么您的User-Agent标题很可能会被阻止.
我认为“套接字挂起”是一个相当普遍的错误,表明连接已从服务器端终止。换句话说,用于维持客户端和服务器之间连接的套接字已断开。(虽然我确信上面提到的许多观点对不同的人都有帮助,但我认为这是更普遍的答案。)
就我而言,我发送的请求的负载超过 20K。这被服务器拒绝了。我通过删除文本并重试直到请求成功来验证这一点。确定最大可接受长度后,我验证了添加单个字符会导致错误显现。我还通过从 Python 应用程序和 Postman 发送相同的请求来确认客户端不是问题。所以无论如何,我相信,就我而言,有效负载的长度是我的具体问题。
问题的根源再次是轶事。一般问题是“服务器说不”。
值得一提的另一个案例(对于Linux和OS X)是,如果您使用类似于https执行请求的库,或者如果您https://...作为本地服务实例的URL 传递,那么您将使用端口443作为保留的私有端口并且您可能会结束Socket hang up或ECONNREFUSED错误.
相反,使用port 3000,fe,并执行http请求.
使用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
}
});
Run Code Online (Sandbox Code Playgroud)
经过一番挣扎,我能够解决这个问题 - 因为它出现了非常非常简单的错误.我通过HTTPS协议连接到数据库,但我不断向我的nano对象传递一个keepalive代理,作为使用此库展示的示例(它们依赖于一些使用http的默认值).
使用HttpsAgent的一个简单的改变就是诀窍:
var KeepAliveAgent = require('agentkeepalive').HttpsAgent;
Run Code Online (Sandbox Code Playgroud)
这给我带来了问题,因为我正在执行此处列出的所有操作,但仍然出现错误。事实证明,调用 req.abort() 实际上会抛出一个错误,代码为 ECONNRESET,因此您实际上必须在错误处理程序中捕获该错误。
req.on('error', function(err) {
if (err.code === "ECONNRESET") {
console.log("Timeout occurs");
return;
}
//handle normal errors
});
Run Code Online (Sandbox Code Playgroud)
小智 5
我在向某些服务器请求时遇到了同样的问题。就我而言,在请求选项的标头中为 User-Agent 设置任何值对我有帮助。
const httpRequestOptions = {
hostname: 'site.address.com',
headers: {
'User-Agent': 'Chrome/59.0.3071.115'
}
};
Run Code Online (Sandbox Code Playgroud)
这不是一般情况,取决于服务器设置。
| 归档时间: |
|
| 查看次数: |
307997 次 |
| 最近记录: |