NodeJSでパーサーを書く

以前は、解析のメインライブラリはJSDOMでしたが、これは過度の重みに悩まされ、実際には解析プロセスが遅くなりました。 しかし、時代は変わり、 チェリオが来ました。 彼はほぼ同じことをすべて行い、余分なものをプロセスから破棄しますが、彼自身はjQueryの一部(つまり、解析に必要なもの)を実装します。 これにより、正規表現を使用して生産性を向上させることなく、最終的に抑制のないパーサーを作成できます。 xmlに対応しています。{xmlMode:true}で呼び出す必要があるのはあなただけです。 猫の下でnodeJSを簡単に解析する方法について。



テクノロジー


Deferredの作成と非同期キューの作成にQを使用し、コンテンツの抽出要求と、それ自体の解析にcheerioを使用します。



真空No.1の例


request(url, function(err, res, body){ if(err){console.log(err);} else{ $ = cheerio.load(body); var cards = []; $('.card').each(function(){ cards.push({ title:$('.title',this).text(), url:$('a',this).attr('href') }); }); } }
      
      







この方法で、ページをスパーできます。



しかし、複数のページがある場合はどうでしょうか? Promiseを使用せずに真正面から解決する場合、2つの問題が発生します。 1つ目はスタックし、2つ目はスコープの複製によりメモリに移動します。 もちろん、すべての悪の根源は再帰的な関数であり、解析時にあまり適していないため、ミサゴのレベルを上げることなく非同期キューを構築する必要があります。



これを行うには、プログラムを2つの段階に分けます。

ステージ1:ページを作成し、合計ページ数を調べる。

ステージ2:解析関数をフックする非同期キューを作成します。



非同期キューで実行される関数は、2つの方法で実行できます。

最初に、各呼び出しに対してサブスコープを事前に生成します(以下のコードでは、生産に入る前に改良が必要です)。



 for(var i = 0; i<l;i+=){ chain.then(asyncF.bind({page: i})); }
      
      







非同期関数内では、this.pageからコンテキストを読み取る必要があります。



別の方法は、共通のデータストリームをグローバル形式で使用し、非同期関数自体の中で既に増加している非同期関数内で、以下に示すように単純に数を転送することです。



真空No.2の例


 //stage 1 request('pager',function(err,res, body){ $ = cheerio.load(body); var pager = $('.pager'); var limitPage = parseInt( pager.eq(pager.length-1).text().trim(), 10); //stage 2 function parsePage(page){ var defer = Q.defer(); request('/pager/'+page,function(err,res, body){ if(page<=limitPage){ defer.resolve(page+1); //              } else { defere.reject(); } //      }); // promise     . return defer.promise; } var chain = Q.fcall(function(){ return parsePage(1); }); for(var i = 2; i<limitPage;i++){ chain = chain.then(function(page){ return parsePage(page); //       ,   . }); } });
      
      







更新:



Node.JSを使用する場合のエンコードの問題:



もともとNode.JSにないエンコードのいずれかを使用するには、データをバッファーとして受け入れる必要があります。そのためには、エンコードを使用して呼び出しを要求する必要があります。nullでiconvライブラリを使用して、既に解析します。



エンコードの例


 var request = require('request'); var Iconv = require('iconv').Iconv; var fromEnc = 'cp1251'; var toEnc = 'utf-8'; var translator = new Iconv(fromEnc,toEnc); request( { url:'http://winrus.com/cpage_r.htm', encoding:null }, function(err,res,body){ console.log(translator.convert(body).toString()); } );
      
      






All Articles