【问题标题】:How to run Selenium Webdriver correctly on Heroku with a Rails app如何使用 Rails 应用程序在 Heroku 上正确运行 Selenium Webdriver
【发布时间】:2019-08-22 12:43:49
【问题描述】:

我正在使用 watir gem 在我的应用上实现一个非常基本的 scraper。它在本地运行得很好,但是当我在 heroku 上运行它时,它会触发这个错误:Webdrivers::BrowserNotFound: Failed to find Chrome binary.

我将 google-chrome 和 chromedriver buildpacks 添加到我的应用程序中,以告诉 Selenium 在 Heroku 上的哪里可以找到 Chrome,但它仍然无法正常工作。此外,当我打印选项时,二进制文件似乎设置正确:

#<Selenium::WebDriver::Chrome::Options:0x0000558bdf7ecc30 @args=#<Set: {"--user-data-dir=/app/tmp/chrome", "--no-sandbox", "--window-size=1200x600", "--headless", "--disable-gpu"}>, @binary="/app/.apt/usr/bin/google-chrome-stable", @prefs={}, @extensions=[], @options={}, @emulation={}, @encoded_extensions=[]>

这是我的应用 Buildpack URL:

1. heroku/ruby
2. heroku/google-chrome
3. heroku/chromedriver

这是我的代码:

def new_browser(downloads: false)

  options = Selenium::WebDriver::Chrome::Options.new

  chrome_dir = File.join Dir.pwd, %w(tmp chrome)
  FileUtils.mkdir_p chrome_dir
  user_data_dir = "--user-data-dir=#{chrome_dir}"
  options.add_argument user_data_dir

  if chrome_bin = ENV["GOOGLE_CHROME_SHIM"]
    options.add_argument "--no-sandbox"
    options.binary = chrome_bin
  end

  options.add_argument "--window-size=1200x600"
  options.add_argument "--headless"
  options.add_argument "--disable-gpu"

  browser = Watir::Browser.new :chrome, options: options

  if downloads
    downloads_dir = File.join Dir.pwd, %w(tmp downloads)
    FileUtils.mkdir_p downloads_dir

    bridge = browser.driver.send :bridge
    path = "/session/#{bridge.session_id}/chromium/send_command"
    params = { behavior: "allow", downloadPath: downloads_dir }
    bridge.http.call(:post, path, cmd: "Page.setDownloadBehavior",
                                  params: params)
  end
  browser
end

知道如何解决这个问题吗?我在不同的网站上检查了许多类似的问题,但我没有找到任何东西。

