学習メモ

Ruby on Railsを中心にプログラミングやWEB技術を勉強しています。

ogpの情報を取得したい

nokogiriを利用したスクレイピング

アプリ制作に伴いogpの情報を自分のアプリ内で表示したいと思って調べました。
今回はurlを登録するとそのサイトのmetaタグから情報を取得して、データベースに保存するサンプルを作ります。

環境

  • ruby 2.6.6
  • rails 6.0.3
  • nokogiri 1.11.3
  • image_processing 1.12.11

導入

rails newの雛形作成直後を例に進めます。
hogeモデルとコントローラーを作ります。後からカラムを追加するのは余計なフォームができるのを避けるためです。

bundle install

rails g scaffold hoge url:string

rails g migration AddColumnToHoges title:string description:string

rails db:migrate

バリデーション等考慮すべきですが、今回は動作確認が目的なので省略。 これでURLを登録するフォームができました。
次にスクレイピング部分を実装します。わかりやすいようにいったんcreateアクション内で全て行います。

def create
  require 'open-uri'
  @hoge = Hoge.new(hoge_params)

  html = URI.open(@hoge.url).read
  doc = Nokogiri::HTML.parse(html)

  @hoge.title = doc.css('meta[property="og:title"] @content').to_s
  @hoge.description = doc.css('meta[property="og:description"] @content').to_s

  以下略

require 'open-uri'rubyのライブラリを読み込み。URI.openによりファイルを開くような感覚でhttp/ftpにアクセスできます。

openメソッドでサイトにアクセスし、readメソッドでデータを読込んで内容を変数に保存。

Nokogiri::HTML.parse(html) により取得したデータをパースする。その後cssメソッドで取得したい情報を選択して各属性に保存。 参考記事ではrailsを使用しないrubyファイルだったのでnokogiriのrequireをしていましたが、railsの場合はインストールされているのでなくても使用できました。
https://zenn.dev/arao99/articles/40cde7168279f899d0f5

データ検索条件についてはcssセレクタxpathを使用する方法があり、検索するメソッドもたくさんありました。
https://nokogiri.org/rdoc/Nokogiri/XML/Searchable.html#css-instance_method

ogpについては記載方法が決まっているようなので上記のような方法だと設定されている場合は取得できるはず。
https://ogp.me/

viewに表示部分を追加します。

<p><%= @hoge.title %></p>
<p><%= @hoge.description %></p>

続いて画像の保存部分です。 active storageを使用して保存してみます。最初にインストールを行います。

rails active_storage:install

これにより必要なテーブルを作成するためのマイグレーションファイルが生成されます。 保存先はデフォルトではこんな感じです。 config/strage.yml

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>


local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

config/environments/development.rbに設定の読み込みを追加します。

config.active_storage.service = :local

画像の加工をしたいのでGemfileの中のimage_processingのコメントを解除してbundle installします。

gem 'image_processing', '~> 1.2'

マイグレーションとgemのインストールを行ったのでサーバー起動中の場合は再起動します。

class Hoge < ApplicationRecord
  has_one_attached :image
end

モデルに関連付けを追加。 createアクションに処理を追加します。

image = doc.css('meta[property="og:image"] @content').to_s
@hoge.image.attach(io: URI.open(image), filename: image)

viewに表示を追加

<div class="">
  <%= image_tag @hoge.image.variant(resize: "200x200") %>
</div>

active storageの使用方法はrailsガイドの記載を参考にしました。 https://railsguides.jp/active_storage_overview.html

これで取得した画像を保存、表示することができました。

URI.openのアクセスについては503エラーとなるサイトがありました。その場合はユーザーエージェントに関する記述を追加すれば同様の処理ができましたが、あまりわかっていないので割愛します。

また、スクリプトによる連続アクセスは攻撃とみなされトラブルになることもあるそうなので気をつけて使用する必要があるとのことでした。

あとは取得した情報を元にCSSを設定すると好みの見た目でリンクを表示できそうです。