講習会 スクレイピング入門

2015.12.17 理工学図書館TA 情報科学研究科 M2 加藤

はじめに

スクレイピングとは普段使っているブラウザ(Internet Explorer, Google Chrome, Safariなど)ではなくプログラムからインターネットにアクセスする技術です。注意事項
として人間が操作するのとは異なりプログラムからは高速アクセスが可能です。使い方を誤ると事件になる場合(Librahack事件)もありますのでウェブサイトの利用規約を先に確認するなど十分注意してください。プログラムからアクセスしていいかを確認するためにRubyではRobotexというライブラリを併用することをおすすめします。

また、電子ジャーナル・電子ブックのウェブサイトに対してスクレイピングを行うと、機械的なダウンロードと判断されて大阪大学全体の利用が停止される恐れがありますので絶対に行わないでください。

**追記: 図書館のページから見ている方へ**
準備で使っている`sample.html`はこのリンクから入手できます.
また以下では順を追ってプログラムを作り上げていきますが,完成後のプログラムも同じディレクトリに入っていますので,
分からなくなった方は参考にしてみて下さい.

環境の動作確認

こちらで用意した環境を使用するか、自前でライブラリのインストールを行って下さい。以下はUbuntu(Linux)とFirefoxを用いて説明をしますので,自分で環境を用意する方は適宜読み替えて下さい.

1. こちらで用意した環境を使う場合

Virtualbox(https://www.virtualbox.org)をインストールしたあと, Ubuntu.ovaをダウンロードし起動。
*「Ubuntu.ova」のリンクをクリックすればダウンロードできます。ファイルサイズが2.2GBと大きいのでインターネット接続環境の良いところでダウンロードしてください。
 *「Ubuntu.ova」をダウンロードした際に、別の拡張子(.tar)に変わってしまった場合は、ファイルの名前の変更で、拡張子部分を「.ova」に修正してください。

インターネットの接続

ターミナル

  1. cd Desktopでデスクトップに移動
  2. lsでファイル一覧を出す

Ruby

コマンド編
  1. テキストエディタで
    puts "hello, world"
    puts 2**10
    test.rbという名前でデスクトップに保存
  2. ターミナルでruby test.rbで実行

2. 自前でライブラリを用意する場合

Rubyにてpry,robotex,nokogiriをインストールしてあればOKです。

pry編
  1. ターミナルを開いてpryと打ってみる
  2. [1] pry(main)>が出てきたらputs "hello, world"と打ってみる
  3. exitでターミナルに戻る

注) PryはRubyを1行ずつ動かすための環境

予備知識

普段目にするウェブページはhtmlで表現されている。そのhtmlの中身がどうなっているかをsample.htmlを使って簡単に紹介する。

HTMLの構造
<!DOCTYPE html>
<html lang="ja">
 
<head>
  <meta charset="UTF-8"/>
  <title>HTMLのサンプル</title>
</head>
 
<body>
  <h1>Hello, everyone!</h1>
  <div class="favorite">
    <h3>What I like is ...</h3>
    <ul>
        <li id="food">apple</li>
        <li id="sport">baseball</li>
        <li id="instrument">cello</li>
    </ul>
  </div>
</body>
 
</html>
XPath

XMLに準拠した文書(=HTML)の特定の部分を指定する言語(Wikipedia)

Ruby(超入門)
candidates.each do |candidate|
  # 何か処理 
  # 例えばputs candidateとすればcandidatesそれぞれの要素を出力する 
end

スクレイピングに挑戦

練習

まとめ

pryexitと打ちターミナルに戻り、ruby practice.rbで同じ結果が出ることを確認

xpathの探し方

xpath(発展版)

Yahooニュース一覧のスクレイピング

実践!ブログの記事タイトル一覧取得

require 'nokogiri'
# ローカルではなくウェブページを開くのに必要 
require 'open-uri'
# 実際のウェブページをスクレイピングしていいか確認できるライブラリ 
require 'robotex'
 
robotex = Robotex.new
url = '?????'
 
if robotex.allowed?(url)
  # おまじない 
  UserAgent = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)'
  html = open(url, 'User-Agent' => UserAgent).read
 
  doc = Nokogiri::HTML(html)
  doc.xpath('?????').each do |node|
    node.xpath('.?????').each do |a|
      puts a.text
    end
  end
else
  puts 'Now allowed :-('
end

Flickrから画像を取得してみる

require 'nokogiri'
require 'open-uri'
require 'robotex'
def save_image(url)
  filename = File.basename(url)
  open(filename.to_s, 'wb') do |file|
    open(url) do |data|
      file.write(data.read)
    end
  end
end
url = "?????"
# picsは画像のurlを入れるための配列(最初は空) 
pics = []
robotex = Robotex.new
if robotex.allowed?("https://www.flickr.com") then
  doc = Nokogiri::HTML(open(url))
doc.xpath("?????").each do |link|
puts link
end
end
if robotex.allowed?("https://www.flickr.com") then
  doc = Nokogiri::HTML(open(url))
  doc.xpath("?????").each do |link|
    puts ?????
  end
end
<div style="transform: translate(758px, 1015px); -webkit-transform: translate(758px, 1015px); -ms-transform: translate(758px, 1015px); width: 302px; height: 187px; background-image: url(//c4.staticflickr.com/8/7012/6672150457_420d61007d_n.jpg)">


transform: translate(758px, 1015px); -webkit-transform: translate(758px, 1015px); -ms-transform: translate(758px, 1015px); width: 302px; height: 187px; background-image: url(//c4.staticflickr.com/8/7012/6672150457_420d61007d_n.jpg)

正規表現入門
私は人です OK
私は男です OK
僕は人です NG
私は長男です NG
あろうことか私は熊ですと答えてしまった。 ?
= "あろうことか私は熊ですと答えてしまった。"
puts a.match(/私は.です/).to_s #=> 私は熊です 

再びFlickrから画像を取得してみる

if robotex.allowed?("https://www.flickr.com") then
  doc = Nokogiri::HTML(open(url))
  doc.xpath("?????").each do |link|
    puts link.attr('style').match(//).to_s
  end
end
if robotex.allowed?("https://www.flickr.com") then
  doc = Nokogiri::HTML(open(url))
  doc.xpath("?????").each do |link|
    puts "" + link.attr('style').match(//).to_s
  end
end
if robotex.allowed?("https://www.flickr.com") then
  doc = Nokogiri::HTML(open(url))
  doc.xpath("?????").each do |link|
    pics << "" + link.attr('style').match(//).to_s
  end
end
pics[0, 5].each do |pic_url|
  save_image(pic_url)
end
まとめ