Html Agility Pack-便利な.NET HTMLパーサー

みなさんこんにちは!

かつて、Habréに投稿された空席を分析するというアイデアが思いつきました。 私は、給料の規模と高等教育の利用可能性との間に相関関係があるかどうかに特に興味がありました。 そして今、学生たちは(私のものも含めて)セッションを行っているので、おそらく誰かが試験で神経質になろうとするのにもう疲れているかもしれません。この分析は役に立つでしょう。

私は.Netのプログラマーなので、この問題を解決することにしました-Habrの広告をC#で解析することにしました。 HTML行を手動で解析したくなかったので、タスクを達成するのに役立つHTMLパーサーを見つけることにしました。

今後は、分析から何もおもしろくなく、セッションをさらに進める必要があると思います:(

しかし、その後、非常に便利なHtml Agility Packライブラリについて少しお話します



パーサーの選択



Stackoverflow についての議論を通してこのライブラリに行きました。 コメントは、ソリューションを提案しました。たとえば、HTMLをXmlDocumentに変換するSgmlReaderライブラリ、および.NetツールのXML用のフルセットのツールです。 しかし、何らかの理由でこれは私を賄briしませんでしたので、Html Agility Packをダウンロードしに行きました。



クイックツアーHTML Agility Pack



ライブラリのヘルプは、プロジェクトページからダウンロードできます。 機能は実際にとても幸せです。

20の主要なクラスを利用できます。







メソッドの名前は、 DOMインターフェース ( 備考 k12th )+パンに対応しています :GetElementbyId()、CreateAttribute()、CreateElement()など。JavaScriptを処理する必要がある場合に特に便利です。

htmlはまだXmlでオーバーライドされており、HtmlDocumentと他のクラスはラッパーであるように見えますが、これには何の問題もありません。



Parsim Habr!



Habréの求人は表形式で表示され、行は必要な専門分野と給与に関する情報を提供しますが、教育に関する情報が必要なため、空席のページに移動して分解する必要があります。

それでは、始めましょう、そこから給与とポジションに関するリンクと情報を取得するためのテーブルが必要です:

  1. static void GetJobLinks ( HtmlDocument html )
  2. {
  3. var trNodes = html。 GetElementbyId ( "job-items" ) 。 ChildNodes 。 Where ( x => x。Name == "tr" ) ;
  4. foreach ( trNodesのvarアイテム)
  5. {
  6. var tdNodes =アイテム。 ChildNodes 。 Where ( x => x。Name == "td" ) 。 ToArray ( ) ;
  7. if ( tdNodes。Count ( ) != 0 )
  8. {
  9. var location = tdNodes [ 2 ] 。 ChildNodes 。 Where ( x => x。Name == "a" ) 。 ToArray ( ) ;
  10. jobList。 追加 ( 新しい HabraJob ( )
  11. {
  12. Url = tdNodes [ 0 ] ChildNodes 。 最初 ( ) 。 属性 [ "href" ] 。 価値
  13. タイトル= tdNodes [ 0 ] 。 FirstChild InnerText 、
  14. 価格= tdNodes [ 1 ] 。 FirstChild InnerText 、
  15. 国=ロケーション[ 0 ] 。 InnerText 、
  16. 地域=ロケーション[ 2 ] 。 InnerText 、
  17. 市=場所[ 2 ] 。 InnerText
  18. } ) ;
  19. }
  20. }
  21. }


その後、各リンクを調べて教育に関する情報を取得すると同時に、雇用も取得する必要があります。空席へのリンクを持つテーブルが既知のIDを持つdivにある場合、空席に関する情報はテーブルに存在しないという小さな問題があります。 id、だから私は少しひねる必要がありました:

  1. static void GetFullInfo ( HabraJob job )
  2. {
  3. HtmlDocument html = new HtmlDocument ( ) ;
  4. html LoadHtml ( wClient。DownloadString ( job。Url ) ) ;
  5. // html.LoadHtml(GetHtmlString(job.Url));
  6. //これはできません:-(
  7. var table = html。 GetElementbyId ( "main-content" ) 。 ChildNodes [ 1 ] 。 ChildNodes [ 9 ] 。 ChildNodes [ 1 ] 。 ChildNodes [ 2 ] 。 ChildNodes [ 1 ] 。 ChildNodes [ 3 ] 。 ChildNodes 。 Where ( x => x。Name == "tr" ) 。 ToArray ( ) ;
  8. foreach (表のvar tr )
  9. {
  10. 文字列カテゴリ= tr。 ChildNodes 。 FindFirst ( "th" ) 。 InnerText ;
  11. スイッチ (カテゴリ)
  12. {
  13. ケース 「会社」 :
  14. 仕事。 会社 = tr。 ChildNodes 。 FindFirst ( "td" ) 。 FirstChild InnerText ;
  15. 休憩;
  16. ケース 「教育:」 :
  17. 仕事。 教育 = HabraJob。 ParseEducation ( tr。ChildNodes。FindFirst ( "td" ) 。 InnerText ) ;
  18. 休憩;
  19. ケース 「雇用:」 :
  20. 仕事。 雇用 = HabraJob。 ParseEmployment ( tr。ChildNodes。FindFirst ( "td" ) 。 InnerText ) ;
  21. 休憩;
  22. デフォルト :
  23. 続ける;
  24. }
  25. }
  26. }


結果



それでは、結果をXMLで保存し、Excel-eで何が起こったのかを調べます...そして、ほとんどの企業は給与の金額を示さないか、教育に関する情報を示さない(忘れて、本文で示す)欠員、本当に重要ではない)、または一度にすべてを示すものではありません。

気にする人は、ここにxlsxとxmlの結果があり、ここにソースがあります



PS



解析時に、このような問題が発生しました-ページのダウンロードが非常に遅くなりました。 そこで、最初にWebClientを試し、次にWebRequestを試しましたが、違いはありませんでした。 グーグル検索では、コードでプロキシを明示的に無効にする必要があることが示され、その後はすべてうまくいきますが、それも助けにはなりませんでした。



All Articles