Google 先生に聞いても意外とわからなかったウェブスクレイピング実践編1

Index

  1. 環境
  2. やりたいこと1:基本サンプルの実行
  3. やりたいこと2:宮沢りえの出演映画を取得
  4. やりたいこと3:宮沢りえの出演映画を一覧で取得
  5. まとめ

先ポスト↓からの続きです。
前置きはいいよ!ということで実際にスクレイピングしていきます。
しかしながら HTML の構造は、作り手とコンテンツ次第で千差万別です。(それ故スクレイピングには一通りの正解のようなものがないのだと思います)
よってここからは、やりたいことごとにサンプルコードを実行して結果を見てみたいと思います。

環境

初っ端からはしょって申し訳ありませんが、スクレイピングの手段として、Ruby, Nokogiri を使います。(Scrapy はコピペしかできない私にはまだ早かったです。)
・ruby 2.3.1p

やりたいこと1:基本サンプルの実行

Qiita で拾ってきたサンプル(URL を変更しました)。
Nokogiriで文字化けを防ぐ - Qiita

sample1.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -- coding: utf-8
require "open-uri"
require "rubygems"
require "nokogiri"
url = "https://filmarks.com/people/63083"
charset = nil
html = open(url) do |f|
  charset = f.charset
  f.read
end
doc = Nokogiri::HTML.parse(html, nil, charset)
p doc.title

実行します。
ruby samble1.rb
結果です。
"宮沢りえの出演・関連映画作品・プロフィール | Filmarks"
何をしたかというと、対象のウェブページのソースにおける、title 部分を取得してきたことになります。
ブラウザで右クリックして”View Page Source”となる部分です(画像は Chrome の例)
f:id:rrringress:20170108005048p:plain
f:id:rrringress:20170108013438p:plain

やりたいこと2:宮沢りえの出演映画を取得

次に、ちょっと応用です。スクレイピングでは何かの一覧を取得する利用例が多いです。
ここでは宮沢りえさんの出演映画をリストとして取得してみたいと思います。
今度はソースコードでもいいのですが、”デベロッパーツール”を使って、Xpath (DOM 構造における住所)を取得してみたいと思います。
試しに「湯を沸かすほどの熱い愛」はどこか確認してみます。
Chrome で、View > Developer > Developer Tools を表示します。
「▶」をたどって該当する場所を上記画像のように探し、右クリックで”Copy XPath”すると、クリップボードに /html/body/div[3]/div[2]/div/div[1]/h3 と保存されます。
f:id:rrringress:20170108010639p:plain
余談ですが、CSS を使って DOM の住所を指定したい場合は、”Copy Selector” を選びます。
先ほどの sample1.rb の最終行の puts するものを、xpath によって変更します。

sample2.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -- coding: utf-8
require "open-uri"
require "rubygems"
require "nokogiri"
url = "https://filmarks.com/people/63083"
charset = nil
html = open(url) do |f|
  charset = f.charset
  f.read
end
doc = Nokogiri::HTML.parse(html, nil, charset)
# doc.xpath("<xpathで指定したい場所>"
# doc.css("<cssで指定したい場所>")
p doc.xpath("//html/body/div[3]/div[2]/div/div[1]/h3").text

実行します。
ruby samble2.rb
結果です。
"湯を沸かすほどの熱い愛"

やりたいこと3:宮沢りえの出演映画を一覧で取得

最後にもうちょっと応用です。これだけでは1タイトルしか取得できていませんので、次に繰り返し構文を用いて、同様の属性を持つものを順番に取得していきます。
同様の属性とはこの場合何なのでしょうか? もう一度デベロッパーツールを参照します。
右隣りにある映画”TOO YOUNG TO DIE! 若くして死ぬ”のタイトルを表示する XPATH は /html/body/div[3]/div[2]/div/div[2]/h3です。
先ほどと比較すると、h3 タグの手前の div がタイトルごとに変わっていくと推測されます。
(このあたりの具体的な方法から、あまりぐぐりきることができず、筆者は時間を浪費しました・・・orz)
似たようなツリーが多すぎて、もう少し丁寧に指定してあげたいときは、class を指定したりしますが、その際は以下を参考にしました。
XPath Cheat Sheet
スクレイピングのためのNokogiri利用メモ - それはそれ。これはこれ。

sample3.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -- coding: utf-8
require "open-uri"
require "rubygems"
require "nokogiri"
url = "https://filmarks.com/people/63083"
charset = nil
html = open(url) do |f|
  charset = f.charset
  f.read
end
doc = Nokogiri::HTML.parse(html, nil, charset)
titles = doc.xpath("//html/body/div[3]/div[2]/div/div/h3")
titles.each do |title|
p title.text
end

実行します。
ruby samble3.rb
結果です。未鑑賞タイトルが多いですが、ひとまず言えることとして直近の2作品は最高でした。(鑑賞してお薦めできるものはリンク付けています。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
"湯を沸かすほどの熱い愛"
"TOO YOUNG TO DIE! 若くして死ぬ"
"トイレのピエタ"
"紙の月"
"魔女の宅急便"
"映画 謎解きはディナーのあとで"
"The Moment -写真家の欲望-"
"ブラックボード 〜時代と戦った教師たち〜/第一夜 軍国主義[未来]"
"夢のまにまに"
"ゼラチンシルバーLOVE"
"オリヲン座からの招待状"
"花よりもなほ"
"晴れた家"
"阿修羅城の瞳"
"父と暮せば"
"トニー滝谷"
"北の国から 2002遺言"
"たそがれ清兵衛"
"ノートルダムの鐘 II"
"うつつ"
"華の愛 遊園驚夢"
"釣りバカ日誌12 史上最大の有給休暇"
"運転手の恋"
"北の国から'98時代"
"北の国から'95秘密"
"天守物語"
"蛍の光"
"四十七人の刺客"
"欽ちゃんのシネマジャック3 ほのぼの編"
"エロティックな関係"
"豪姫"
"どっちにするの。"
"ぼくらの七日間戦争"

では、一つのページから複数の要素を取ってきたり、複数ページにまたがるスクレイピングをしたい場合についてはどうでしょうか?
長くなったため、次のポストで試してみたいと思います。

まとめ

簡易なスクレイピングのチュートリアルができました。
Filmarks さん、勝手に利用して申し訳ありませんでした。いつも愛用させていただいております。
filmarks.com
その他参照 Nokogiri 本家サイト
映画.com でスクレイピングを実施している例 RubyのNokogiriを使ってサイトをスクレイピングする - Think Big Act Local

書籍類 ー自動化や運用までの道のりについても触れられており、満足度の高い内容です。環境作りから丁寧に解説されています。