概要
- selenium-webdriverを使ってchromiumのheadlessモードで表示したwebページからテキストを抽出する
- CSS or tagで抽出する場所を指定し、テキスト出力できます。
- Excelに優しい☺️タブ区切りで出力もできます。
環境
使い方
後述のコードを web_capture.rb
としてrailsの適当なフォルダ( lib/web_capture.rb
とか)にいれて、 rails c
などで下記のようにうごかします。(urlは適当なやつに書き換えて下さい。)
Rails.logger 等のRails固有の記述を削除すればrailsなくてもうごきます。その場合は適宜修正お願いします。
rails c
> web_capture = WebCapture.new(url: 'https://xxxxyyyyzzzzexample.com')
> web_capture.extract # bodyタグ内のテキストを改行区切りで出力
> web_capture.extract(tag_name: 'li', format: :tab_text) # liタグの全テキストをタブ区切りで出力
> web_capture.extract(css: 'div.menu') # cssセレクタdiv.menu内のテキストを改行区切りで出力
> web_capture.extract(tag_name: 'li', format: :array) # liタグの全テキストをarrayとして出力
コード
ほとんどこちらのscreenshot_capture.rbと同じです。差分のみ解説します。
web_capture.rb
# frozen_string_literal: true
require 'selenium-webdriver'
require 'httpclient'
class WebCapture
include ActiveModel::Model
include ActiveModel::Attributes
attribute :url, :string
CONVERTER = {
array: lambda do |els|
els.map(&:text)
end,
text: lambda do |els|
ary = els.map(&:text)
ary.join(' ')
end,
tab_text: lambda do |els|
ary = els.map(&:text)
ary.join("\t")
end
}.freeze
def initialize(args = {})
super(args)
@client = HTTPClient.new
end
def extract(tag_name: 'body', format: :text, css: '')
return unless valid?
begin
driver = Selenium::WebDriver.for :chrome, options: headless_chrome_options
driver.navigate.to url
sleep(1)
elements = if css.present?
driver.find_elements(:css, css)
elsif tag_name.present?
driver.find_elements(:tag_name, tag_name)
end
output = CONVERTER[format].call(elements)
rescue => e
Rails.logger.error e
end
driver.close
driver.quit
output
end
def valid?
return false unless url
return false unless successful?
true
end
def successful?
@content ||= @client.get(url)
HTTP::Status.successful?(@content.status)
rescue StandardError => e
Rails.logger.error e
end
def headless_chrome_options
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')
options.add_argument('--hide-scrollbars')
options.binary = '/app/.apt/usr/bin/google-chrome' if heroku?
options
end
def heroku?
Rails.env.production?
end
end
解説
seliniumでcssセレクタもしくはタグ名指定で抽出するところは、下記のコードです。
引数でcssが指定されていたら、そちらを優先します。
web_capture.rb
elements = if css.present?
driver.find_elements(:css, css)
elsif tag_name.present?
driver.find_elements(:tag_name, tag_name)
end
- タブ区切り等の出力はここでやっています。
web_capture.rb
CONVERTER = {
array: lambda do |els|
els.map(&:text)
end,
text: lambda do |els|
ary = els.map(&:text)
ary.join(' ')
end,
tab_text: lambda do |els|
ary = els.map(&:text)
ary.join("\t")
end
}.freeze
以上。