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

Index

  1. やりたいこと4:自分が観た映画のリストの取得
  2. やりたいこと5:スコアも一緒に取得したい
  3. やりたいこと6:Clips で試してみる
  4. 参照

先ポストの続きです。
今回はもう少し複雑なことを実施してみます。Nokogiri だけでなく、Ruby 用スクレイピングフレームワーク Anemone を使います。

やりたいこと4:自分が観た映画のリストの取得

正規表現書き途中で自信がないですが・・・

sample4.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -- coding: utf-8
require 'nokogiri'
require 'anemone'
opts = {
depth_limit: 1
}
URL = "https://filmarks.com/users/<Username>" # Username を入れてください
Anemone.crawl(URL, opts) do |anemone|
anemone.focus_crawl do |page|
page.links.keep_if { |link|
link.to_s.match(/<Username>?page=d+/) # ここ、自信ないです
}
end
anemone.on_every_page do |page|
doc = Nokogiri::HTML.parse(page.body)
titles = doc.xpath("//html/body/div[3]/div[3]/div[1]/div/h3/a")
titles.each do |title|
p title.text
end
end
end

ruby sample4.rb
結果です。

1
2
3
4
5
6
"ファンタスティック・ビーストと魔法使いの旅"
"ローグ・ワン/スター・ウォーズ・ストーリー"
"ブルーに生まれついて"
"この世界の片隅に"
"湯を沸かすほどの熱い愛"
(長いため以下略)

やりたいこと5:スコアも一緒に取得したい

タイトルと一緒にスコアを一緒に取得してみたいと思います。

sample5.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -- coding: utf-8
require 'nokogiri'
require 'anemone'
opts = {
depth_limit: 1
}
URL = "https://filmarks.com/users/hogehoge" # hogehoge に Username を入れてください
Anemone.crawl(URL, opts) do |anemone|
anemone.focus_crawl do |page|
page.links.keep_if { |link|
link.to_s.match(/hogehoge?page=d+/) # ここ、自信ないです
}
end
anemone.on_every_page do |page|
doc = Nokogiri::HTML.parse(page.body)
# 本当は title と score を分けて記述したかったが、うまくとりだせなかったため、"|"をつかって一度の繰り返しのなかで該当する要素を OR で抽出しています。
titlescores = doc.xpath('//html/body/div[3]/div[3]/div[1]/div/h3/a/text()|//html/body/div[3]/div[3]/div[1]/div/div/div[3]/a/span/text()')
titlescores.each do |titlescore|
p titlescore.text
end
end
end

実行します。
ruby sample5.rb
結果です。

1
2
3
4
5
6
7
8
9
"ファンタスティック・ビーストと魔法使いの旅"
"3.5"
"ローグ・ワン/スター・ウォーズ・ストーリー"
"4.0"
"ブルーに生まれついて"
"4.2"
"湯を沸かすほどの熱い愛"
"5.0"
(以下省略)

こんな形で好きな要素を複数取ってくることもできました。が、だいたいusername?page=5までで止まっているようです。

やりたいこと6:Clips で試してみる

正規表現の部分がおかしいのだと思いますが、うまくいっていないため、今度は観た映画ではなく、観たい映画としてクリップしているタイトルとその平均スコアを取ってきたいと思います。
場所はhttp://.../users/hogehoge/clips?=<数字>です。

sample6.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Clips は配下ディレクトリにあるため、観た映画より試しやすいです。
require 'nokogiri'
require 'anemone'
opts = {
depth_limit: 2
}
URL = "https://filmarks.com/users/rrr" # hogehoge に Username を入れてください
Anemone.crawl(URL, opts) do |anemone|
anemone.focus_crawl do |page|
page.links.keep_if { |link|
link.to_s.match(/clips/)
}
end
anemone.on_every_page do |page|
doc = Nokogiri::HTML.parse(page.body)
titlescores = doc.xpath('//html/body/div[3]/div[3]/div[1]/div/h3/a/text()|//html/body/div[3]/div[3]/div[1]/div/div/div[3]/a/span/text()')
titlescores.each do |titlescore|
p titlescore.text
end
end
end

実行します
ruby example6.rb
結果抜粋です。

1
2
3
4
5
6
7
8
9
10
"ディア・ハンター"
"4.0"
"ジキル博士とハイド氏"
"3.3"
"俺たちは天使じゃない"
"3.5"
"俺たちは天使じゃない"
"3.6"
"ライトスタッフ"
"3.8"

こちらはきちんと全部取り出せていました。

参照

Anemoneによるクローラー入門
Anemone - Information and Examples
パイプ以外にも便利な表現が沢山ありますね。
XPath Cheat Sheet