【Rails】Mechanizeを利用して、サイトの情報を取得して表示する方法【スクレイピング】

# 1:概要

**railsでスクレイピングでhtml情報を取得し、欲しい要素を抽出して自サイトに表示させる方法**を紹介していきたいと思います。

スクレイピングとはWebやデータベースを広く探って「データを抽出する手法」のことです。
Mechanizeというgemを使った方法を紹介していきたいと思います。

今回は2種類ご紹介したいと思います
①Qiitaのトレンド記事の見出しを取得し、リンク付きで表示する方法
②[https://craftgawker.com/](https://craftgawker.com/)(手作り作品投稿サイト)から写真を取得し表示させる方法


### 完成図イメージ
①
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1373315/177e8a5c-85b2-f15e-3fb7-d349c37123d7.png)

②
![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1373315/27bc0a2e-9034-3142-c7c5-198e3f3f8e52.png)

#### 前提
コントローラー名はtweets,アクション名はhomeで記述しています。
```ruby:開発環境
ruby 2.7.3
rails 6.1.6
```

# 2:実装

## 2-1 一般的な実装方法

##### 1　gem「mechanize」をインストールする

まずはスクレイピングを簡単にしてくれるGem、mechanizeをインストールしていきます。

```ruby:Gemfile
gem 'mechanize'
```

```ruby:ターミナル
bundle install
```
公式はこちら

https://github.com/sparklemotion/mechanize



##### 2　Mechanizeクラスのインスタンスを生成し、ページから情報を取得してインスタンス変数に代入する

```ruby:tweets_controller.rb
    def home
        agent = Mechanize.new
        page = agent.get("URL名")
        @elements = page.search('要素名')
    end
```

``agent = Mechanize.new``
ここでまずMechanizeクラスをインスタンス化しています。
インスタンス化とは、Classの定義を元に新たな変数を作成することです。Mechanizeを使えるように定義し直した、と思ってもらえたら大丈夫です。
``page = agent.get("URL名")``
Mechanizeクラスのgetメソッドを使ってHTML情報を取得しています。
``@elements = page.search('要素名')``
上で取得したHTML情報から、searchメソッドを使って要素を取得し、インスタンス変数に代入しています。
要素名の部分には、クラス名やID名などが入ります。CSSのセレクターの取得と同じです。

##### 3　Viewページで表示する

```ruby:home.html.erb
<% @elements.each do |ele| %>
  <%= ele %>
<% end %>
```
``@elements``には戻り値が配列として入っているため、eachメソッドを使用して表示します。
inner_textメソッドや、get_attributeメソッドを利用することで、表示方法を選ぶことが出来ます。（後述）

## 2-2 Qiitaのトレンド記事の見出しを取得し、リンク付きで表示する

ここからは実際のWebページを取得していこうと思います。まずはQiitaのトレンド記事から。
gem「mechanize」は導入済みとします。

#### コントローラー記入

```ruby:tweets_controller.rb
    def home
        agent = Mechanize.new
        page_qiita = agent.get("https://qiita.com/")
        @qiita = page_qiita.search('.css-skov52 a')
    end
```

取得したい要素のセレクタ名を探すには、検証ツールを利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1373315/1462b14d-4c64-f6b3-9460-5028489cf6b2.png)

タイトル部分をみると、``css-skov52``というクラス名の中の`aタグ`だとわかるので、このように記入できます。

#### viewページ記入
```ruby:home.html.erb
<% @qiita.each do |qiita| %>
      <p><%=link_to(qiita.inner_text,qiita[:href])%></p>
<% end %>
```

これで表示することが出来ます。

#### 解説
each doの中にそのまま以下のように書くと
```ruby
<%= qiita %>
```
以下のように表示されてしまいます。
>`<a href="https://qiita.com/ken1041/items/49417edd50536a397318" class="css-11rvgoz">ワンランク上のSQLを書くためのポイント3つ</a>`

ここからテキスト情報、hrefの中のリンクを取得していきます。

##### inner_textメソッド
タグ内のテキストを取得することが出来ます。
```ruby:home.html.erb
<% @qiita.each do |qiita| %>
      <p><%= qiita.inner_text %></p>
<% end %>
```
表示↓
>`ワンランク上のSQLを書くためのポイント3つ`


##### get_attributeメソッド
タグの持つ属性値を取得する際に使用します。つまり、href属性の値を取得できます。

正式に書くと``qiita.get_attribute('href')``ですが、
省略して``qiita[:href]``と書くことが出来ます。

```ruby:home.html.erb
<% @qiita.each do |qiita| %>
      <p><%= qiita[:href] %></p>
<% end %>
```
表示↓
>`https://qiita.com/ken1041/items/49417edd50536a397318`

この2つのメソッドを利用して、`link_to`に代入すれば、タイトルとリンク付きで表示することが出来ます。


## 2-3 手作り作品投稿サイトから写真を取得し表示させる方法

次に、たくさんの写真が並んでいる以下のサイトから、写真情報を取得して、同じように写真で表示させる方法を紹介していきます。

https://craftgawker.com/　


#### コントローラー記入

```ruby:tweets_controller.rb
    def home
        agent = Mechanize.new
        page_craft = agent.get("https://craftgawker.com/")
        @img = page_craft.search('img')
    end
```
画像要素をもってくるため、要素名にはimgと記入します。

#### viewページ記入

```ruby:home.html.erb
<% @img.each do |i| %>
      <%= image_tag i[:src] ,size: '275x275'%>
<% end %>
```
そのままだと`<img src="//photo2.craftgawker.com/wp-content/uploads/craft/2022/12/480365.jpg" width="275" height="275" alt="Christmas`となるため、get_attributeメソッドを利用してsrc属性の値を取得し、image_tagに代入し、サイズを調整するときれいに表示されます。

ちなみにrailsのため`image_tag`を利用しておりますが、
```ruby
<img src="<%= i[:src]%>" width="275" height="275">
```
と書いても同じように表示できます。


# 3:おわりに
これを利用すれば色んなサイトから情報をとってきて表示することができます！ワクワクしますね😊
著作権などもあるので、そこには気をつけてください！

ちなみにコントローラーの記述において、`searchメソッド`では該当要素すべてを取得しますが、`atメソッド`を利用すると該当1件のみを取得することができます。

#### 参考記事
>[Railsでスクレイピング Mechanizeの基礎](https://qiita.com/Tamitchao/items/762e9838a38d6598d099)
[【Rails】mechanizeを使えばrailsスクレイピングが余裕な件](https://qiita.com/soehina/items/948f7f158a3a2d5be1dc)
[【rails】スクレイピングの実装方法](https://qiita.com/gogotakataka1234/items/ce4ba1832181e3e95c1f)