Docker 使用 Selenium:在容器化环境中运行自动化测试
前言
随着容器技术的普及,Docker已经成为开发和部署环境的首选。尤其是对于自动化测试,利用Docker来管理和运行Selenium WebDriver可以大大提高测试环境的稳定性和可重复性。
在本文中,我们将探讨如何在Docker中使用Selenium,简化Web自动化测试的流程,并且通过Docker容器进行远程浏览器调试。
知识点📖📖
模块 | 链接 | 作用 |
---|---|---|
selenium | https://www.selenium.dev/zh-cn/documentation/ | 支持 web 浏览器自动化的一系列工具和库的综合项目 |
docker | https://www.docker.com/ | Docker 帮助开发人员在任何地方构建、共享、运行和验证应用程序,无需繁琐的环境配置或管理。 |
应用场景
在以下场景中,你可能需要使用Selenium与Docker结合来进行自动化测试:
- Web自动化测试:当你需要在不同浏览器和平台上运行自动化测试时,Selenium与Docker能够提供一致的环境和配置。
- 远程调试:通过noVNC,你可以方便地通过浏览器查看容器内的浏览器界面,进行手动调试,适用于UI自动化测试。
- CI/CD流水线:将自动化测试集成到持续集成(CI)流程中,通过Docker容器化环境避免环境不一致的问题。
- 多平台测试:在同一台机器上通过Docker快速启动多个浏览器实例,进行并行测试。
1. 使用 docker run 启动 Selenium
1.1 创建网络
为了让多个容器之间可以互相通信,首先需要创建一个自定义网络:
docker network create spider-net
1.2 启动Selenium容器
启动Selenium容器,确保它可以通过selenium/standalone-chrome
镜像启动,并将端口暴露出来:
docker run -d \
--name selenium \
--network spider-net \
-p 4444:4444 -p 7900:7900 \
--shm-size=3g \
-e VNC_NO_PASSWORD=1 \
selenium/standalone-chrome:latest
4444
端口:Selenium WebDriver服务的默认端口。7900
端口:通过noVNC提供的远程桌面端口,用于查看容器中的浏览器界面。--shm-size=3g
:设置共享内存大小,避免Chrome浏览器因内存不足而崩溃。
1.3 构建爬虫镜像
requirements.txt
selenium
Dockerfile
- 构建自己的爬虫镜像并配置
main.py
为爬虫脚本:
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple -r requirements.txt
# 安装中文字体,避免页面中文乱码(可选)
# RUN apt-get update && apt-get install -y fonts-wqy-zenhei fonts-wqy-microhei && rm -rf /var/lib/apt/lists/*
COPY . .
CMD ["python", "-u", "main.py"]
构建镜像:
docker build -t myspider:latest .
1.4 启动爬虫容器
启动爬虫容器并通过环境变量配置远程Selenium WebDriver地址:
docker run -d \
--name myspider \
--network spider-net \
-e SELENIUM_REMOTE_URL=http://selenium:4444/wd/hub \
-v "$(pwd)/main.py:/app/main.py" \
-v "$(pwd)/screenshots:/app/screenshots" \
myspider:latest
SELENIUM_REMOTE_URL
环境变量指向 Selenium 服务。-v
用于挂载文件或目录。
1.5 连接到 Remote Selenium
在爬虫脚本中,通过如下代码连接到远程的Selenium服务:
import os
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--window-size=1920,1080')
# 调试时不要加 --headless,可以通过noVNC看到真实浏览器
# options.add_argument('--headless')
driver = webdriver.Remote(
command_executor=os.environ['SELENIUM_REMOTE_URL'],
options=options
)
2. 使用 Docker Compose 管理 Selenium 和爬虫容器
为了更好地管理多个容器,推荐使用docker-compose
:
version: "3" # 这是版本号
services:
selenium: # 这是 Selenium 服务
image: selenium/standalone-chrome:latest
ports:
- 4444:4444 # Selenium 端口
- 7900:7900 # noVNC 端口
shm_size: 3g # 共享内存大小
environment:
- VNC_NO_PASSWORD=1 # 设置无密码连接
networks:
- spider-net # 网络配置
myspider: # 这是你的爬虫服务
image: myspider:latest
environment:
- SELENIUM_REMOTE_URL=http://selenium:4444/wd/hub # 远程 Selenium 地址
volumes:
- ./main.py:/app/main.py
- ./screenshots:/app/screenshots
networks:
- spider-net
depends_on:
- selenium
networks:
spider-net: # 自定义网络,用于容器间通信
driver: bridge
3. 页面元素操作技巧
遇到元素在屏幕外无法点击:
这一步非常关键!在容器中运行Selenium遇到的元素不可见、元素不可点击等错误大部分是因为
元素
没有在当前屏幕展示,所以需要将屏幕滚动到你的 元素 处。
driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)
这样可以将元素滚动到可见区域,再进行点击,避免出现“元素不可点击”错误。
4. 通过 noVNC 远程调试
- 浏览器访问
http://服务器IP:7900
,输入密码secret
,即可看到真实的浏览器界面,方便调试页面渲染和元素定位。
我本机的ip为 192.168.10.158
,这里访问url为:192.168.10.158:7900
。
5. 常见问题排查
- 黑屏:确认没有加
--headless
参数,或者noVNC
端口已正确映射。 - Chrome崩溃:增大
--shm-size
设置。 - 页面乱码:安装中文字体包。
- 元素不可点击:尝试先滚动元素再进行点击。
6. 关于 --headless 参数
经过测试,--headless
参数并没有明显加快程序的运行速度。因此,在使用时,你可以根据具体需求决定是否加上该参数。加上 --headless
主要是为了让浏览器不显示界面(即“无头模式”),这对某些背景任务可能有帮助,但对于性能提升并没有直接影响。
7. 运行效果展示
# main.py
import os
import time
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--window-size=1920,1080')
options.add_argument("--disable-browser-side-navigation")
options.add_argument('--no-sandbox')
options.add_argument("--window-size=1920,1080")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-gpu")
options.add_argument("blink-settings=imagesEnabled=false")
options.add_argument("enable-automation")
driver = webdriver.Remote(
command_executor=os.environ['SELENIUM_REMOTE_URL'],
options=options
)
# 访问网站
driver.get('https://frica.blog.csdn.net/')
print(driver.title)
driver.save_screenshot('./screenshots/frica.png')
# 停留10秒
time.sleep(10)
# 访问其它网站
driver.get('https://www.bilibili.com/')
print(driver.title)
driver.save_screenshot('./screenshots/bilibili.png')
time.sleep(10)
# 退出浏览器
driver.quit()
运行日志 和 容器
G:\docker-selenium>docker logs myspider
是小菜欸-CSDN博客
哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
G:\docker-selenium>docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55c585acb918 myspider:latest "python -u main.py" 5 minutes ago Exited (0) 4 minutes ago myspider
2b88dab30d9c selenium/standalone-chrome:latest "/opt/bin/entry_poin…" 42 minutes ago Up 15 minutes 0.0.0.0:4444->4444/tcp, 5900/tcp, 0.0.0.0:7900->7900/tcp, 9000/tcp selenium
代码运行git
- 注意看右上方日志输出(为程序的
print
输出
截图文件:
总结
- 推荐使用官方 Selenium 镜像,除非有特殊需求。
- 使用环境变量配置 Selenium 服务地址,确保容器间通过相同网络进行通信。
- 调试时不加
--headless
参数,通过 noVNC 远程查看浏览器界面。 --headless
参数按需添加:加速程序运行的效果并不明显,因此可以根据需求来决定是否启用。- 遇到问题时,先排查配置和依赖,调整内存和字体问题。