現在
、ハブには
約350のハブがあります。 サイトの機能により
、名前と
インデックスで並べ替えることができます。 そして、他のパラメータ-たとえば
、投稿数 -には、私はしたいと思います。
ハブポストの記事
評価に触発され、同様の記事を作成することを決めました
が、ハブ自体の評価を作成することにしました。
記事の前半では
、ハブと企業の評価、およびそれらの小さな分析を紹介します。 そして2つ目
-JSoupライブラリを使用してJavaでHabraのHTMLページをどのように解析したか、どのような興味深い現象や問題に遭遇したかについて詳しく説明します。 そして、記事の最後に、プログラムの完全なソースコードを示します。
Webページとしての4つの評価(すべて)ハブの評価
ハブを並べ替えると、興味深いものが現れました。 たとえば、ポストがゼロのハブがあることは知りませんでした。 そして
、それらの4がありました ! さらに、
500人以上がそれぞれに
加入しています。
3つのハブ-
私はPRと
Web開発である Chulanは 、投稿数と読者数の点でリーダーです。 管理者が記事を削除するため、クローゼットは1位です。 次は、ハブで非常に人気のある
情報セキュリティです。
残念ながら、
Habrahabrハブが
オフトピックである理由を理解できませんでした。 投稿数で、彼は
13位になり、彼のサブスクライバーは
80Kを超えます。 同じサイトについてサイトに書くことは、トピックからの逸脱ですか?
Javaハブが私たちが望むほど高くないのは残念でした。
格付け会社
当初はハブに対してのみ評価を作成する予定でしたが、記事へのコメントの中で、彼らは企業に対しても同じことをするという良いアイデアを提示しました。 コードをあまり変更する必要はありませんでした。
多くの企業があります-1343。したがって、TOP-30と最後の10社のみを掲載します。 これは興味深い点です-何らかの理由で、Habrtは
Everything(1331)を表示しますが、私のプログラムでは1343をカウントしていますが、実際、これは正しいです。 それらを手動で数えると-ページ数67に20の会社、さらには3を掛けると-1343になります。
そもそも、「会社が非アクティブ化されている」と「ページが見つからない」という2種類の会社不在があることに驚いた。 繰り返しますが、すべての企業がリストから選ばれました。 投稿数-2でマークした最初のビュー。 そのような会社はたくさんあります。 また、名前が数字で構成されている3つの企業は、「ページが見つかりません」につながります。 -3とマークしました。 そのようなものです。 また、投稿がゼロの企業も多数あります(例:
Apple) 。 なぜ会社のアカウントを作成し、そこからまったく書かないのだろうか?
実際、ハブに登録された1343から、存在しない企業や投稿のない企業を削除すると、321のみになります。そのようなことがあります。
開発
非常に長い間、私は
Habrahabr Apiを理解しようとし
ました 。 判明したように、それは閉じられており、まだ開発中です。 しかし、
support @ habrahabr.ruとの通信で、彼らは自分のページを解析することに何もしないと私に言った。 実際、これはまさにAndroid向けのhabraclientの動作方法です(現時点では)。
「自分用」のプロジェクトになると、大好きなJavaを選択します。 彼女は今回も私を失望させませんでした
-JSoupライブラリにより、HTMLページから必要なデータを
数行で取得でき
ました。 しかし、まずハブがどのように機能するかを説明しましょう。
ハブのあるページは
habrahabr.ru/hubs/pageN/にあります。ここで、Nは1以降の数字です。 したがって、すべてのハブの完全なリストを取得したい場合は、これらのページがダウンロードされるまで、それらが終了するまで分析する必要があります。 各ページにハブのリストがあります。 リストアイテムの形式は非常にシンプルで、解析が容易です。 次のようになります。
<div class="hub " id="hub_50"> <div class="habraindex">1 280,58</div> <div class="info"> <div class="title"> <a href="http://habrahabr.ru/hub/infosecurity/"> </a> <span class="profiled_hub" title=" "></span> </div> <div class="buttons"> <input type="button" class="mini blue subscribeHub" value="" data-id="50"> <input type="button" class="mini hidden unsubscribeHub" value="" data-id="50" "=""> </div> <div class="clear"></div> <div class="stat"><a href="http://habrahabr.ru/hub/infosecurity/subscribers/" class="members_count">91741 </a>, <a href="http://habrahabr.ru/hub/infosecurity/posts/">3385 </a><a></a></div><a> </a></div><a> </a></div>
サイト上
のすべてのハブのリストを返すメソッドを作成しましょう。
static List<Hub> getAllHubs() { ArrayList<Hub> fullHubsList = new ArrayList<>(); String urlHubsIncomplete = "http://habrahabr.ru/hubs/page"; int pageNum = 1; do { String urlHubs = urlHubsIncomplete + pageNum; try { Document doc = Jsoup.connect(urlHubs).get(); Elements hubs = doc.select(".hub"); if (hubs.size() == 0) { break; } for (Element hubElem : hubs) { Hub hub = new Hub(hubElem); fullHubsList.add(hub); } pageNum++; } catch (Exception e) { e.printStackTrace(); break; } } while (true); return fullHubsList; }
無限のwhileループをスピンし、反復ごとに新しいURLを形成します。 次に、
Jsoup.connect(urlHubs).get()を使用して、ハブとそのパラメーターのリストを含むHTMLドキュメントを直接取得します。 ご覧のとおり、ハブ情報ハブには
ハブクラスがあり、
doc.select( "。Hub")を呼び出すことにより、これらの要素のリストを取得します。 サイズがゼロの場合、つまり、最後のページを通過し、すべてのハブを既に分析したことを意味します。その後、ループを終了します。
次に、すべてのハブ要素を
調べ 、それぞれに対してタイプ
ハブのオブジェクトを作成し、
org.jsoup.nodes.Elementをコンストラクターに渡します。 上記と同じ形式のHTMLコードが含まれています。 では、すべてから
抽象化し
ましょう 。 このために、OOPが存在します。 上記のHTMLの一部と、それを詰め込む必要のあるクラスだけが私たちの前にあります。 クラスのフレームワークを書きましょう:
import org.jsoup.nodes.Element; public class Hub { String title; int posts; boolean profiled; int membersCount; float habraindex; String url; public Hub(Element hubElem) { } }
コンストラクタを書きましょう。 始めるために、最も簡単なことをしましょう-ヘッダータグからデータを取得します。 これを行うには、まずフォームのdiv自体を抽出します
<div class="title"> <a href="http://habrahabr.ru/hub/infosecurity/"> </a> <span class="profiled_hub" title=" "></span> </div>
パーシムスルー
Element titleDiv = hubElem.select(".title").get(0); Element tagA = titleDiv.getElementsByTag("a").get(0); title = tagA.text(); url = tagA.attr("href"); profiled = (hubElem.select(".profiled_hub").size() != 0);
次に、サブスクライバーと投稿の数、実際には並べ替えに使用するパラメーターを解析します。 しかし、すぐに最初の問題に遭遇します-タグには文字列
"91741 subscribers"が含まれていますが、これを取得して整数に変換することはできません-文字が含まれています! ここでは、
正規表現が役立ちます。 文字列を受け取り、数値以外のすべてを切り取り、さらに結果をintに変換する巧妙なメソッドをすばやく作成します。
\ Dは数字ではありませんが、
+ -"1回以上発生します。" つまり この場合、文字をvoidに置き換えています。
private int getNumbers(String str) { String numbers = str.replaceAll("\\D+", ""); return Integer.valueOf(numbers); }
これで、冷静な精神ですでに価値を得ることができます。
String membersCountFullStr = hubElem.select(".members_count").get(0).text(); membersCount = getNumbers(membersCountFullStr); String statFullStr = hubElem.select(".stat").get(0).getAllElements().get(2).text(); posts = getNumbers(statFullStr);
原則として、これは停止できますが、興味のために、ハブに関するすべての可能な情報を抽出することにしました。 ここで、非常に興味深い2番目の問題が発生しました。これは
、記事のハイライトです 。 Habraindexを解析する方法は?
まず、コンマをピリオドに置き換え、余分なスペースを削除する必要があります。 しかし、それだけでは十分ではありません! Habraindexをコピーしてコードに貼り付けると、パーサーは引き続きエラーを返します
-Double.valueOf( "-1.11") 。 そして、同じ番号を手動で入力した場合-すべてがOKです。 そして、私の
IDEAでは視覚的にはまったく同じに見えます!
habraのデザイナーは、
マイナスではなく
ダッシュを使用しただけで、異なる文字コードを使用していること、そしてもちろん、パーサーを食べないことがわかりました。 注意してください。 問題の本質は
次のとおりです。
System.out.println((int)'-');
かつて、私の記事
Tricky Java Tasksで、 Lが小さい1と区別できない場合のキャッチを調べました。実際、今、私は同様の問題に遭遇しました。
したがって、Habraindexを取得するためのコードはもう少し複雑になります。
String rawHabraIndex = hubElem.select(".habraindex").get(0).text();
次に、ハブのネストされた静的クラスとしてポストコンパレーターを記述します
public static class ComparePosts implements Comparator<Hub> { @Override public int compare(Hub o1, Hub o2) { return o2.posts - o1.posts; } }
メインのどこかに並べ替えます
List<Hub> hubs = getAllHubs(); Collections.sort(hubs, new Hub.ComparePosts());
すべて、タスクが完了しました! 加入者の数は似ています。 次に、コンソールに2つのリストを表示するコードを作成し、記事にすぐに挿入できるようにしました。最初にそれを行いました。
すべてのハブを取得するには約10秒かかります。 ソースコードは
こちらからダウンロードできます 。
Jsoupをインストールし、パスを自分のものに置き換えることを忘れずに、次のようにビルドして実行します。
javac -cp .;"C:\prog\lib\jsoup-1.7.3.jar" com/kciray/habrahubs/Main.java java -cp .;"C:\prog\lib\jsoup-1.7.3.jar" com.kciray.habrahubs.Main
さらに、同じクラスを再編集して、企業に関する統計を収集しました。 そこには、すべてが似ているように見えますが、会社のブログの投稿数を調べるには、それぞれ個別にページをロードする必要がありました。これには約5分かかりました。 速度を上げるためにマルチスレッドダウンロードを行いました。 habraでは、同時に5〜7ページ以上をロードできないことがわかりました。 実際、
ArrayList <CompanyBlog>を
シリアル化し 、書き留めました。 この100キロバイトのファイルは
2番目のソースにあります-作業できます。
完全な評価と
よりコンパクトな形式に興味がある場合は
、Webページとして投稿し
ました 。