Dockerfile内容如下
FROM python
RUN pip install -i http://pypi.douban.com/simple \
requests selenium retrying --trusted-host pypi.douban.com
docker-compose.yaml内容如下
version: "3.7"
services:
myspider:
build: .
volumes: # 数据卷映射
- /root/mycode:/root/mycode
command: python /root/mycode/1.py
# 依赖下方 selenium服务,注意此依赖仅仅能做到
# selenium服务先启动, myspider服务后启动(有的服务内部程序启动的快,有的慢)
# 根本程度上还是解决不了 完全依赖 的 问题, 因此可以用延时处理等方法
depends_on:
- selenium
selenium:
image: selenium/standalone-chrome # 拉取镜像完成自动化全套配置
ports:
- "4444:4444"
shm_size: 2g # 设置主机共享内存2g
hostname: selenium # 其他容器可以用此名来访问 eg: http://selenium:4444/
爬虫脚本代码1.py如下
import requests
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.chrome.options import Options
from retrying import retry
# 注:docker-compose.yaml中的depends_on那里提到过:
# 服务可以起到先后依赖的效果。
# 而服务中的启动程序,并不能达到完全的依赖(启动速度相当的情况下,谁快谁慢运气成分)
# 可以通过加延时来控制先后顺序
# import time
# time.sleep(3) # 这种睡眠延时方式,或多或少不太精确,可以用下面的 retrying代替之
# 也可以通过 retrying模块装饰实现
# retrying用法,可参考 https://segmentfault.com/a/1190000019301761#articleHeader17
@retry(
stop_max_attempt_number = 10000,
stop_max_delay = 10*1000,
)
def verify_request():
response = requests.get("http://selenium:4444", timeout=0.5)
print(response)
verify_request()
# 下面基本上是连接Docker Selenium服务的固定写法,可当作模板套
options = Options()
options.add_argument('--headless')
with webdriver.Remote(
command_executor='http://selenium:4444/wd/hub', # selenium为docker-compose的host名
desired_capabilities=DesiredCapabilities.CHROME,
options=options
) as driver:
driver.get('http://www.baidu.com')
# 这里使用绝对路径, 否则数据卷映射失败
# 映射部分在上面 docker-compose.yaml 的 volumes部分
with open('/root/mycode/test.html', 'w') as f:
f.write(driver.page_source)
print('写入成功')
踩坑
selenium 因为有服务端程序,所以我们可以在远程"云服务器用Docker容器部署"
容器部署后。。。。
"只能云服务器中访问,
不能在远程服务器访问。
(
其实根本不需要在远程服务器访问的,某种邪恶的念头,让我走了弯路。。。一根筋想要远程访问
其实代码同是部署在容器中的,容器互通是完全OK的。
但如果你也想试试远程访问, 它却真的无法访问。。。。。。。。。。。
)"
(
我的认知里,既然云服务器宿主机可以访问容器内部 启动的服务端程序
而远程服务器不能访问容器内部的 启动的服务端程序。。。。那一定是容器和宿主机连通配置问题阿。
带着这个思路,找了很久很久, 然并卵。。。
)
实在没办法了。。科学上网,搜一下这个问题的解决方案吧。
后来无意中发现,客户端现在居然可以连上了。。
后来测试,哇, 果然是 需要科学上网才能 远程访问到,此服务端。。。
但我现在还没有明白,为什么我云服务器宿主机, 不需要科学上网,也能成功访问内部容器的服务端??
(虽然这个疑惑没有必要)