docker運(yùn)行時(shí)占用的資源非常少睹晒,而且能將環(huán)境進(jìn)行有效的隔離,可以快速的進(jìn)行部署前联,因此可以將docker與selenium結(jié)合實(shí)現(xiàn)在容器中執(zhí)行無(wú)界面的自動(dòng)化操作措译。例如:自動(dòng)測(cè)試、自動(dòng)下載郵件等偎行。
需求說(shuō)明
通過(guò)Selenium自動(dòng)的登錄郵箱川背,下載郵箱中符合條件的郵件,并對(duì)郵件的內(nèi)容進(jìn)行解析存檔蛤袒。
方案選擇
Selenium官方提供了基于selenium hub的方式來(lái)管理selenium的node節(jié)點(diǎn)熄云,提供了分布式的遠(yuǎn)程調(diào)度方案,可以為SeleniumGrid添加各種類型的WebDriver妙真。
基于Selenium Grid的方案適用于以下場(chǎng)景:
1.通過(guò)Selenium自動(dòng)訪問(wèn)網(wǎng)頁(yè)時(shí)皱碘,需要阻塞等待與用戶的交互,例如需要輸入短信驗(yàn)證碼的場(chǎng)景隐孽,通過(guò)Selenium Grid的調(diào)度癌椿,可以最優(yōu)的利用所有可訪問(wèn)的資源健蕊,提高系統(tǒng)的并發(fā)執(zhí)行效率。
2.需要對(duì)網(wǎng)頁(yè)的兼容性進(jìn)行測(cè)試時(shí)踢俄,可以接入多種內(nèi)核的WebDriver到Selenium Grid中缩功,這樣在進(jìn)行網(wǎng)頁(yè)的自動(dòng)化測(cè)試時(shí),也同時(shí)對(duì)瀏覽器的兼容性進(jìn)行了測(cè)試都办。
3.訪問(wèn)只支持IE內(nèi)核的網(wǎng)站時(shí)嫡锌,例如一些開發(fā)比較早的政府網(wǎng)站等。
4.訪問(wèn)需要安裝安全控件的網(wǎng)站琳钉,例如網(wǎng)銀的登錄等势木。
本次的需求對(duì)時(shí)效性要求不高,郵件的獲取需要由定時(shí)器進(jìn)行觸發(fā)歌懒,如果使用Selenium Grid啦桌,可能會(huì)增加了整個(gè)系統(tǒng)的復(fù)雜程度,分布式系統(tǒng)中每引入一個(gè)中間件及皂,就會(huì)增加系統(tǒng)的復(fù)雜性甫男,系統(tǒng)的可用性就會(huì)隨之降低。
基于以上分析验烧,考慮采用selenium handless的模式板驳,在Docker中運(yùn)行Chrome的WebDriver,完成最終郵件的自動(dòng)獲取碍拆。
在確定方案之后若治,需要尋找合適的docker鏡像,最終找到了chromium-xvfb這個(gè)鏡像文件感混,集成了chromium和xvfb直砂,可以滿足在Docker容器中通過(guò)selenium來(lái)進(jìn)行無(wú)界面的操作。
方案驗(yàn)證
1.下載chromium-xvfb的鏡像文件
[root@prod ~]# docker pull markadams/chromium-xvfb-py2
2.交互模式運(yùn)行
[root@prod ~]# docker run --rm -it markadams/chromium-xvfb-py2 bash
3.進(jìn)入pytho環(huán)境
root@8016c66877aa:/usr/src/app# python
4.輸入以下python代碼
from selenium import webdriver
driver = webdriver.Chrome()
url = 'https://github.com/mark-adams/docker-chromium-xvfb/blob/master/samples/python3/test_google.py'
driver.get(url)
沒(méi)有錯(cuò)誤輸出浩习,證明Chrome已經(jīng)在Docker下可以正常工作。
方案實(shí)施
以markadams/chromium-xvfb-py2作為基礎(chǔ)鏡像济丘,重新編寫的Dockerfile如下:
FROM markadams/chromium-xvfb-py2
WORKDIR /opt/zs5s/download-mail
COPY ./download-mail/.pip /root/.pip/
COPY ./download-mail/requirements.txt /opt/zs5s/download-mail/requirements.txt
RUN pip install --upgrade pip
RUN pip install -r requirements.txt && mkdir /tmp/downloaded_files
ENV DISPLAY :1
COPY ./download-mail /opt/zs5s/download-mail
COPY ./data_service /opt/zs5s/data_service
COPY ./save_mail /opt/zs5s/save_mail
COPY ./common/ /opt/zs5s/common
USER root
在編譯運(yùn)行后谱秽,發(fā)現(xiàn)在這個(gè)docker容器內(nèi)單純的去訪問(wèn)網(wǎng)頁(yè)沒(méi)有問(wèn)題,如果去執(zhí)行帶有鍵盤的操作時(shí)摹迷,會(huì)報(bào)錯(cuò)疟赊,錯(cuò)誤信息如下:
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: an X display is required for keycode conversions, consider using Xvfb
(Session info: chrome=57.0.2987.98)
(Driver info: chromedriver=2.28.455506 (18f6627e265f442aeec9b6661a49fe819aeeea1f),platform=Linux 4.4.27-moby x86_64)
經(jīng)過(guò)調(diào)查是需要在啟動(dòng)容器時(shí)執(zhí)行Xvfb,申請(qǐng)一塊Screen峡碉,具體可以參考鏈接1近哟。在Dockerfile中加入啟動(dòng)腳本:
CMD sh start.sh
start.sh的內(nèi)容如下:
#!/bin/sh
export DISPLAY=:1
Xvfb $DISPLAY -ac -screen 0 1280x1024x8 &
sleep 1
ps -aux
tail -f start.sh #測(cè)試用,為了阻塞住容器內(nèi)的進(jìn)程
結(jié)果驗(yàn)證
在新生成的容器內(nèi)執(zhí)行以下的python腳本鲫寄,可以正常執(zhí)行吉执,說(shuō)明在Chrome中已經(jīng)可以接收通過(guò)selenium傳入的鍵盤事件疯淫。
from splinter import Browser
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
url = 'https://github.com/mark-adams/docker-chromium-xvfb/blob/master/samples/python3/test_google.py'
browser = Browser('chrome')
browser.visit(url)
element = browser.find_by_xpath('/html/body/div[1]/header/div/div/div/div/form/label/input[1]')
element.type('aaaa')
殘留問(wèn)題
在python退出selenium時(shí),雖然執(zhí)行了driver.quit()函數(shù)戳玫,但是實(shí)際上Chrome并沒(méi)有真正的退出熙掺,似乎是selenium的一個(gè)Bug,在3.1中提到了修正咕宿,但是好像沒(méi)有起作用币绩,
selenium-commit-url
解決辦法可以考慮執(zhí)行shell腳本主動(dòng)的kill掉Chrome的進(jìn)程。
參考鏈接
1.protractor-sendkeys-not-working-an-x-display-is-required-for-keycode-conversion
2.crawling-python-selenium-docker
3.docker-chromium-xvfb