id:yamaukと申します.最近はてな村にやってきた新参者です.よろしくお願いします.
新参者としましては,はてな村で有力なユーザが誰なのかを抑えておきたいところです.そこで簡単なプログラムを書いて,有力村民をリストアップしてみることにしました.
何をもって有力とするかは色々と考えられますが,今回は基本的な方針として,はてなスターを沢山もらっているユーザを有力村民とみなすことにしました.
ただし,付与されたスターの数をそのまま有力度とすることには色々と問題があるため,今回はPageRankと呼ばれる指標を使います*1.PageRankはWebページ間のリンク構造からページの重要度を決定するアルゴリズムですが,今回はスター付与の関係をリンク構造とみなし,ユーザの有力度の決定に用います.PageRankについてはWikipediaの記事を参照してください.
では,具体的な手法をみていきましょう.
手法
スター付与の関係を有向グラフで表現し,PageRankを計算することで村民の有力度を決定します.
グラフは次のように構築します. 各ユーザをノードとします.ユーザBのコメントに,ユーザAがスターを付けた場合,ノードAからノードBにエッジを張ります. また,各エッジにはスター数で重みを付けておきます.なお,自身のコメントへのセルフスター(ループ)は,本エントリでは無視することにします.
このようにして構築したグラフの各ノードに対して,PageRankを計算します.
実験
実験には以下のツールを使用しました.
- Python (+BeautifulSoup, NetworkX)
- Redis
また,実験に使用したプログラムのソースをGitHubにアップしています. 汚いソースで申し訳ありません.コメント等大歓迎です.
データ収集
ホッテントリのリスト
今回の実験では,はてなブックマークのホッテントリ(http://b.hatena.ne.jp/hotentry)内のエントリを対象とします. 全てのウェブページをクロールすることは不可能であるため,最もスター付与合戦が盛んであると思われるホッテントリに対象を絞りました. また,対象期間は2014/1/1〜2015/4/30としました.*2
ホッテントリのURLリストの取得には以下のプログラムを使用しました.
hatena/get_hotentry.py at master · yamauk/hatena · GitHub
結果として,以下のようなホッテントリのリストを取得しました.
対象期間 | 記事数 |
---|---|
2014/1/1〜2015/4/30 | 24140 |
スター情報
次にはてなスターのデータを収集します.はてなブックマークにははてなスター取得APIが用意されているため,ブックマークに付与されたスターの情報は容易に取得することができます.取得した情報からスター付与関係グラフの隣接リストを作成し,Redisに保存しておきます.
スター情報の取得および隣接リストの作成には以下のプログラムを使用しました.
hatena/get_star.py at master · yamauk/hatena · GitHub
取得したスター情報の統計を以下に示します.2014/1/1〜2015/4/30内のホッテントリのブコメについたスターの情報であることに注意してください*3.
ユーザ数 | 総スター数 |
---|---|
25829 | 3767176 |
ちなみに,スター付与数のトップ3は以下の通りでした.
# | ID | スター付与数 |
---|---|---|
1 | kiya2015 | 151827 |
2 | watto | 107427 |
3 | guldeen | 43102 |
なかなか迫力がありますね.
グラフ構築とPageRank計算
さて,いよいよスター付与関係グラフを構築し*4,PageRankを計算してみます.
先程Redisに保存した隣接リストから,以下のようにしてグラフを構築します.グラフの構築にはNetworkXを使用しました.
hatena/star_network_pagerank.py at master · yamauk/hatena · GitHub
G.add_edge(k, key, weight=v)
とすることで,ノードkからノードkeyに対して,重みvでエッジを張っています(これは,ホッテントリ内におけるkeyさんの全てのコメントに対して,合計v個のスターをkさんが付与したことを意味します).
構築したグラフに対してPageRankを計算してみましょう. PageRankを求めるにはグラフの遷移確率行列の固有値計算などが必要ですが,実はNetworkXのnetworkx.pagerank_scipyメソッドを使って簡単に計算することができます. 先ほどのソースの終わり頃にある,
pagerank = nx.pagerank_scipy(G, alpha=0.85)
でPageRankを計算しています*5. NetworkXは便利ですね.
結果
上記の設定のもと,各ユーザのPageRankを計算した結果を以下に掲載します.
# | ID | PageRank |
---|---|---|
1 | feita | 0.00764836939752 |
2 | xevra | 0.00478677706214 |
3 | cider_kondo | 0.00421880118293 |
4 | IkaMaru | 0.00325257360166 |
5 | nekora | 0.00296871347355 |
6 | watto | 0.00281244908991 |
7 | jt_noSke | 0.0026119632306 |
8 | REV | 0.0026030801699 |
9 | wideangle | 0.00259544671919 |
10 | nakakzs | 0.00252683475568 |
11 | shields-pikes | 0.00242718948013 |
12 | kanose | 0.00238339397978 |
13 | whkr | 0.0023766727969 |
14 | TakamoriTarou | 0.00233194015572 |
15 | uturi | 0.00231578830442 |
16 | htnmiki | 0.00227776074556 |
17 | augsUK | 0.00216262880401 |
18 | Gl17 | 0.00213353383319 |
19 | QJV97FCr | 0.00208664557829 |
20 | mahal | 0.00208207225066 |
栄えあるPageRankトップはid:feitaさんであることが分かりました. 個人的にははてな村の村長と噂されるid:kanoseさんがトップである予想していましたが,id:kanoseさんは12位という結果になりました.残念ですね.
以下に全てのユーザのPageRankを貼っておきます.
hatena/result20140101-20150430_selfstar_removed.log at master · yamauk/hatena · GitHub
感想
何となく実感にあった結果が得られた気がします.よかったですね.
今回はホッテントリに対象を絞りましたが,「世の中」や「政治と経済」など,他のカテゴリを対象にしても面白そうです. また,スター情報ではなく,お気に入りユーザー情報を使ってPageRankを求めると,また違った結果が得られるかもしれませんね.
最後に少し言い訳を.本エントリでやっていることは統計分析でも何でもなく,ただのお遊びです.使用する手法,使用するデータによって結果は異なります.各位,お手柔らかにお願いします.