LoginSignup
3
3

More than 5 years have passed since last update.

[Rails] Selenium-webdriverでWebページのテキストを抽出する

Posted at

概要

  • 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

以上。

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