Node と Cheerio を使用して Web スクレイパーを構築していますが、特定の Web サイトで次のエラーが発生します (このエラーは、この 1 つの Web サイトでのみ発生し、スクレイピングしようとしている他の Web サイトでは発生しません)。
毎回異なる場所で発生するため、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
});
}
接続を閉じるための直接的な呼び出しはありませんが、私はNode Request
これは (私が知る限り) を使用するhttp.get
ので必須ではありません。間違っていたら訂正してください。
編集2: これは実際に使用中のコードの一部で、エラーを引き起こしています。prodURL
他の変数は主に、以前に定義されたjQueryセレクタです。これはasync
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);
}
]);
});
}
ベストアンサー1
がスローされるケースは 2 つあります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)
この行は、特に @Blender が言及したhttp.js:1526:9
ものと同じものです:socketCloseListener
// 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;
}
これは、クライアントがブラウザのユーザーである場合の典型的なケースです。リソース/ページをロードするリクエストには時間がかかり、ユーザーは単にページを更新します。このようなアクションにより、以前のリクエストが中止され、サーバー側でこのエラーがスローされます。
このエラーはクライアントの希望によって発生するため、クライアントはエラー メッセージを受け取ることを期待していません。したがって、このエラーを重大と見なす必要はありません。無視してください。このようなエラーが発生すると、res
クライアントがリッスンしていたソケットは書き込み可能ではあるものの破棄されるため、無視することをお勧めします。
console.log(res.socket.destroyed); //true
したがって、応答オブジェクトを明示的に閉じる以外は、何も送信する意味はありません。
res.end();
ただし、すでにリクエストをアップストリームに中継しているプロキシ サーバーの場合は、アップストリームへの内部リクエストを中止して、応答に興味がないことを示す必要があります。これにより、アップストリーム サーバーに、おそらくコストのかかる操作を停止するように指示できます。