読者です 読者をやめる 読者になる 読者になる

まとめて読もう! 2012年 アドベントカレンダー はてブ数ランキングベスト30 を作ってみた。

あけましておめでとうございます。今年も from scratchと yosuke_furukawaをよろしくお願いいたします。

Perlでプログラム初めをしてました。2012年のアドベントカレンダー記事一覧スクレイピングしてURLだけ取得し、はてなブックマーク数でランキングを作ってみました。

ランキング

No カテゴリ ブログ 2013/1/5現在のはてブ
1 Vim Advent Calendar 2012 : ATND 「Vimを使い始めようと思うんですけど、おすすめを教えてください」 - ぼっち勉強会 939
2 HTML5 Advent Calendar 2012 ちょっとこの辺でHTML5のタグを全部確認してみようぜ!! - WEBCRE8.jp 769
3 #LOVEFONT Advent Calendar 2012 やさしさゴシックの魅力|可愛くて温かい商用可フリーフォント #LOVEFONT Advent Calendar 2012 | Kana-Lier カナリエ 698
4 「サイボウズ・アドベントカレンダー2012」記事一覧 | Cybozu Inside Out | サイボウズエンジニアのブログ 超速で開発・リリースするための6つのこと | Cybozu Inside Out | サイボウズエンジニアのブログ 552
5 Competitive Programming Advent Calendar Div2012 へ、変態っ!!読めないからやめてっ!bit使ったデータ構造・アルゴリズム実装集 - Negative/Positive Thinking 449
6 PHP Advent Calendar 2012 PHPerのMVCの一体どこが間違っていたのか - MugeSoの日記 437
7 【急遽開催】クラスメソッドアドベントカレンダー2012 | クラスメソッド開発ブログ 【追記】【寄せあつめ】今さらだけどSublime Text 2の基本とカスタマイズ【&Vim化】【4日目】 431
8 PHP Advent Calendar 2012 PHPを使う理由 - Shin x blog 317
9 Vim Advent Calendar 2012 : ATND Big Sky :: モテる Vim 使いに読み書き出来ないファイルなどなかったんだよ! 257
10 軽めのjQuery Advent Calendar 2012 jQuery モダンAjaxな書き方を目指して 〜deferredを使ったAJAX〜 - Hack Your Design! 239
11 TDD Advent Calendar jp: 2012 : ATND 「愛せないコードを書くには人生はあまりにも短い」というタイトルで TDD について講演させていただきました #TddAdventJp #devlove2012 - t-wadaの日記 229
12 HTML5 Advent Calendar 2012 Shumpei Shiraishi's Weblog: Web開発を革命する(かも知れない)Web Componentsという仕様について 203
13 C++ Advent Calendar 2012 構造化『並列』プログラミング - どらの日記 202
14 CakePHP Advent Calendar 2012 カンファレンスなどで海外からゲストを呼ぶ際に注意すること : candycane development blog 191
15 Garbage Collection Advent Calendar 2012 エデンの園でおきたこと - steps to phantasien 170
16 【急遽開催】クラスメソッドアドベントカレンダー2012 | クラスメソッド開発ブログ 【クリスマスだし】Internet Explorerとうまく付き合う方法【IE対応まとめ】【25日目の6】 | クラスメソッド開発ブログ 160
17 東京Node学園祭2012 アドベントカレンダー : ATND 「Node.jsは静的コンテンツには向いていない」のか? - hakobera's blog 154
18 tech.kayac.com Advent Calendar 2012 | tech.kayac.com - KAYAC engineers' blog #2「JavaScriptでおっぱいを動かす」 tech.kayac.com Advent Calendar 2012 | tech.kayac.com - KAYAC engineers' blog 153
19 tech.kayac.com Advent Calendar 2012 | tech.kayac.com - KAYAC engineers' blog #12 チームでgitを使い始めてよかった! | tech.kayac.com - KAYAC engineers' blog 153
20 Git Advent Calendar 2012 / Jun. - Qiita 怠惰にgitを使うためのシェル活用術、またはgst一族 #AdventCalendar #git - Qiita 152
21 #LOVEFONT Advent Calendar 2012 丸みがかわいらしいシンプルフォント「Comfortaa」 #LOVEFONT | Arch 150
22 Git Advent Calendar 2012 / Jun. - Qiita Git submodule の基礎 #git #AdventCalendar - Qiita 149
22 HTML5 Advent Calendar 2012 次世代JavaScriptでデータバインディング: Object.observe() を試す - ぼちぼち日記 149
24 軽めのjQuery Advent Calendar 2012 jQueryの$()が多機能すぎる件について。5種類も仕事があるよ。(軽めのjQuery Advent Calendar 2012 – 01日目) | Ginpen.com 145
25 Fireworks Lover Advent Calendar 2012 【Fireworks】ワイヤフレーム作成時に覚えておくと便利なアタリ画像&アタリテキストを簡単に作成する拡張機能 | バシャログ。 139
26 HTML5 Advent Calendar 2012 WebSocketの中身を覗いてみる - m-kawato@hatena_diary 132
27 東京Node学園祭2012 アドベントカレンダー : ATND Node.js で簡単に音声認識できるモジュールを作ってみた #nodefest - 凹みTips 131
28 Sublime Text 2 Advent Calendar 2012 Sublime Text 2によるストレスフリーな開発環境 | ntcncp.net 130
29 Java Advent Calendar 2012 : ATND Javaウェブオペレーションエンジニアがトラブル切りわけ時に見ていること3つ - カイワレの大冒険 125
30 TDD Advent Calendar jp: 2012 : ATND 軽量なテスト駆動開発を目指して #TddAdventJp - やさしいデスマーチ 123

