带有Selenium的Chromedriver远程调试端口

Jul*_*lie 3 ruby selenium selenium-chromedriver google-chrome-headless

我正在使用Capybara Selenium运行无头Chrome,这很好用,但我无法弄清楚如何使用远程调试。当我添加--remote-debugging-port=4444--remote-debugging-port=9222或时--remote-debugging-port=9521,Selenium不再连接到浏览器以运行测试。

如何使远程调试工作?这是我的代码供参考:

Capybara.register_driver :selenium do |app|
  # from https://github.com/SeleniumHQ/selenium/issues/3738
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: {browser: 'ALL'})
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument '--disable-infobars' # hide info bar about chrome automating test
  # if we don't use this flag, every selenium test will die with the error:
  # "unknown error: Chrome failed to start: exited abnormally"
  options.add_argument '--no-sandbox'
  # BREAKS THINGS if uncommented
  # options.add_argument '--remote-debugging-port=4444'
  options.add_argument '--headless'
  options.add_argument '--window-size=1600,2400'
  options.add_preference('profile.default_content_settings.popups', 0)
  options.add_preference('download.default_directory', DownloadHelpers::PATH.to_s)
  Capybara::Selenium::Driver.new(
    app,
    clear_local_storage: true,
    clear_session_storage: true,
    browser: :chrome,
    options: options,
    desired_capabilities: capabilities,
  )
end
Run Code Online (Sandbox Code Playgroud)

rog*_*ito 5

chrome 67和chromedriver 2.39开始,chromedriver现在可以正确使用您指定的端口--remote-debugging-port。这从上面的回答中消除了很多麻烦。我现在采取的步骤(对于需要使用chrome_remote配置下载设置的用)适用于以下情况:

它利用nodejs库crmux-允许多个客户端同时连接到chrome的远程调试端口。

  1. 首先安装Node.js: Node.js v9.7.0正常运行
  2. 通过运行安装crmux npm install crmux -g
  3. 之前您开始chromedriver( Capybara::Selenium::Driver.new),您需要spawn一个单独的线程会火起来crmux,这将让你和chromedriver通过港口铬本身传达的水豚(4444)中规定:

    crmux --port=4444 --listen=4444

  4. 您可能希望在主脚本/线程中sleep 3spawn命令后添加一个,以便在继续测试启动之前给crmux启动时间。

然后,您可以使用chrome_remote(例如)在capybara进行操作时使用端口4444访问chrome 。

  • 我终于弄清楚了:您可以使用`browser_options.args <<“ --remote-debugging-port = 9222”`(默认值为0,将Chrome的--remote-debugging-port)设置为所需的值。它选择随机端口)。(不管是否使用crmux,都可以这样设置端口。)然后,您可以设置`crmux`以侦听*不同*端口,如9223(默认),但是必须将`--port 9222`传递给*与Chrome浏览器的“ --remote-debugging-port”端口相同,因为它是代理访问*的端口。现在,您可以从chrome_remote,其他浏览器等连接到crmux的* listen *端口。 (2认同)
  • 如果您有兴趣,我编写了一个 gem 来帮助将 crmux 和 chrome_remote 与 Capybara 集成,类似于您的操作方式:https://github.com/TylerRick/capybara-chrome_dev_tools。如果您有任何建议或改进,请告诉我或贡献。我还添加了 https://github.com/TylerRick/capybara-chrome_response_headers,它使用 `chrome_remote` 在你的测试中为你提供 `response_headers` 和 `status_code`。 (2认同)

rog*_*ito 0


更新:如果使用 Chrome 67/chromedriver 2.39 之后的版本,我上面的替代答案提供了一个更简单的解决方案


这里的核心问题是 Chromedriver 还使用远程调试端口连接与 Chrome 进行通信。这使用了 websocket 协议,该协议仅支持一次连接一个客户端。通常,当chromedriver启动chromedriver进程时,它会选择一个随机的空闲TCP端口号并使用它来访问远程调试端口。但是,如果您指定--remote-debuggging-port=9222,Chrome 将使用您请求的调试端口打开,但 chromedriver 将默默地继续尝试使用此随机端口号打开连接。

我最终得到的解决方案很大程度上受到了chromedriver issues 中第 20 条评论的启发。它需要相当多的代码才能使其工作,但工作稳定。它使用了一个nodejs库crmux——它允许多个客户端同时连接到chrome的远程调试端口。

  1. 首先安装nodejs: Nodejs v9.7.0工作正常
  2. 通过运行安装 crmuxnpm install crmux -g
  3. 在启动 chromedriver( )之前Capybara::Selenium::Driver.new,您需要spawn一个单独的线程来执行一些操作:查找 chromedriver 尝试用于连接到 chrome 的远程调试端口,然后使用它来启动crmux。一旦发生这种情况,水豚等就会正常工作。
  4. 我的单独线程运行一个 ruby​​ 脚本,该脚本首先重复执行 netstat 命令,直到找到 chromedriver 的相关条目(TCP 状态为 SYN_SENT)。当 chrome 启动并运行时,这个单独的线程必须继续在后台运行

其代码是:

$chrdrv_wait_timeout = 60
$chrdrv_exe = "chromedriver.exe"

def get_netstat_output
  stdout = `netstat -a -b -n`
  stat_lines = stdout.split("\n")
  stat_lines
end

def try_get_requested_port
  socket_state = "SYN_SENT" # i.e. sent with no reply
  statout = get_netstat_output
  n = statout.length
  i = 0
  loop do
    i += 1
    # find lines relating to chromedriver
    exe_match = /^ +\[#{$chrdrv_exe}\]$/.match statout[i]
    if exe_match != nil
      # check preceeding lines which should contain port info
      port_match = /TCP.*:([0-9]+)\W+#{socket_state}/.match statout[i-1]
      if port_match != nil
        return port_match[1].to_i
      end
    end
    break unless i < n
  end
  return nil
end

def get_tcp_port_requested_by_chromedriver
  i = 1
  loop do
    puts "Waiting for #{$chrdrv_exe}: #{i}"
    port = try_get_requested_port
    if port != nil
      return port
    end
    break unless i < $chrdrv_wait_timeout
    sleep 1
    i += 1
  end
  raise Exception, "Failed to get TCP port requested by #{$chrdrv_exe} (gave up after #{$chrdrv_wait_timeout} seconds)"
end
Run Code Online (Sandbox Code Playgroud)

(我在 Windows 中工作:对于 Mac/Linux,netstat 语法/输出可能不同,因此代码需要调整;关键是你需要它输出每个连接条目的可执行所有者- 并解析与chromedriver 获取有问题的端口)。

  1. 一旦找到随机端口(我将使用12225作为示例),后台 ruby​​ 脚本就可以执行 crmux 进程,该进程将通过在 Capybara 中指定的端口(4444)将 chromedriver 与 chrome 本身重新组合:

    crmux --port=4444 --listen=12225

  2. 最后,这个单独的脚本将发现的侦听端口保存到文本文件中。这允许运行水豚的主脚本/线程知道它可以通过从该文件读取端口来访问 chrome(通过 crmux 的多路复用连接)的端口号。因此,您可以使用chrome_remote来使用端口12225访问 chrome ,例如,当水豚正在执行其操作时。