Selenium Docker

docker-composeで公式サンプルに一部追記

appサービスとしてPython実行のシェルのためのContainerを用意。
tty: trueを忘れずに。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# To execute this docker-compose yml file use `docker-compose -f <file_name> up`
# Add the `-d` flag at the end for detached execution
version: "3"
services:
chrome:
image: selenium/standalone-chrome
volumes:
- /dev/shm:/dev/shm

app:
image: python:3-slim
working_dir: /app
command: /bin/bash
tty: true
volumes:
- ./app:/app

起動

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PS > docker-compose up
selenium-standalone_app_1 is up-to-date
selenium-standalone_chrome_1 is up-to-date
Attaching to selenium-standalone_app_1, selenium-standalone_chrome_1
chrome_1 | 2020-04-18 03:04:17,638 INFO Included extra file "/etc/supervisor/conf.d/selenium.conf" during parsing
chrome_1 | 2020-04-18 03:04:17,639 INFO supervisord started with pid 7
chrome_1 | 2020-04-18 03:04:18,641 INFO spawned: 'xvfb' with pid 10
chrome_1 | 2020-04-18 03:04:18,642 INFO spawned: 'selenium-standalone' with pid 11
chrome_1 | 03:04:18.800 INFO [GridLauncherV3.parse] - Selenium server version: 3.141.59, revision: e82be7d358
chrome_1 | 2020-04-18 03:04:18,801 INFO success: xvfb entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
chrome_1 | 2020-04-18 03:04:18,801 INFO success: selenium-standalone entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
chrome_1 | 03:04:18.859 INFO [GridLauncherV3.lambda$buildLaunchers$3] - Launching a standalone Selenium Server on port 4444
chrome_1 | 2020-04-18 03:04:18.888:INFO::main: Logging initialized @240ms to org.seleniumhq.jetty9.util.log.StdErrLog
chrome_1 | 03:04:19.041 INFO [WebDriverServlet.<init>] - Initialising WebDriverServlet
chrome_1 | 03:04:19.122 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
chrome_1 | 03:05:29.991 INFO [ActiveSessionFactory.apply] - Capabilities are: {
chrome_1 | "browserName": "chrome",
chrome_1 | "version": ""
chrome_1 | }
chrome_1 | 03:05:29.993 INFO [ActiveSessionFactory.lambda$apply$11] - Matched factory org.openqa.selenium.grid.session.remote.ServicedSession$Factory (provider: org.openqa.selenium.chrome.ChromeDriverService)
chrome_1 | Starting ChromeDriver 81.0.4044.69 (6813546031a4bc83f717a2ef7cd4ac6ec1199132-refs/branch-heads/4044@{#776}) on port 27205
chrome_1 | Only local connections are allowed.
chrome_1 | Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
chrome_1 | [1587179130.011][SEVERE]: bind() failed: Cannot assign requested address (99)
chrome_1 | 03:05:30.539 INFO [ProtocolHandshake.createSession] - Detected dialect: W3C
chrome_1 | 03:05:30.563 INFO [RemoteSession$Factory.lambda$performHandshake$0] - Started new session c7eb56f1ed116e861a77db2cbb3acd33 (org.openqa.selenium.chrome.ChromeDriverService)
chrome_1 | 03:05:31.362 INFO [ActiveSessions$1.onStop] - Removing session c7eb56f1ed116e861a77db2cbb3acd33 (org.openqa.selenium.chrome.ChromeDriverService)

テストスクリプト

appで実行するテストスクリプト

appで動かすこのスクリプト記述した接続先のchromeはdocker-composeによって名前解決される(docker-compose upで起動する必要がある)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

def test_access(driver):
driver.get('https://www.google.com')
driver.save_screenshot('test.png')
print(driver.title)
#driver.quit()

if __name__ == '__main__':
options = {
'command_executor': 'http://chrome:4444/wd/hub',
'desired_capabilities': DesiredCapabilities.CHROME,
}
with webdriver.Remote(**options) as driver:
test_access(driver)

テストスクリプトによるテスト

実行するapp上ではpip install seleniumでモジュールをインストール。
実行するとコンソール上にGoogleが表示され、画面キャプチャがtest.pngというファイル名で保存される。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PS > docker-compose up -d
Creating network "selenium_default" with the default driver
Creating selenium_app_1 ... done
Creating selenium-hub ... done
Creating selenium_firefox_1 ... done
Creating selenium_chrome_1 ... done
Creating selenium_opera_1 ... done
PS > docker-compose exec app bash
root@602dac150459:/app# pip install selenium
Collecting selenium
Downloading selenium-3.141.0-py2.py3-none-any.whl (904 kB)
|████████████████████████████████| 904 kB 2.6 MB/s
Collecting urllib3
Downloading urllib3-1.25.9-py2.py3-none-any.whl (126 kB)
|████████████████████████████████| 126 kB 11.3 MB/s
Installing collected packages: urllib3, selenium
Successfully installed selenium-3.141.0 urllib3-1.25.9
root@602dac150459:/app# python test_code.py
Google

Selenium Screenshot width=640

quit()の挙動

quit() すると、WebDriverException になる。

1
2
3
4
5
6
7
8
9
10
11
12
Traceback (most recent call last):
File "test_code.py", line 16, in <module>
test_access(driver)
File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 170, in __exit__
self.quit()
File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 698, in quit
self.execute(Command.QUIT)
File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: No active session with ID d0110743cd1a9b2d4789ad493a9c805b