【问题讨论】:

    标签: ruby-on-rails heroku selenium-chromedriver watir


    【解决方案1】:

    前两天我也在做同样的事情,正如你所说,我尝试了很多不同的事情。我终于成功了。

    问题是heroku使用不同的路径下载chromedriver。在 webdriver gem 的源代码中,我发现 webdriver 正在寻找(linux、mac os、windows)的默认系统路径,这就是为什么在本地工作或在 WD_CHROME_PATH 环境变量中定义的路径的原因。要在 heroku 上设置路径,我们必须设置这个环境变量

    "WD_CHROME_PATH": "/app/.apt/usr/bin/google-chrome"
    

    必须是 google-chrome 而不是 google-chrome-stable,就像我们可以在示例中找到的那样。

    也就是说,只需从终端运行:

    heroku config:set WD_CHROME_PATH=/app/.apt/usr/bin/google-chrome
    

    【讨论】:

    • 真的非常感谢!我有完全相同的问题!花了一整天的时间在上面工作。我考虑写一篇关于在 heroku 上使用 selenium 的分步指南的文章,因为这真的很痛苦。
    • 您能分享更多我们的配置吗?即使使用 WD_CHROME_PATH,我也无法使其正常工作。
    • "test": { "env": { "WD_CHROME_PATH": "/app/.apt/usr/bin/google-chrome" }, "buildpacks": [ // ... { “url”:“github.com/heroku/heroku-buildpack-chromedriver.git”},{“url”:“github.com/heroku/heroku-buildpack-google-chrome.git”}],“插件”:[“heroku-postgresql:in-dyno”,“heroku-redis:in-dyno”], "scripts": { // 测试设置,// 运行测试 } }
    • @thomas 你写这篇文章了吗?
    • @wachichornia 不,不幸的是没有。但最近(我认为是 1 或 2 周前)有一个更新(我不确定是因为 google chrome、chromedriver 还是 heroku),我的设置又坏了。很多同事都有同样的问题。现在整个设置又被破坏了。如果您找到解决方案,请告诉我。如果我也发现问题,我会在这里发布解决方案。
    【解决方案2】:

    没有适合我的解决方案(Heroku-18 堆栈,带有 'https://github.com/heroku/heroku-buildpack-google-chrome.git' 和 'https://github.com/heroku/heroku- buildpack-chromedriver' buildpacks)。

    我尝试了各种解决方案,但最终找到了一种自己调试的防故障方法。

    它涉及到几个资源: https://www.simon-neutert.de/2018/watir-chrome-heroku/ 和 尤其是https://github.com/jormon/minimal-chrome-on-heroku/blob/master/runner.thor

    检查您的实际二进制文件和驱动程序在 Heroku 上的位置:

    $ heroku run bash
    ~ $ which chromedriver
    /app/.chromedriver/bin/chromedriver
    ~ $ which google-chrome
    /app/.apt/usr/bin/google-chrome
    

    buildpacks 为我设置的垫片不起作用。事实上,即使您在 Heroku 上将上述值设置为不同的值,构建包也会重置它们,因此您会丢失新的 shim(参见此处:https://github.com/heroku/heroku-buildpack-google-chrome/blob/master/bin/compile)所以我制作了新的 shim:

    $ heroku config:set GOOGLE_CHROME_REAL=/app/.apt/usr/bin/google-chrome
    $ heroku config:set CHROME_DRIVER_REAL=/app/.chromedriver/bin/chromedriver
    

    然后,我修改了浏览器初始化程序(来自:https://github.com/jormon/minimal-chrome-on-heroku/blob/master/runner.thor):

    def new_browser(downloads: false)
        require 'watir'
        require 'webdrivers'
        options = Selenium::WebDriver::Chrome::Options.new
    
        # make a directory for chrome if it doesn't already exist
        chrome_dir = File.join Dir.pwd, %w(tmp chrome)
        FileUtils.mkdir_p chrome_dir
        user_data_dir = "--user-data-dir=#{chrome_dir}"
        # add the option for user-data-dir
        options.add_argument user_data_dir
    
        # let Selenium know where to look for chrome if we have a hint from
        # heroku. chromedriver-helper & chrome seem to work out of the box on osx,
        # but not on heroku.
        if chrome_bin = ENV["GOOGLE_CHROME_REAL"]
            Selenium::WebDriver::Chrome.path = chrome_bin
        end
        if chrome_driver = ENV["CHROME_DRIVER_REAL"]
            Selenium::WebDriver::Chrome.driver_path = chrome_driver
        end
    
        # headless!
        options.add_argument "--window-size=1200x600"
        options.add_argument "--headless"
        options.add_argument "--disable-gpu"
    
        # make the browser
        browser = Watir::Browser.new :chrome, options: options
    
        # setup downloading options
        if downloads
          # make download storage directory
          downloads_dir = File.join Dir.pwd, %w(tmp downloads)
          FileUtils.mkdir_p downloads_dir
    
          # tell the bridge to use downloads
          bridge = browser.driver.send :bridge
          path = "/session/#{bridge.session_id}/chromium/send_command"
          params = { behavior: "allow", downloadPath: downloads_dir }
          bridge.http.call(:post, path, cmd: "Page.setDownloadBehavior",
                                        params: params)
        end
        browser
    end
    

    希望这对其他人有所帮助。

    【讨论】:

      【解决方案3】:

      我已经尝试使用不同的方法解决这个问题一段时间,但没有一个奏效。然后我检查了 webdrivers 源代码,发现您需要设置“WD_CHROME_PATH”环境变量才能使其工作。只是在这里附上我的完整设置。这花了我几个小时来调试和修复。

      spec_helper.rb

      require 'webdrivers'
      require 'capybara/rspec'
      
       # Heroku build packs need to put the chromedriver binary in a non-standard location specified by GOOGLE_CHROME_SHIM
       chrome_bin = ENV.fetch('GOOGLE_CHROME_SHIM', nil)
      
       options = {}
       options[:args] = ['headless', 'disable-gpu', 'window-size=1280,1024']
       options[:binary] = chrome_bin if chrome_bin
      
       Capybara.register_driver :headless_chrome do |app|
         Capybara::Selenium::Driver.new(app,
            browser: :chrome,
            options: Selenium::WebDriver::Chrome::Options.new(options)
          )
       end
      
       Capybara.javascript_driver = :headless_chrome
      

      宝石文件

      group :test do
        gem 'capybara'
        gem 'timecop'
        gem 'selenium-webdriver'
        gem 'webdrivers'
      end
      

      app.json

      {
        "name": "evocal",
        "repository": "https://github.com/zeitdev/evocal",
        "environments": {
          "test": {
            "addons":[
              "heroku-postgresql:in-dyno"
            ],
            "scripts": {
              "test-setup": "bundle exec rake db:seed",
              "test": "bundle exec rspec"
            },
            "buildpacks": [
              { "url": "heroku/ruby" },
              { "url": "https://github.com/heroku/heroku-buildpack-google-chrome" },
              { "url": "https://github.com/heroku/heroku-buildpack-chromedriver" },
              { "url": "heroku/nodejs" }
            ],
            "env": {
              "WD_CHROME_PATH": "/app/.apt/opt/google/chrome/chrome"
            }
          }
        }
      }
      

      我还没有完全理解 selenium、webdriver 和 gem 是如何相互作用的。有些人还写道,您可以放弃另一个 buildpack。但这至少目前有效:-D。

      【讨论】:

        猜你喜欢
        • 2012-12-01
        • 2017-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多