はじめに
Rails環境かつ、Heorku環境でもスクレイピングをするための環境構築の備忘録。
ローカル環境でとりあえず動かすことはできても、連続してスクレイピングできなかったり、Heorku環境でスクレイピングができない問題がありました。
最終的にHeorku環境で動作させることができたので、参考になれば幸いです。
やりたいこと
- Heroku環境でSeleniumのスクレイピングが機能するか確認するためのJobを作成すること
今回はwww.google.comにアクセスして、そのページのタイトルを返すものを作ります。
Googleというタイトルをスクレイピングするだけです。
(あくまで動作確認をするだけに徹しています)
環境構築
Docker環境
元々DockerfileでChromeのインストールとChromeDriverをインストールしていたのですが、連続してスクレイピングできなかったり、Heroku環境で動作しなかったのでchromeのdocker imageを使用します。
この他、appやredis, sidekiqは適宜追加してください。
今回はJobにしてバックグラウンド実行を想定しております。
services:
chrome:
image: selenium/standalone-chrome:latest
ports:
- 4444:4444
- 7900:7900
shm_size: "2gb"
tty: true
Service
Jobから呼ぶためのスクレイピングのサービスクラスを作成します。
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にすることもあります。
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の時間で進めることができました。
参考にさせていただいたドキュメントの著者の方々に感謝しております。