投稿/購読者によるハブと企業の評価

現在、ハブには約350のハブがあります。 サイトの機能により、名前インデックスで並べ替えることができます。 そして、他のパラメータ-たとえば、投稿数 -には、私はしたいと思います。

ハブポストの記事評価に触発され、同様の記事を作成することを決めましたが、ハブ自体の評価を作成することにしました。

記事の前半では、ハブと企業の評価、およびそれらの小さな分析を紹介します。 そして2つ目-JSoupライブラリを使用してJavaでHabraのHTMLページをどのように解析したか、どのような興味深い現象や問題に遭遇したかについて詳しく説明します。 そして、記事の最後に、プログラムの完全なソースコードを示します。



Webページとしての4つの評価(すべて)

ハブの評価


ハブを並べ替えると、興味深いものが現れました。 たとえば、ポストがゼロのハブがあることは知りませんでした。 そして、それらの4がありました ! さらに、 500人以上がそれぞれに加入しています。

3つのハブ- 私はPRWeb開発である 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)'-');//45 System.out.println((int)'–');//8211 

かつて、私の記事Tricky Java Tasksで、 Lが小さい1と区別できない場合のキャッチを調べました。実際、今、私は同様の問題に遭遇しました。

したがって、Habraindexを取得するためのコードはもう少し複雑になります。
 String rawHabraIndex = hubElem.select(".habraindex").get(0).text();//1 265,92 char minus = 45;//'-' char dash = 8211;//'–' String niceHabraIndex = rawHabraIndex.replaceAll(" ", "").replace(",", ".").replace(dash,minus);//1266.72 habraindex = Float.valueOf(niceHabraIndex); 

次に、ハブのネストされた静的クラスとしてポストコンパレーターを記述します
 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ページとして投稿しました

Source: https://habr.com/ru/post/J211775/


All Articles