Javaではてなブックマークのスクレイピングに挑戦しよう(対象データのスクレイピング編)

こんにちは、らくからちゃです。

前回に引き続きまして、はてなブックマークからブックマークのデータをJavaを使って抽出し、解析を行う方法のプログラムの作り方についてお話したいと思います。本稿は、以下の記事の続きとなりますので、ご承知おき下さい。

さて、前回の記事では『指定のURLにつけられたはてなブックマークのデータを、Javaを使って引っこ抜いてくる方法』についてご説明いたしました。対象となるURLのリストさえあれば、ブックマークをCSVとして保存して解析することが可能です。

ただ、その『リスト』を作るのが大変なんですよね(笑)。例えば『自分のサイトの過去記事つけられたはてブのデータをまとめて引っこ抜いてくる』ということがしたい場合、リストを作るところも自動化したいですよね?

今回は、ウェブサイト上からデータを抽出する技術、一般的にスクレイピング』と呼ばれる技術を使ってその作業を自動化したいと思います。この技術は、あらゆるウェブサイトからデータを抽出する際に応用ができるので、エンジニアさんは覚えておいても損が無いかもしれません。(コンサル的にも、サボりたいときに結構便利)

前回は『JavaでHelloWorldさえ書ければOKです!』と言いましたが、今回はそれに加えて簡単なHTMLの知識が必要になります。ざっくりいうと『HTMLでHelloWordって表示させることが出来るくらいの知識』ですかね。ちょっと自信がない人は、この辺の本もどうぞ!

それじゃあ、

