初めまして、コロンビア人の学生エンジニアgaruです。
今回はスクレイピングの基礎「open-uri」についてです。

open-uriとは?

open-uriとは、openを拡張してURLをローカルファイルのように開けるrubyライブラリです。
スクレイピングの際、最後に保存をするのに使われる事が多いです。

スクレイピング(クローリング)の利用例

スクレイピングをする時、open-uriは以下のような利用例が考えられます。

大量の画像を保存する

open-uriは画像をデータとして保存できます。
私用ですが、過去に機械学習用で2000枚の画像を保存したことがあります。
スクレイピングは機械学習のデータセット作成にも使われます。

HTML構造を理解する(解析する)

open-uriはサイトのHTML構造をそのまま取得できます。
あのサイトを参考にして、サイトを作りたい時などはHTMLを保存して参考にする良いかもしれません。

サイトが開けるか確認する

実在するのかしないのか曖昧なURLをopen-uriで試しに開いてみて、アクセスエラーがないか確認する使い方も良いかもしれません。

open-uri を使ったスクレイピングでHTML(or画像)を取得する

require 'open-uri'
tmp = open('http://rooter.jp/')
#  => #<Tempfile:/var/folders/3s/w10jlsdx029b726z16dj6fm80000gn/T/open-uri20180409-4585-1xgi05t>

openするだけでは何も出来ないので、出力や保存をしてみます。

# 中身(HTML)を出力
tmp.read
#  => "<!doctype html>\n<html(略 

# 文字コードを出力
tmp.charset
#  => "utf-8" 

# 弊社のロゴを保存
image = open('http://rooter.jp/wp-content/uploads/2018/03/rooter_logo.png')
open("rooter_logo.png", "w+b") do |out|
  out.write(image.read)
end

他のライブラリでクローリングして、最後に取得したURLをopen-uriで開くなどすると良いでしょう。


open-uriでつまづく箇所

httpからhttpsにリダイレクトされたらどうなるの?

=> 怒られます。

open('http://yahoo.com')
#  => RuntimeError: redirection forbidden: http://yahoo.com -> https://www.yahoo.com/

リダイレクトを許可するgemを入れましょう。

require 'open_uri_redirections'
open('http://yahoo.com', allow_redirections: :all)
#  => #<Tempfile:/var/folders/3s/w10jlsdx029b726z16dj6fm80000gn/T/open-uri20180409-4585-sewwr3>

Basic認証は突破できない?

=> できます。「http_basic_authentication」を使いましょう。

certs = ['user', 'pass']
open(url, :http_basic_authentication => certs)
#  => #<Tempfile:/var/folders/3s/w10jlsdx029b726z16dj6fm80000gn/T/open-uri20180409-4585-vcjw6u>

スマホ版のHTML構造を取得したい

=> User Agentを設定しましょう。

ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
open(url,  'User-Agent' => ua)



最後に(open-uriの便利な使い方)

いかがだったでしょうか。
スクレイピングにおいてopen-uriは、シンプルで使用頻度の高いライブラリになります。
使用頻度が高いので、openのまま利用せず下記のようなメソッドにするともっと便利に使えたりします。
参考までにどうぞ。

UA_CHROME = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36'.freeze

def get_html(url, ua = UA_CHROME)
  open(url, 'User-Agent' => ua, allow_redirections: :all).read
end