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村の少年のオリジナル文章で、転载は小さい尾の偶数をプラスすることを覚えていて、博主はここにリンクします.