HippoBlog
Web開発に関する備忘録や
日々の雑記ブログ
  • #Ruby on Rails
  • 2020年2月25日
ENTRY TITLE

[rails] OG画像URLスクレイピング・ないときはキャプチャ取る(の作業ログ)

TEXT BY @hippohack@hippohack
TEXT BY @hippohack@hippohack
  • このエントリーをはてなブックマークに追加

OG画像URLスクレイピング

Nokogiriでスクレイピング。

og:image だったり、og:image:url だったりするので2重チェックしてる。

で、どっちもないときはキャプチャを取る。

doc = Nokogiri::HTML(open(url))

og_image_url = doc.xpath('/html/head/meta[@property="og:image"]/@content').to_s
og_image_url = doc.xpath('/html/head/meta[@property="og:image:url"]/@content').to_s if og_image_url.blank?

キャプチャを取る

Watir を使う。

[Gemfile]

gem 'watir'
gem 'headless'
gem 'webdrivers'
gem 'faker'

bundle install する。

Headlessでエラー。

Headless::Exception (Xvfb not found on your system)

XvfbはLinuxのパッケージらしい。

dockerfileを編集していれる。

[dockerfile]

︙
RUN apt-get update && apt-get install -y build-essential libpq-dev tmux xvfb
︙

Watir::Browser.new :chrome, headless: true でエラー。

Webdrivers::BrowserNotFound (Failed to find Chrome binary.)

Selenium::WebDriver::Error::UnknownError (unknown error: Chrome failed to start: exited abnormally)
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

chromeのバイナリ入れないといけないみたい。

[dockerfile]

︙
# install google-chrome-stable
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -RUN echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.listRUN apt-get update && apt-get install -y google-chrome-stable

RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.zip && unzip chromedriver_linux64.zipRUN mv chromedriver /usr/bin/chromedriver && chown root:root /usr/bin/chromedriver && chmod +x /usr/bin/chromedriver
︙

では、解決せず。

webdriverの使い方ミスってたかも。

いやー、でも解決せず。

一旦リセット。Watirを捨てる。

純粋にselenium-webdriverでいける?

また、Webdrivers::BrowserNotFound (Failed to find Chrome binary.)

↑のdockerfileの修正でgoogle-chrome-stableもっかい入れた。

# which google-chrome
/usr/bin/google-chrome

結果おなじエラー。。

Selenium::WebDriver::Error::UnknownError (unknown error: Chrome failed to start: exited abnormally)
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.)

パスの設定覗いてみる

Selenium::WebDriver::Chrome.driver_path
2019-08-29 04:37:05 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path instead.
=> #<Proc:0x000055e90596c0a0@/usr/local/bundle/gems/webdrivers-4.1.2/lib/webdrivers/chromedriver.rb:119>

あんじゃん。んー。。。

chromedriver入れてみる。

だめだ、とりあえずハードコーディング。

[dockerfile]

ENV CHROME_DRIVER_VERSION 76.0.3809.126

# ENV CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`
RUN wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip

RUN unzip chromedriver_linux64.zip && rm chromedriver_linux64.zip

RUN mv chromedriver /usr/local/bin/

確認。

# which chromedriver
/usr/local/bin/chromedriver

[module]

def get_screenshot(url)
  # configure the driver to run in headless mode
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument('--headless')
  options.add_argument('--no-sandbox')
  options.add_argument('--disable-gpu')
  driver = Selenium::WebDriver.for :chrome, options: options
  driver.navigate.to url
  # resize the window and take a screenshot
  driver.manage.window.resize_to(372, 248)
  src = 'data:image/png;base64,' + driver.screenshot_as(:base64)
  # driver.save_screenshot "screenshot.png"
  driver.quit
  src
end

で、いけたー。

けど、 Net::ReadTimeout with #<TCPSocket:(closed)> とか出る。 → 例外処理で回避。

エラー: chrome not reachable

WebDriverException: Message: chrome not reachable

driver.quit で閉じてないことによってリソース負荷の問題ぽかった。

ここのコメントの「タブが開きすぎ」ってのでパッと来た。

画像のサイズが大きすぎるので調整する

︙
# resize the window and take a screenshot
driver.manage.window.resize_to(1280, 800)src = driver.screenshot_as(:base64)
driver.quit
image = Magick::Image.from_blob(Base64.decode64(src)).firstnew_src = image.change_geometry!('372x248') do |cols, rows, img|
    img.resize(cols, rows)
end
return 'data:image/png;base64,' + Base64.encode64(new_src.to_blob)
  • でかいサイズでキャプチャした画像をRMagickでリサイズする。
  • Base64に再エンコードして返す。

参考サイト


最後までお読みいただき、ありがとうございました。

ご意見などありましたら@hippohackへDMをお願いいたします。

  • このエントリーをはてなブックマークに追加