いっくぞー( ・`д・´)

ライブラリの取得と下ごしらえ

 今回、データを抽出するにあたって『jsoup』というライブラリを利用します。まずは、何も考えずに作業を進めて下さい。最初に、下記のページからライブラリをダウンロードします。

次に、前回同様にライブラリの追加を行います。こんな感じですね。

f:id:lacucaracha:20160207095154p:plain

引数も変更しましょう。空白スペースを入れて、1って後ろにつけておきます。

f:id:lacucaracha:20160207095233p:plain

ソースコードの貼り付けと実行

さて、ここまでくれば後は『コピペでOK!』です。前回作成したファイルを、下記のコードに上書きして下さい。(何か、編集している箇所があるかたは、ご注意くださいね!)

gist6f6bc0a2221372b6d71f

どうでしょう?これで実行すると、こんな感じで指定のサイトのブックマークの一覧が出てきますか?

独自ドメインに変更したらどんな影響があるの?(2016年1月度月間報告) - ゆとりずむ,saneyuu,
独自ドメインに変更したらどんな影響があるの?(2016年1月度月間報告) - ゆとりずむ,sukahazafu,アドセンスのことも載ってましたが「子供を捨てるのは何人目だろう」(まんが王国)とか興味のない広告しか表示されないアドセンス(アドワーズ広告)がイヤです。どうしてGoogleは興味のない広告しか表示しないんだろう…
独自ドメインに変更したらどんな影響があるの?(2016年1月度月間報告) - ゆとりずむ,mapbang,
(中略)
寝るときは夫婦一緒?別々? - ゆとりずむ,treve2013,私たちにもそんな時代がありました。子供が出来て育児に必死だった10年間(3人分)を過ぎてみれば。。。嗚呼。
寝るときは夫婦一緒?別々? - ゆとりずむ,OKP,セミシングル並べてクイーンサイズにしてる。布団と枕も別なのでよく眠れるし季節毎に寝具の調整も個々にできるのでオススメ。
寝るときは夫婦一緒?別々? - ゆとりずむ,kun-maa,うらやましくて腹立った(笑)
(中略)
テレビで大流行の『電力自由化』がネットでは殆ど聞かないのは何でだろう? - ゆとりずむ,sawarabi0130,
テレビで大流行の『電力自由化』がネットでは殆ど聞かないのは何でだろう? - ゆとりずむ,wsuzunooto,
テレビで大流行の『電力自由化』がネットでは殆ど聞かないのは何でだろう? - ゆとりずむ,ga_kun,NewsPicks再開しようと思いました。ハイ。

 3件ずつ抜粋してみましたが、対象となるサイトの過去のブックマークが抽出できたかと思います。これがどういう仕組みになっているのか?順番に見ていきましょう。

ブックマークページの構造解析

最初に、31行目にこんな記述があると思います。

url = "http://b.hatena.ne.jp/entrylist?sort=hot&layout=headline&url=" + URLEncoder.encode(args[0], "utf-8") + "&of=" + i * 20;

 このURLを実行すると、こんな感じのページに接続します。

URLの引数部分を変えることで、特定サイトの『新着エントリー』の一覧ページを開くことが出来るんですね。見てお分かりの通り、『ゆとりずむ』がブックマークを獲得した順に、20件ずつページが表示されています。

次に、このページの構造を解析してみましょう。このページは、こんな感じの小さな部品が沢山存在することがわかります。

gistb57ce61d519907ff633a

じゃあ、この『部品』のなかの『URL』、この例だと、『http://www.yutorism.jp/entry/bedroom』の部分を取得し、ブックマークデータの取得用の処理に渡せば、サイト内のブックマークを取得できちゃいますね。

HTMLのパース

勿論、生のテキストデータをガリガリ解析してやっても結果は得られますが、かなり面倒くさいですよね。相当、テキストの解析がしっかりできる人じゃないと難しいように思われます。そこで、力を発揮するのがjsoupです。jsoupを使えば、指定のURL上に存在するデータの構造を解析して、がりがりとJava上で扱うことが出来ます

先ほどのソースコードの38行目から40行目御覧ください。

document = Jsoup.connect(url).timeout(100000).get();
for (org.jsoup.nodes.Element element : document.select("li.entrylist-unit"))

まず、指定されたURLのデータを元に、document変数を作成します。次に、作成された変数に対し、『liタグの中で、entrylist-unitの要素を持っているものを持って来い』という指示を与え、一個ずつelement変数に格納します。

次は、42行目を御覧ください。

url = element.getElementsByTag("a").attr("href");

 element変数に対し、『自分の中で、Aタグの物を取得し、属性値がhrefの値を返せ』という指示を与え、URLを取得しています。これで求めていた『特定サイトにつけられたブックマークのURL』が取得できました。またURLのof以降の指定で、20件ずつ表示されます。その為、全て取得し終えた後はof部分に20を加えし、次のデータを取得します。引数に指定した1は取得ページ数ですので、ここに5を指定すれば、直近100ブックマークを取得します。

ね、簡単でしょう?

ウェブページの構造さえ解析できれば、同じ構造で提供されている情報は容易に取得出来ます。例えばこちらの記事。

日次ブックマークランキングの結果(2015年01月01日の日間ランキング)を元に、同じようなことを行っています。色々と工夫すれば、株価のデータや家賃の情報、ショッピングサイトの最安値などなど、Web上で公開されている多種多様なデータを取得することが出来ます。また、Webブラウザ上の動作を再現することも出来ますので、『一日一回クリック!』とか言っているページの・・・げふんげふん。

ただ大量のデータを取得するということは、相手先のシステムに少なからぬ負荷を与えてしまいます。大規模なサービスとして公開されているシステムであれば、ある程度の処理能力と、それを超えたアクセスがあった場合への備えはしていますので、問題になることはありません。ただ、システム運用者側のシステム設計が甘く、何か問題が生じてしまった場合、色々とお叱りを受けることもあります。

そういったことも胸に留めながら、適切なアクセス量とすることは利用者としての責務ですので、お忘れなく。

さて、これで大量のデータを取得することが出来るようになりましたが、いい加減『画面上に出力する』だけだとつまんなくなってきちゃいましたねw お次は、組み込み型データベースのsqliteに取得したデータを取り込ませ、分析していく方法についてお話したいと思います。

続き

lacucaracha2.hatenablog.jp