2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Railsでスクレイピングの環境構築してみた【Rails+Selenium+Heroku】

Posted at

はじめに

Rails環境かつ、Heorku環境でもスクレイピングをするための環境構築の備忘録。

ローカル環境でとりあえず動かすことはできても、連続してスクレイピングできなかったり、Heorku環境でスクレイピングができない問題がありました。

最終的にHeorku環境で動作させることができたので、参考になれば幸いです。

やりたいこと

  • Heroku環境でSeleniumのスクレイピングが機能するか確認するためのJobを作成すること

今回はwww.google.comにアクセスして、そのページのタイトルを返すものを作ります。
Googleというタイトルをスクレイピングするだけです。
(あくまで動作確認をするだけに徹しています)

環境構築

Docker環境

元々DockerfileでChromeのインストールとChromeDriverをインストールしていたのですが、連続してスクレイピングできなかったり、Heroku環境で動作しなかったのでchromeのdocker imageを使用します。

この他、appやredis, sidekiqは適宜追加してください。
今回はJobにしてバックグラウンド実行を想定しております。

compose.yml
services:
  chrome:
    image: selenium/standalone-chrome:latest
    ports:
      - 4444:4444
      - 7900:7900
    shm_size: "2gb"
    tty: true

Service

Jobから呼ぶためのスクレイピングのサービスクラスを作成します。

selenium_health_check_service.rb
class SeleniumHealthCheckService < ApplicationService
  require 'selenium-webdriver'

  attr_reader :driver

  def call
    @driver ||= setup_driver

    run
  end

  private

  def run
    driver.get('https://www.google.com')
    logger.info "Page title: #{driver.title}"
  ensure
    sleep 3
    driver.quit
  end

  def setup_driver
    options = build_chrome_options
    setup_webdriver(options)
  end

  def build_chrome_options
    options = Selenium::WebDriver::Chrome::Options.new
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--window-size=1280x800')
    options.add_argument("--user-agent=#{user_agent}")
    options
  end

  def user_agent
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'
  end

  def setup_webdriver(options)
    if Rails.env.production?
      setup_production_driver(options)
    else
      setup_development_driver(options)
    end
  end

  def setup_production_driver(options)
    chrome_bin_path = ENV.fetch('GOOGLE_CHROME_BIN', nil)
    chromedriver_path = ENV.fetch('CHROMEDRIVER_PATH', nil)
    options.binary = chrome_bin_path if chrome_bin_path
    Selenium::WebDriver::Chrome::Service.driver_path = chromedriver_path if chromedriver_path
    Selenium::WebDriver.for :chrome, options: options
  end

  def setup_development_driver(options)
    Selenium::WebDriver.for :remote, url: 'http://chrome:4444/wd/hub', options: options
  end
end

ポイントはlocal環境とHeroku環境でdriverの作成を分岐させています。
こうすることで、Heroku環境でもスムーズに環境構築することができます。
詳しくは後にあります。

また、動作確認でデバックするときにlogger.infoを仕込んでおくとわかりやすいです。

Job

今回は検証用なのでスクレイピングがすぐにできますが、本来は色々なページを行き来したり、データを取得するので時間がかかります。
そのためバックグラウンドで動作するようにJobにしておきます。
想定する環境によってTaskにすることもあります。

selenium_health_check_job.rb
class SeleniumHealthCheckJob < ApplicationJob
  queue_as :default
  sidekiq_options retry: false

  def perform
    SeleniumHealthCheckService.call
  end
end

このようにしておけばコンソールで実行できます。

SeleniumHealthCheckJob.perform_later

=> Page title: Google

Heroku設定

Herokuでは大きく2つの設定をすればOKです。
これだけでHeroku環境の設定ができるのですごくシンプルです。

①Buildpacksの追加

以下の2つを追加します

  • https://github.com/heroku/heroku-buildpack-chromedriver.git
  • https://github.com/heroku/heroku-buildpack-google-chrome.git

②環境変数の追加

以下の2つを追加します

  • CHROMEDRIVER_PATH: /app/.chromedriver/bin/chromedriver
  • GOOGLE_CHROME_BIN: /app/.apt/usr/bin/google-chrome

おわりに

途中手こずりましたが想定の1/4の時間で進めることができました。
参考にさせていただいたドキュメントの著者の方々に感謝しております。

参考文献

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?