27
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

RUNTEQAdvent Calendar 2021

Day 5

gemを使ってスクレイピングしてみた

Last updated at Posted at 2021-12-05

はじめに

本記事は、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に格納することができます!!


# 終わりに 最後までご一読いただきありがとうございました!  同じように、ポートフォリオ作成を考えていらっしゃる方の参考になれば幸いです! また、もし間違っている点等あれば、ご指摘いただけると嬉しいです。ありがとうございました!

参考URL

27
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?