nodejs爬虫プログラムはgbkなどの中国語の符号化の問題を解決します.
9896 ワード
nodejsを使って爬虫類のデモを書きました.目的はホームページのtitle部分を抽出することです. 最大の問題はウェブページのコードとnodejsのデフォルトコードが一致しないことによる文字化けです.nodejsはutf 8、ucs 2、ascii、binary、base 64、hexなどの符号化方式をサポートしていますが、漢語にとって符号化は主に3種類に分けられています.utf-8、gb 2312、gbk.この中のgbkは完全にgb 2312に対応していますので、符号化の処理には主にutf-8とgbkの2つの種類があります.(これは他の国のコード状況を考慮していません.例えば日本のShift-uJISコードなどです.ここではこのiconv-liteモジュールでサポートされている符号化方法は限られています.) まず、ブラウザでウェブページの内容を表示する場合、コードの問題をどう処理しますか?サーバーとクライアントは通信しています.サービス端末は指定された符号化方式(gbkなど)に従ってウェブページをバイナリコードストリームに符号化しています.すなわち、私たちはワイスハークを使ってクローズドして見た16進コードストリームを見ました.クライアントは、ウェブページのソースコードによって規定されたコード方式で、ブラウザから対応するデコーダを呼び出し、バイナリコードストリームを復号して表示します.符号化方式は通常ホームページでは以下のような内容で表示されます.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>` `<meta charset=utf-8"/>
クライアントがnodejs爬虫類要求プログラムである場合、nodejsのデフォルトの符号化方式はutf-8であるため、爬虫類プログラムは受信したバイナリコードストリームを文字列(デフォルトの形式utf-8)で表示すると、文字化けが表示されます.このときは、元のバイナリコードストリームをウェブページの元の符号化方式で復号する必要があります.文字化けは発生しません. したがって、解決方法は以下の通りです. 受信したウェブページのソースをバイナリで保存し、バイナリデータの流れを処理するためにBuffer全体のオブジェクトを使用します.res.on('data', function(data) {
htmlData.push(data);
htmlDataLength += data.length;
});
var bufferHtmlData = Buffer.concat(htmlData,htmlDataLength);
その後、これらのバイナリのデータに対応する復号プログラムを呼び出します.iconv-liteモジュールは復号に用いられ、cherioモジュールはウェブページの内容を解析するために用いられる.decodeHtmlData = iconv.decode(bufferHtmlData,'gbk');
var $ = cheerio.load(decodeHtmlData, {decodeEntities: false});
$('title','head').each(function(i, e) {
htmlHeadTitle = $(e).text();
console.log(htmlHeadTitle);
});
上記のブfferHtmlDataはバイナリコードストリームであり、デコードHtmlDataは、gbk符号化規則を介してバイナリコードストリームをunicode符号化に対応する数字(すなわちusc 2バイトストリーム)に変換し、対応する文字列に変換する.下記はiconv-liteのソースコードの復号部分で、住所はここです.fromEncoding: function(buf) {
buf = ensureBuffer(buf);
var idx = 0, len = 0,
newBuf = new Buffer(len*2),unicode,gbkcode;
for (var i = 0, _len = buf.length; i < _len; i++, len++) {
if (!!(buf[i] & 0x80)) {//the high bit is 1, so this byte is gbkcode's high byte.skip next byte
i++;
}
}
var newBuf = new Buffer(len*2);
for (var i = 0, j = 0, _len = buf.length; i < _len; i++, j++) {
var temp = buf[i], gbkcode, unicode;
if (temp & 0x80) {
gbkcode = (temp << 8) + buf[++i];
unicode = table[gbkcode] || iconv.defaultCharUnicode.charCodeAt(0);//not found in table, replace with defaultCharUnicode
}else {
unicode = temp;
}
newBuf[j*2] = unicode & 0xFF;//low byte
newBuf[j*2+1] = unicode >> 8;//high byte
}
return newBuf.toString('ucs2');
}
最終的に戻ってきたのは、newBuf.toString(‘ucs 2’)文字列であることがわかる. 爬虫類プログラムのソースコードは以下の通りです.var cheerio = require('cheerio');
var http = require('http');
var iconv = require('iconv-lite');
var htmlData = [];
var htmlDataLength = 0;
var count = 0;
http.globalAgent = 'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1';
http.get('http://www.cr173.com', function(res) {
res.on('data', function(data) {
htmlData.push(data);
htmlDataLength += data.length;
count ++;
});
res.on('end',function(){
callback(htmlData);
});
});
function callback(htmlData){
console.log(count);
var bufferHtmlData = Buffer.concat(htmlData,htmlDataLength);
var charset = '';
var decodeHtmlData;
var htmlHeadTitle = '';
var htmlHeadCharset = '';
var htmlHeadContent = '';
var index = 0;
var $ = cheerio.load(bufferHtmlData, {decodeEntities: false});
$('meta','head').each(function(i, e) {
htmlHeadCharset = $(e).attr('charset');
htmlHeadContent = $(e).attr('content');
if(typeof(htmlHeadCharset) != 'undefined'){
charset = htmlHeadCharset;
}
if(typeof(htmlHeadContent) != 'undefined'){
if(htmlHeadContent.match(/charset=/ig)){
index = htmlHeadContent.indexOf('=');
charset = htmlHeadContent.substring(index+1);
}
}
});
// , cheerio buffer,iconv
if(charset.match(/gb/ig)){
decodeHtmlData = iconv.decode(bufferHtmlData,'gbk');
}
else{// charset , utf8
decodeHtmlData = iconv.decode(bufferHtmlData,'utf8');
}
var $ = cheerio.load(decodeHtmlData, {decodeEntities: false});
$('title','head').each(function(i, e) {
htmlHeadTitle = $(e).text();
console.log(htmlHeadTitle);
});
console.log(charset);
}
本文はCSDN村の少年のオリジナル文章で、転载は小さい尾の偶数をプラスすることを覚えていて、博主はここにリンクします.