こうしてみると、HTML5,PHP, jQuery等の技術トピックに加えてVimSublime Text2等のエディタが人気だと感じました。

1位の記事もVimだし。去年流行りだしたSublime Text2の人気もすごいですね。Vim vs Emacs vs Sublimeが丁度三国志の様相を呈してきて面白くなりそうです。あと、gitもユーザーごとにTipsがあってアドカレ向きのトピックだと感じました。

あとはkayac、クラスメソッド等の企業でのアドベントカレンダーも人気でした。
こういうところからも企業風土が見えていいですね(kayacの1位の記事がおっぱいの記事というのがなんとも)。

個人的には、ビット演算アルゴリズムまとめが面白かった。
へ、変態っ!!読めないからやめてっ!bit使ったデータ構造・アルゴリズム実装集 - Negative/Positive Thinking

ランキング入りしてないけど面白かった奴


あと、作っている最中に見つけた面白そうなアドベントカレンダーも一緒に紹介しておきます。
子育てエンジニア advent calendar 2012 : ATND
子育てエンジニアがお役立ち育児グッズをひたすら紹介する Advent Calendar 2012

子供を持つエンジニアがどうやって自己研鑚に励んでいるか、という話が良かったです。

この中でもすたじおなんとかさんと皆さんから呼ばれている@studio3104さんの以下の記事が良かったです。

孕ませ駆動結婚のおかげさまでそこそこまともにサラリーマン生活を営めている話 #childrenac2012 - studio3104::Blog


あとは皆のペット自慢アドカレとか。
Tech Pets Advent Calendar 2012

変態アドカレとか。
HENTAI Advent Calendar 2012 - 変態アドベントカレンダー - : ATND



多少斜め上を目指している方々のエントリも面白かった。

スクレイピング方法


というわけで、ランキングの話は終わりです。
あとはこのランキングをどうやって作ったかというPerlの話です。

コード


なんというか、もう少しやりようはなかったのか、という感じですが公開します。

アドベントカレンダー一覧からアドベントカレンダーの募集ページだけを引っ張ってくる(スクレイピングする)コード

use URI;
use Web::Scraper;
use strict;
use warnings;

my $NAVER_URL = 'http://matome.naver.jp/odai/2135217818800380701?page=';

for (1..8) {
  my $naver = scraper {
    process 'a.mdMTMWidget01ItemUrl01Link', 'links[]' => '@href';
  };
  my $url = $NAVER_URL.$_;
  my $res = $naver->scrape( URI->new($url) );
  for my $page (@{$res->{links}}) {
    print "$page\n";
  }
}

アドベントカレンダーのページからブログのURLを引っ張ってくるコード

use URI;
use Web::Scraper;
use HTTP::Lite;

use strict;
use warnings;

our $URL_REGREP = '(?:http|https)://(?:[a-zA-Z0-9-;/?|:@&=+$,_.!~*\'%#]+)';

