IP地址 | 操作系统 | 安装软件 |
---|---|---|
172.17.2.82 | windows | PyCharm Pro |
172.17.2.118 | ubuntu16.04 | Docker |
PyCharm Pro安装在windows电脑上
PyCharm远程调用局域网内一台ubutun16.04系统上的docker python运行python代码
pycharm调用docker的原理如下:
docker在ubuntu系统上的安装见:安装docker
Ubuntu16.04下修改:
# 在下ExecStart行中增加:-H tcp://0.0.0.0:2375
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock
CentOS7下修改:
vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd-current -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock \
--add-runtime docker-runc=/usr/libexec/docker/docker-runc-current \
......
重新加载docker的service配置文件:
systemctl daemon-reload
systemctl restart docker
验证:
curl http://172.17.2.118:2375/images/json
在File --> settings中配置python解释器:
image name的python版本选择可见docker官方的github:
https://github.com/docker-library/docs/tree/master/python
此时在pycharm上运行python代码时会报错:
python: can't open file '/opt/project/run.py': [Errno 2] No such file or directory
这个/opt/project路径是哪来的呢?因为pycharm是在windows系统上跑的,肯定是没有此路径
这里注意:上图是我创建的是run.py文件,当再新创建一个文件运行时可能还是会出现一开始的错误,又需要手动设置下这里的Docker container settings项。如果想以后创建的所有文件都按此要求配置,可到下面的templates/python设置默认的配置
如果这里的路径配置不是你想要的,可以点击后面的文件夹图标进行修改。
所以我们需要把win上的pycharm代码上传到/data/pywwwroot/webcrawler目录下,当pycharm调用远程主机上的docker时,docker会将/data/pywwwroot/webcrawler挂载到/opt/project中
上面的步骤配置完成后可以正常运行python代码,但还有一个问题如果需要安装requests模块,要怎么做呢?默认的python:alpine:3.7镜像中不自带requests模块。此时需要借助于Dockerfile
此时运行Dockerfile时系统会根据Dockerfile文件自动构建出一个新的镜像,但是新的镜像的tag每次都不一样。下面给构建的新的镜像统一tag
这样每次构建出来的新镜像的tag标签统一为:spider-dev:latest。container name也设置成了spider-dev,即启动容器时,容器名为spider-dev。因为现在我们要使用新的镜像,所以在python解释器的地方也需要设置
注意:pycharm中的docker-compose.yaml文件无法像Dockerfile一样在文件上右键 --> 运行,docker-compose.yaml文件需要手动在远程主机上去运行
Dockerfile文件内容如下(下面安装的gevent为1.4.0版本,最新版的安装不上老报错):
FROM python:alpine3.7
# 修改alpine系统源及pip安装源
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN mkdir -p /root/.pip
RUN echo -e "[global]\nindex-url = https://mirrors.aliyun.com/pypi/simple/" > /root/.pip/pip.conf
# 安装gcc编译环境
RUN apk add --no-cache build-base
# 安装支持http/https协议客户端请求库
RUN pip install requests &&\
pip install aiohttp &&\
pip install tornado &&\
pip install selenium &&\
pip install appium-python-client
# 下列模块的安装需要gcc编译环境
RUN pip install twisted &&\
pip install gevent==1.4.0
# 安装scrapy
RUN apk add --no-cache libxml2-dev libxslt-dev zlib-dev libffi-dev openssl-dev &&\
pip install scrapy
# 安装pyspider
RUN apk add --no-cache curl-dev openssl-dev libxml2-dev libxslt-dev zlib-dev &&\
pip install pyspider &&\
apk del build-base
运行该Dockerfile文件前,可以先设置构建的镜像名称与启动的容器名称
配置完成后,在Dockerfile文件上右键 --> RUN ‘Docker/dockerfile’ 构建名为spider-dev的镜像且启动一个名称spider-dev的容器
selenium容器github地址:
https://github.com/SeleniumHQ/docker-selenium
在远程主机上启动一个selenium容器:
docker run -d \
--restart always \
--name selenium \
-p 4444:4444 \
--shm-size=2g \
selenium/standalone-chrome:3.141.59-20200409
也可以通过下面的方式启动selenium容器:
# 用这种方式启动挂载volume后报错
docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome:3.141.59-20200409
python脚本连接selenium docker:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import requests
driver = webdriver.Remote(
# 远程连接selenium,以下为固定写法
command_executor = "http://172.17.2.36:4444/wd/hub",
desired_capabilities = DesiredCapabilities.CHROME
)
driver.get("http://www.baidu.com")
print(driver.title)
driver.close()
如果连接无误,控制台应该输出:百度一下,你就知道
如果需要做数据保持,如下爬取一个web后将其保存为 xxx.html文件,就需要使用到docker-compose.yml文件:
version: "3.6"
services:
spider: # 如果没有指定hostname那么默认就是spider
image: spider-dev
container_name: spider-dev
volumes:
- ./baidu_spider.py:/data/baidu_spider.py
- ./data:/data
command: python /data/baidu_spider.py
depends_on:
- chrome
chrome:
container_name: chrome
image: selenium/standalone-chrome:3.141.59-20200409
ports:
- "4444:4444"
shm_size: 2g
爬虫文件内容如下:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import requests
# 下面这段while循环的作用:
# 因为是启动的spider-dev, selenium-chrome两个容器
# 而该脚本是在spider-dev中运行的,所以这里需要等待selenium-chrome容器中的chrome启动后才能运行后续的脚本
while True:
i = 0
try:
# 下面的chrome为上面docker-compose.yml文件中的hostname
resp = requests.get("http://chrome:4444/wd/hub/status", timeout = 0.5)
except:
i += 1
if i > 10:
raise
else:
print(resp.content)
break
driver = webdriver.Remote(
# 远程连接selenium,以下为固定写法
command_executor = "http://chrome:4444/wd/hub",
desired_capabilities = DesiredCapabilities.CHROME
)
driver.get("http://www.baidu.com")
print(driver.title)
with open("/data/baidu.html", "w") as f:
f.write(driver.page_source)
driver.close()
然后到远程docker主机上执行docker-compose命令:
root@ginvip:/data/pywwwroot/spider/selenium-chrome-docker# ll
total 8
-rw-r--r-- 1 root root 1012 Aug 22 18:30 baidu_spider.py
-rw-r--r-- 1 root root 399 Aug 22 18:26 docker-compose.yml
root@ginvip:/data/pywwwroot/spider/selenium-chrome-docker# docker-compose up -d
Creating network "selenium-chrome-docker_default" with the default driver
Creating chrome ... done
Creating spider-dev ... done
命令执行成功后,会在当前目录保存 data/baidu.html文件
启动容器:
# https://github.com/appium/appium-docker-android
docker run \
--privileged \
-d \
-p 4723:4723 \
-v ~/.android:/root/.android \
-v /dev/bus/usb:/dev/bus/usb \
--name container-appium \
appium/appium
# ~/.android:/root/.android
# 挂载上面的卷是为了当容器被删除后依然保留与手机的连接信息
当主机通过USB连接手机时,执行以下命令:
docker exec -it container-appium adb devices
此时手机会有个提示窗,点击确定即可,再次执行命令:
root@seed:~/docker/appium# docker exec -it appium adb devices
List of devices attached
3HX0217422004536 device
python代码连接手机:
from appium import webdriver
import time
desired_caps = {
}
desired_caps['platformName'] = "Android"
desired_caps['platformVersion'] = "9" # 关于手机中的Android版本号
desired_caps['deviceName'] = "HUAWEI Mate 9" # 关于手机中的产品名称
# 以下两项值的获取见下
desired_caps['appPackage'] = 'com.UCMobile'
desired_caps['appActivity'] = 'com.uc.browser.InnerUCMobile'
print('try to connect')
driver = webdriver.Remote(
# 远程连接selenium,以下为固定写法
command_executor = "http://172.18.0.3:4723/wd/hub", # IP地址为appium容器IP
desired_capabilities = desired_caps
)
print('connect success')
time.sleep(5) # 这里等待手机上的UC浏览器启动
driver.find_element_by_android_uiautomator("text(\"小说\")").click()
time.sleep(2)
driver.quit()
如何获取desired_caps[‘appPackage’] ,desired_caps[‘appActivity’] 的值
这里以华为手机上的UC浏览器为例。手机通过USB连接到电脑,运行以下命令
root@seed:~/docker/appium# docker exec -it appium adb shell # appium为容器名
HWMHA:/ $ # 正常的话会出现此行,表示进入了手机
然后执行命令:
HWMHA:/ $ logcat | grep ActivityManager