Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
97
Help us understand the problem. What is going on with this article?
@rinkun

Rubyでスクレイピングしてみました。

More than 3 years have passed since last update.

スクレイピングに挑戦したのでサンプルコードを公開。
スクレイピング楽しいね :laughing:

Railsではなく素のRubyコードを書きました。
gemはbundlerでインストール。
bundlerでインストールしたgemを読み込む方法はこちら

mechanize編

最初に挑戦したのはmechanizeというgem。
WEBサイトのインタラクションを自動化してくれるgemだそうです。
http://docs.seattlerb.org/mechanize/

今回は、絵本ナビから、
「くすのきだんち」シリーズのタイトル一覧と表紙画像を取得して、
タイトルをターミナルに表示、画像をローカルに保存します。

では早速作業開始。

$ mkdir scraping
$ cd scraping
$ rbenv local 2.2.3
$ bundle init
$ vim Gemfile
// gem 'mechanize'と追記してください。

$ bundle install --path vendor/bundle
$ touch ehon.rb
ehon.rb
# bundler経由でインストールしたgemを有効にするには下記のようにする
require 'bundler'
Bundler.require

# 検索したい絵本のタイトル URL用に日本語をエンコーディングする必要あり
keyword = "くすのきだんち".encode("Shift_JIS")

# 「K」というパラメーターにkeywordを渡してやれば検索結果の一覧を表示できるみたい
target_url = "http://www.ehonnavi.net/ehon01.asp?sel=1&K=#{keyword}"

# 画像の格納ディレクトリ なければ作る
dir_path = "./imgs"
FileUtils.mkdir_p(dir_path) unless FileTest.exist?(dir_path)

# スクレイピング用のコード
# クラス名'.detailOneCol'で絞り込んで、eachでまわしながら、
# 1件ずつタイトルを出力 画像は保存
agent = Mechanize.new
search_page = agent.get(target_url)
search_page.search('.detailOneCol').each do |item|
 puts title = item.search('div.text h3').inner_text # さらに絞り込み
 search_page.image_with(alt: "#{title}").fetch.save("#{dir_path}/#{title}.jpg") # altの値がtitleと一致しているので絞り込める
end

できたら、

$ ruby ehon.rb

わお!すごい :flushed:
たったこれだけで望みが叶いました。

scraping.rb
agent = Mechanize.new
search_page = agent.get('http://example.com')
p search_page.links[0].click

とすると、リンク先のページも取得できます。

scraping.rb
agent = Mechanize.new
search_page = agent.get('http://example.com')
form = search_page.forms[0]
form.name = 'name'
form.password = 'secret'
p agent.submit(form)

とすると、フォームの項目を入力してサブミットした先のページを取得できます。

しかし、mechanizeは普通に使うと、JavaScriptを実行できません。
あれっ、どうしよう :cold_sweat:

Capybara + Poltergeist(PhantomJS)編

クリックイベントなどJSを実行して動的にページを操作したい場合は、
ブラウザ上のアクションをシュミレートするCapybaraと、
JavaScriptのドライバを組み合わせて実現します。

今回はドライバにPhantomJSを使用します。
さらにRubyからPhantomJSを扱えるように、Poltergeistというgemを導入します。

Capybara
https://github.com/jnicklas/capybara

Poltergeist
https://github.com/teampoltergeist/poltergeist

Gemfileに追記。

gem 'capybara'
gem 'poltergeist'

できたら、bundle install

PhantomJSもインストールしてください。

$ brew install phantomjs

バンダイチャンネルから、「犬夜叉 第1期」全44話の各話タイトルをターミナルに表示してみます。

http://www.b-ch.com/ttl/index.php?ttl_c=2277
にアクセスすると、ページの右側に「作品情報」が見えると思います。
下部のメニューから「各話あらすじ」のリンクをクリックすると、onClickイベントで第1話のタイトルとあらすじが表示されます。
「各話あらすじ」という見出しの下のページネーションをクリックしていくと、さらにonClickイベントで内容が書き換えられて、各話のタイトルとあらすじが確認できます。

これをCapybaraを使って、自動化すると下記のようになります。

$ touch bandai.rb
bandai.rb
require 'bundler/setup'
require 'capybara/poltergeist'
Bundler.require

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, {:js_errors => false, :timeout => 1000 })
end
session = Capybara::Session.new(:poltergeist)
session.visit "http://www.b-ch.com/ttl/index.php?ttl_c=2277"
puts session.status_code
puts '各話タイトル'

# 「各話あらすじ」をクリックする => onClickが実行される 
session.find('div.ttlinfo-menu').all('ul')[0].all('li')[2].find('a').click

# 第1話タイトル
puts session.find('div#ttlinfo-stry').find('dt').text

# 第2話タイトル〜
# 最終話は動的に取得してもよいかも
2.upto(44) do |num|
  # onClickイベント ページネーションクリック
  session.find('div#ttlinfo-stry').find('p#page-list').click_link num.to_s
  sleep 3 # ajaxで内容が書き換えられる間少し待つ。待ち時間は適当...
  puts session.find('div#ttlinfo-stry').find('dt').text
end
$ ruby bandai.rb

また一つ望みが叶いました。
難しいことはまだまだですが、勉強になりました :smile:

97
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
rinkun
30を目前に「手に職」への憧れが捨てられず、サラリーマンをやめて、フリーランス、プログラミングの世界に飛び込みました。 WEBをメインに、エクセルVBAとキッズプログラミングでScratchとUnityを少々。 最近はPWAとPhina.jsに興味があります。 サークルアラウンド(株)佐藤正志氏に師事。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
97
Help us understand the problem. What is going on with this article?