our $BLACKLIST = '.*io[\/]?\z|.*\.jp[\/]?\z|.*\.com[\/]?\z|.*\.net[\/]?\z|.*partake.*|.*twitter\.com\/.*|.*atnd.*|.*zusaar.*|.*aiit.*|.*worksap.*|.*qiita.*|.*adventar.*|.*atmarkit.*|.*r-project.*|http:\/\/www\.cygwin\.com\/|http:\/\/b\.hatena\.ne\.jp\/entry\/|.*github\.com\/|http:\/\/increments\.co\.jp|https:\/\/mixpanel\.com\/f\/partner|http:\/\/kobitoapp\.com|.*google\.co.*|.*wikipedia\.com.*|.*colorschemedesigner.*|.*wonderfl.*';

our $QIITA = 'http://qiita.com/items.*';

our $EndPoint = 'http://api.b.st-hatena.com/entry.count';

my $file = shift;
my @advent_urls;

my $web = scraper {
  process 'a', 'links[]' => '@href';
};

sub get_links {
  my ($url, $BLACK, $WHITE) = @_;
  my @links;
  my $res = $web->scrape( URI->new($url) );
  for my $page (@{$res->{links}}) {
    if ($WHITE) {
      if ($page =~ /($URL_REGREP)/o && ($page !~ /($BLACK)/ || $page =~ /($WHITE)/)) {
        push(@links, $1);
      }
    } else {
      if ($page =~ /($URL_REGREP)/o && $page !~ /($BLACK)/) {
        push(@links, $1);
      }
    }
  }
  return @links;
}

sub get_numofhatebu {
  my ($url) = @_;
  my $http = new HTTP::Lite;
  my $req = $http->request($EndPoint.'?url='.$url) 
    or die "Unable to get document: $!";
  if ($http->body()) {
    return $http->body();
  } else {
    return 0;
  }
}

open( my $fh, "<", $file)
  or die "Cannot open $file: $!";
while (my $line = readline $fh) {
  chomp $line;
  my @links = &get_links($line, $BLACKLIST, $QIITA);
  for my $link (@links) {
    my $num = &get_numofhatebu($link);
    print "|[$line:title]|[$link:title]|$num|\n";
    if ($link =~ /($QIITA)/o) {
      my $NEW_BLACK = $BLACKLIST.'|'.$QIITA;
      my @qiita_links = &get_links($link, $NEW_BLACK);
      for my $qiita_link (@qiita_links) {
        my $qiita_num = &get_numofhatebu($qiita_link);
        print "|[$line:title]|[$qiita_link:title]|$qiita_num|\n";
      }
    }
  }
}

戦略


スクレイピングモジュールはPerlWWW::Scraperを利用しています。

最初にnaverにまとめられていたAdvent Calendarのまとめ記事からアドベントカレンダーの募集ページだけを収集します。その後、それぞれのページに対して再度スクレイピングして、今度はブログの記事のURLだけを収集し、はてブ数をはてブAPIから取得してコンソールに表示します。

もともと、atnd、partake、qiita、adventar等、アドベントカレンダーの募集ページの種類が多く、最初は真面目にHTML構文解析してたんですが、途中からさじを投げて "ズル" をすることにしました。"ズル"、というのはaタグのhref属性にあるURLしか見ないことにして、正規表現でURLだと判定されたあと、ブラックリストによって必要/不要を選別することにしたのです。トップレベルドメインだけのリンクやtwittergoogle等の明らかにブログではないリンクはブラックリストに入れて無視し、それ以外をひとまず収集。トップ50位のランキングを作った後で、それでもブラックリストを抜けて入ってしまった間違ったページは見て省く、という戦略にしました。最終的には人力です。。。

それにしてもこれだけあると募集ページをどこに作るかだけでも迷ってしまいそうですね。スクレイピングしていた側からすると、adventarが一番楽でした(リンクが少ないので)。atndやconnpass、partakeだと募集ページによってもページ構造がまちまちなので、スクレイピングしにくかったです。atnd, connpass等の募集ページで表組みするのも面倒だと思うので、adventarで募集するのもアリではないでしょうか。

あと、Qiitaのアドカレ募集ページでは、Qiitaのitemページから自分のブログにリンクだけ貼って飛ばしているようなケースもあり、itemページだけを収集するのではなく、さらにitemページの内容もスクレイピングする必要がありました。スクレイピングしていた側からすると、せっかくQiitaに書くならQiitaのページにTipsを書けばいいのにとか少し思いました(^^;)。
(ストックされるとちょっと嬉しい気分になりますよ!)

最後に

というわけで、ちょっと遅れた年賀状です。
今年もよろしくお願い致します。