はじめに
本記事は、2021 RUNTEQアドベントカレンダー5日目の記事になります!
現在ポートフォリオを作成しており、その作成過程でスクレイピングを用いて必要な情報を取得しDBに格納しました。今回はそこで使用したgem Mechanizeについて書いていこうと思います!
この記事でわかること
gem Mechanizeについて
- できること
- 提供しているメソッド
- PFで用いたDBに格納する方法
##できること
まず概要を公式より見てみます
Mechanizeライブラリは、ウェブサイトとの対話を自動化するために使用されます。Mechanizeは、自動的にクッキーを保存、送信し、リダイレクトを行い、リンクをたどり、フォームを送信することができます。フォームフィールドは入力して送信することができます。また、Mechanizeは、あなたが訪問したサイトを履歴として記録します。
ざっくりとした解釈ですが、自動的にwebサイトに訪問して、フォームがあれば入力もできちゃうよ〜ってことですね。 webサイトを自動で訪問できるので、そこでスクレイピングしたいページにとび、取得したいデータのみ抽出するという処理も書けちゃうわけです
##提供しているメソッド
下準備
メソッドの説明に入っていくのですが、gemをinstallすると、mechanizeクラスが使えるようになります。
公式では下準備としてインスタンス化してくださいとあるので、下記のように設定します
# 公式には下記の記載がありますが、Ruby1.9以降では必要ないのでコメントアウトします
# require 'rubygems'
require 'mechanize'
class Scraping
agent = Mechanize.new
end
get
スクレイピングしたいwebサイトのHTMLを取得してくれます。
require 'mechanize'
class Scraping
def self.hoge
agent = Mechanize.new
page = agent.get("https://www.hogehoge.co.jp/")
end
end
コンソールで実行してみます
irb(main):001:0> Scraping.hoge
=> #<Mechanize::Page
{url #<URI::HTTPS https://www.hogehoge.co.jp/>}
{meta_refresh}
{title "公式サイト | Japan"}
{iframes
#<Mechanize::Page::Frame
nil
...
#<Mechanize::Page::Link "ホーム" "/">
#<Mechanize::Page::Link "\n" + "メニュー\n" + "\n" + "\n" "/menu/">
#<Mechanize::Page::Link "おすすめ" "/menu/">
#<Mechanize::Page::Link "バーガー" "/menu/burger/">
#<Mechanize::Page::Link "セット" "/menu/set/">
#<Mechanize::Page::Link "サイドメニュー" "/menu/side/">
#<Mechanize::Page::Link "ドリンク" "/menu/drink/">
...
これ以上は長くなってしまうので省きますが、これだけでもざっくりページの情報を得られているのがわかると思います〜〜
search
cssを指定するのと同じ要領で要素を指定できます。タグはそのまま指定。
classを指定する際は、「.(ドット) class名」。idを指定する際は、「#(シャープ) id名」といった感じですね。返り値は配列の形式で返ってきます。
試しにli a
を指定し、格納した配列を出力してみます
class Scraping
def self.hoge
agent = Mechanize.new
page = agent.get("https://www.hogehoge.co.jp/")
elements = page.search('li a')
puts elements
end
end
コンソール
irb(main):001:0> Scraping.hoge
<a href="/" class="no-underline block h-xs line-height-md p-2:lg my-0 font-semibold active">ホーム</a>
<a href="/menu/" class="no-underline block h-xs line-height-md p-2:lg my-0 font-semibold flex justify-between items-center">
<span>メニュー</span>
<span class="header-submenu-toggle-btn"></span>
</a>
<a href="/menu/" class="no-underline">おすすめ</a>
<a href="/menu/burger/" class="no-underline">バーガー</a>
<a href="/menu/set/" class="no-underline">セット</a>
<a href="/menu/side/" class="no-underline">サイドメニュー</a>
<a href="/menu/drink/" class="no-underline">ドリンク</a>...
先程とは違い、要素を取得できているのがわかります!
at
searchメソッドと同じ要領で要素を指定し、該当する1件のみ取得することができます
先程の文法のまま、searchの部分をatメソッドに変更すると、コンソール上では1件のみ取得できるのがわかります!
irb(main):001:0> Scraping.hoge
<a href="/" class="no-underline block h-xs line-height-md p-2:lg my-0 font-semibold active">ホーム</a>
### get_attribute タグの属性値を取得することができます。属性値とは例えばaタグの中の、href属性に指定されてるURLのことを指します。先程searchメソッドで取得した配列のうち、get_attributeメソッドを使用して、URLの情報を取得してみます
class Scraping
def self.hoge
agent = Mechanize.new
page = agent.get("https://www.hogehoge.co.jp/")
elements = page.search('li a')
urls = []
elements.each do |element|
urls << element.get_attribute(:href)
end
puts urls
end
end
コンソール
irb(main):001:0> Scraping.hoge
/
/menu/
/menu/
/menu/burger/
/menu/set/
/menu/side/
/menu/drink/
inner_text
searchメソッドやatメソッドではタグも含めて全て取り出していましたが、inner_textメソッドではタグの中身のテキストだけを取り出すことができます。
searchで取得した情報にinner_textメソッドを使用してみましょう
class Scraping
def self.hoge
agent = Mechanize.new
page = agent.get("https://www.hogehoge.co.jp/")
elements = page.search('li a').inner_text
puts elements
end
end
コンソール
irb(main):001:0> Scraping.hoge
ホーム
メニュー
おすすめバーガーセットをご案内私たちの責任お店・サービス
季節の商品はこちらから!
会員登録不要
...
テキストだけ取得することができました。
このような形で、サイトに応じてメソッドを使用すればDBに必要な情報を好きなように取得し、格納することもできそうです
PFで用いたDBに格納する方法
上記のメソッドを活用して、実際にDBにスクレイピングしたデータを格納していきます。
仮想のページから、簡易的ですが商品名(name)、価格(price)、説明(description)のカラムを持ったfoodsテーブルを作成し、こちらに格納していきます。テーブル作成は割愛します
require 'mechanize'
class Scraping
def self.hoge
agent = Mechanize.new
links = []
page = agent.get("https://www.hogehoge.co.jp/menu/burger/")
# elementsには商品詳細へのHTMLが格納されています
elements = page.search('.product-list-card a')
# each doメソッドで各HTMLに対し処理を実行。get_attributeメソッドを活用してリンクを取得しlinksに格納しています
elements.each do |ele|
links << ele.get_attribute(:href)
end
# 取得した各リンクを引数としget_foodメソッドを実行します
links.each do |link|
get_food("https://www.hogehoge.co.jp/#{link}")
end
end
まず第一段階で一覧ページから、各商品詳細情報のリンクを取得し、linksの配列に格納していきます
require 'mechanize'
class Scraping
def self.hoge
...
end
def self.get_food(link)
agent = Mechanize.new
page = agent.get(link)
name = page.at('.pdp__product-info h1').inner_text
price = page.at('.items-baseline').inner_text
description = page.at('.pdp__product-info p').inner_text
Food.create(name: name, price: price, description: description)
end
end
第二段階で、取得した各商品詳細情報から、必要な情報を指定して取得し、最後にcreateするとDBに格納することができます!!
# 終わりに 最後までご一読いただきありがとうございました! 同じように、ポートフォリオ作成を考えていらっしゃる方の参考になれば幸いです! また、もし間違っている点等あれば、ご指摘いただけると嬉しいです。ありがとうございました!