如何使用 Rails 应用程序在 Heroku 上正确 运行 Selenium Webdriver
How to run Selenium Webdriver correctly on Heroku with a Rails app
我正在使用 watir gem 在我的应用程序上实现一个非常基本的 scraper。它 运行 在本地非常好,但是当我在 heroku 上 运行 它时,它会触发此错误:Webdrivers::BrowserNotFound: Failed to find Chrome binary.
我在我的应用程序中添加了 google-chrome 和 chrome 驱动程序构建包,以告诉 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 网址:
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
知道如何解决这个问题吗?我在不同的网站上检查了很多类似的问题,但我没有找到任何东西。
我最近两天也在做同样的事情,正如你所说,我尝试了很多不同的事情。我终于成功了。
问题是 heroku 使用不同的路径下载 chrome 驱动程序。在 webdriver gem 的源代码中,我发现 webdriver 正在寻找 (linux, mac os, windows) 的默认系统路径,这就是为什么起作用的原因本地或 WD_CHROME_PATH 环境变量中定义的路径。要在 heroku 上设置路径,我们必须设置这个环境变量
"WD_CHROME_PATH": "/app/.apt/usr/bin/google-chrome"
必须 google-chrome 而不是 google-chrome-稳定,就像我们在示例中找到的那样。
也就是说,只是 运行 来自终端的这个:
heroku config:set WD_CHROME_PATH=/app/.apt/usr/bin/google-chrome
没有适合我的解决方案(Heroku-18 堆栈,使用 'https://github.com/heroku/heroku-buildpack-google-chrome.git' 和 'https://github.com/heroku/heroku-buildpack-chromedriver' 构建包)。
我尝试了各种解决方案,但终于找到了一种可以自己调试的防故障方法。
它涉及到一些资源:
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 为我设置的 shim 不起作用。事实上,即使你在 Heroku 上将上面的值设置为不同的值,buildpacks 会重置它们,所以你会丢失新的垫片(参见此处:https://github.com/heroku/heroku-buildpack-google-chrome/blob/master/bin/compile)所以我制作了新的垫片:
$ 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
希望这对其他人有帮助。
我曾尝试用不同的方法解决此问题一段时间,但 none 的方法奏效了。然后我检查了 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 是如何相互作用的。一些人还写道,您可以留下另一个构建包。但这至少现在有效:-D.
我正在使用 watir gem 在我的应用程序上实现一个非常基本的 scraper。它 运行 在本地非常好,但是当我在 heroku 上 运行 它时,它会触发此错误:Webdrivers::BrowserNotFound: Failed to find Chrome binary.
我在我的应用程序中添加了 google-chrome 和 chrome 驱动程序构建包,以告诉 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 网址:
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
知道如何解决这个问题吗?我在不同的网站上检查了很多类似的问题,但我没有找到任何东西。
我最近两天也在做同样的事情,正如你所说,我尝试了很多不同的事情。我终于成功了。
问题是 heroku 使用不同的路径下载 chrome 驱动程序。在 webdriver gem 的源代码中,我发现 webdriver 正在寻找 (linux, mac os, windows) 的默认系统路径,这就是为什么起作用的原因本地或 WD_CHROME_PATH 环境变量中定义的路径。要在 heroku 上设置路径,我们必须设置这个环境变量
"WD_CHROME_PATH": "/app/.apt/usr/bin/google-chrome"
必须 google-chrome 而不是 google-chrome-稳定,就像我们在示例中找到的那样。
也就是说,只是 运行 来自终端的这个:
heroku config:set WD_CHROME_PATH=/app/.apt/usr/bin/google-chrome
没有适合我的解决方案(Heroku-18 堆栈,使用 'https://github.com/heroku/heroku-buildpack-google-chrome.git' 和 'https://github.com/heroku/heroku-buildpack-chromedriver' 构建包)。
我尝试了各种解决方案,但终于找到了一种可以自己调试的防故障方法。
它涉及到一些资源: 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 为我设置的 shim 不起作用。事实上,即使你在 Heroku 上将上面的值设置为不同的值,buildpacks 会重置它们,所以你会丢失新的垫片(参见此处:https://github.com/heroku/heroku-buildpack-google-chrome/blob/master/bin/compile)所以我制作了新的垫片:
$ 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
希望这对其他人有帮助。
我曾尝试用不同的方法解决此问题一段时间,但 none 的方法奏效了。然后我检查了 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 是如何相互作用的。一些人还写道,您可以留下另一个构建包。但这至少现在有效:-D.