関連図
selenium/standalone-chrome
こういう感じで繋がっている場合、chromeにダウンロードさせても操作しているruby側にはファイルがダウンロードされるわけではない(ダウンロードされるにしてもselenium/standalone-chromeのコンテナ側に入る)。
解決方法
ボリュームを使う
例
envにパスを書いておくことで、docker-compose.yml、ruby側(ENV["CHROME_DOWNLOAD_DIR"]
)で同じ値が参照できる。
.env
CHROME_DOWNLOAD_DIR=/chrome/downloads
docker-compose.yml
# .envがあればdocker-composeはとりあえずそれを読んでymlに反映してくれる
services:
# /chrome/downloads
# を共通のボリュームにしておく
# ただそれだけだと権限の問題で書き込めないので、適当に777とかにしておく
# $ sudo chmod 777 chrome/downloads
chrome:
image: selenium/standalone-chrome
shm_size: 256m
volumes:
- .${CHROME_DOWNLOAD_DIR}:${CHROME_DOWNLOAD_DIR}
backend:
env_file:
- .env # ファイルを指定
build:
context: ./backend
working_dir: /app
volumes:
- ./backend:/app
- .${CHROME_DOWNLOAD_DIR}:/app${CHROME_DOWNLOAD_DIR}
headless chromeでファイルをダウンロードする方法
一般的なseleniumの使い方ならたしかにdownload_path=
が入っているが、リモートだとそもそもこのモジュールが入っていないので、下のように手を加える必要がある。
Selenium::WebDriver::Chrome::Driver | Selenium::WebDriver::Remote::Driver |
---|---|
include DriverExtensions::DownloadsFiles あり | なし |
...
...
driver = Capybara::Selenium::Driver.new(
app,
browser: :remote,
desired_capabilities: caps,
url: "http://#{DOCKER_CHROME_SELENIUM_HOST_NAME}:4444/wd/hub"
)
bridge = driver.browser.send(:bridge)
bridge.http.call(
:post,
"session/#{bridge.session_id}/chromium/send_command",
cmd: "Page.setDownloadBehavior",
params: { behavior: "allow", downloadPath: ENV["CHROME_DOWNLOAD_DIR"] }
)
後は/app/chrome/downloads
にファイルが入ってくるのがruby側でも見れる。