子育て情報アプリを作れるように vol4 ~Youtubeのクローラー~

前回からかなり時間が経ってしまいました。
言い訳すると、
仕事が忙しかったり、
子育てでいっぱいいっぱいだったり、
お盆休みだったからです。
すみません…

今回は、Youtubeから子育て動画を取得してみたいと思います。

今回の目標

  1. 簡単に全体を設計する
  2. Youtubeから動画情報を取得する

1. 簡単に全体を設計する

今回は、YouTubeのサイトをクローリングしますが、
今後YouTubeのサイト以外もクローリングしていくことになるので、
サイトが増えても簡単に追加できる設計にしておきたいと思います。
とは言っても全体がまだ見えていないので、 雰囲気で作ります笑
作りながらメンテしていけば良いかなと思います。
 
(1) サイトを決める
まず、子育て情報どういうサイトから取得するか考えました。
パッと思いついたのが以下。
そして、具体的なサイトも考えます。

(2) 構造設計する
次に構造設計していきますが、
やりたい事は3つ。

  • 各サイトをクローリングする
  • 各サイトをまとめて実行する
  • 各サイトで共通の処理はまとめる

これらを踏まえたファイル構成はこんな感じ。
f:id:tumiki_jp:20150819004958p:plain
githubを使っている関係上、色んなファイルが表示されていますが、
構造設計で重要なのは以下のファイルです。

ファイル 説明
main.rb クローラーをまとめて実行するためのファイル
site.rb 各サイトで共通の処理をまとめたファイル
movie-site.rb 動画サイトで共通の処理をまとめたファイル
youtube-site.rb YouTube用のクローラーファイル

それぞれのファイルの関係を文章でうまく説明できないので、
ソースコードを見てもらったほうが早いと思います。

main.rb

f:id:tumiki_jp:20150819013429p:plain
main.rbはrubyで実行するファイルになります。
実行したいクローラー(YouTubeSite)のインスタンスを生成
それをSiteクラスのコンストラクタに渡す。
それをsitesにセット。これで準備完了
次に、sitesをループさせ、runメソッドを呼び出しているだけです。

site.rb

f:id:tumiki_jp:20150819014156p:plain site.rbもシンプルです。
runメソッドが呼び出されると、
initializeで受け取ったsiteのrunメソッドが呼び出されるだけです。

movie-site.rb

f:id:tumiki_jp:20150819014540p:plain movie-site.rbは継承元クラスになります。
正直、とりあえず用意してみたという感じで、
現時点ではなくても問題ないです。
動画サイトから取得できる情報を保持する変数を用意しています。

youtube-site.rb

この後説明していきます。

 
ここまででとりあえず構造設計は終わりです。
あとからいくらでも修正可能なので次にいきます!

 

2. Youtubeから動画情報を取得する

クローリングするために、ライブラリを使うことになりますが、
今回のアプリでは自由度の高いCapybaraを使っていきます。

先に作成したソースコードをご覧ください。

一つずつ見ていきます。

(1) 最初に

 ①まず、YouTubeのサイトを開いて取得できる動画情報を調べます。

  • 動画のURL
  • 動画のタイトル
  • 動画の説明
  • 動画のカテゴリ
  • 動画の公開日
  • 動画の再生回数
  • 動画のGood数
  • 動画のBad数
  • 動画のコメント
  • 動画のサムネイル画像

 ②Capybaraを使えるようにするには
  インクルードが必要です。
  include Capybara::DSL
  を継承元のmovie-site.rbに書いておきます。

 ③クローリングの処理はrunメソッドの中に
  書いていきます。

(3) Step1 サイトを開く

f:id:tumiki_jp:20150819092217p:plain  Capybara::RackTest::Browser#visitを使います。
 引数にURLを指定するとそのページを開いてくれます。

(4) Step2 検索ワードをセットする

 サイトを開いた後、検索ワードを入力します。
 まず、検索ワードをセットするテキストボックスを探します。
 これには
 Capybara::Node::Element#find
 を使います。
 そして続けてsetメソッドを呼ぶと引数の値をセットしてくれます。
 今回は「子育て 1歳」というキーワードで検索します。
 ※「子育て」だけだと関係ない動画がヒットしまくりだったため苦肉の策で年齢を追加しました。

(5) Step3 検索ボタンをクリックする

 キーワードまでセットできたので、
 次は検索ボタンをクリックします。
 クリックするには、findでボタンを探した後にclickメソッドを呼ぶだけです。
 これで、検索結果が表示されたページが表示されるようになります。

(6) Step4 検索結果を絞り込む f:id:tumiki_jp:20150819092254p:plain

 その日に公開された動画だけ表示します。
 これも簡単で、フィルタボタンをクリックして
 アップロード日の列から「今日」をクリックするだけです。
 ※アップロード日が「今日」で絞り込むと一件もヒットしない可能性があるので、現在はコメントアウトしています

(7) Step5 検索結果をソートする

 アップロード日の新しい順でソートします。
 フィルタボタンをクリックして
 並べ替えの列から「アップロード日」をクリックします。

(8) Step6 URLを取得する

f:id:tumiki_jp:20150819092327p:plain  検索結果ページには動画が20件表示されるので
 それぞれのURLを取得します。
 まずは、各動画が<li>タグで囲われているので、
 <li>エレメントを取得します。
 なお、複数のエレメントを取得するときはallメソッドを使います。
 ※findメソッド複数のエレメントが見つかるとエラーになります。  次に、取得したエレメントそれぞれに対し再度XPathでURLを取得します。

(9) Step7 動画情報を取得する

 Step6で取得したURLの配列をループさせて、動画情報を取得していきます。
 a. 最初に
  visitメソッドを使ってurlのページを開きます。
 b. url
  事前に取得したurlをセットします。
 c. title
  子育て動画の中には「猫」や「犬」の子育て動画も含まれています。
  こういった動画を除外するためにタイトルに
  「犬」「猫」が含まれている場合は飛ばします。
 d. description
  動画の中にはdescription(説明)のない動画があって、
  XPathが見つからない場合があります。(エラーになる)
  なので、descriptionを取得するXPathがあるかどうかを最初にチェックして、
  なかったら「説明なし」としてセットします。
  チェックするにはhas_selector?メソッドを使います。
 e. tags
  動画のタグ情報(カテゴリ)があれば役に立つと思って用意したのですが、
  現在は何もセットしていません。
 f. release_date
  公開日はfindメソッドで取得します。
 g. view_count
  視聴回数はfindメソッドで取得します。
 h. like_count
  Good数は動画によって表示されておらず、XPathが見つからない時があるので、
  事前チェックを行います。has_selector?メソッドを使います。
 i. dislike_count
  Bad数も同じように動画によって表示されておらず、XPathが見つからない時があるので、
  事前チェックを行います。has_selector?メソッドを使います。
 j. comment
  コメントは現在は何もセットしていません。あとで使う予定です。
 k. thumbnail
  サムネイルは現在は何もセットしていません。あとで使う予定です。  

以上でYouTubeクローラーがとりあえず完成です。

実行するとこんな感じで取得します。
f:id:tumiki_jp:20150819203239p:plain  
 
 
今回は結構苦労しました。
今までは本の通りに書いて動いてただけだったので、
自分で一から考えてクローラーを作ろうとすると
いろんな問題に直面して時間がかかってしまいました。
(特にCapybaraの使い方、XPathの書き方が分かっていませんでした。) でも、すごく勉強になりました。
次回は、cookpadのサイトのクローラーを作っていきます。

ここまでこれたのはクロ本のおかげです。ありがたや〜。

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例