前言

困扰我两天的问题,终于看到了一点曙光,下面来好好总结下, robotframework实现自动化下载时,点击下载按钮,会有弹窗进行确认,且这个弹窗跟客户端有关,我们无法直接进行定位点击确认,且我的脚本是在Jenkins中执行,需要浏览器在headless模式下执行,对这个弹窗更要不得。headless模式只有chrome和firefox浏览器支持

chrome浏览器

因为我的脚本大部分都是用的chrome浏览器,先从chrome开始研究 关闭chrome弹窗, 需要设置这个参数为false download.prompt_for_download=False

详细代码如下:

OpenUrl
[Arguments] ${bro} ${url}
${driver_options}= Evaluate sys.modules['selenium.webdriver'].${bro}Options() sys, selenium.webdriver
${currentpath} evaluate os.getcwd() os #获取到项目所在目录
${prefs} create dictionary download.default_directory=${currentpath}${/}Doc${/}
... download.prompt_for_download=False
log ${prefs}
Call Method ${driver_options} add_experimental_option prefs ${prefs}
${options}= Call Method ${driver_options} to_capabilities
Create Webdriver ${bro} desired_capabilities=${options}
Go To ${url}

以上RF代码,下载文件是????的, 但如果设置为headless模式,竟然不生效了,看了网上的方法,比如这个 为啥不生效的原因,普遍说法是 there is currently a"feature" in chrome where headless does not allow file download: ​​bugs.chromium.org/p/chromium/…​​ This method is a hacky work-around until the official chromedriver support for this. Requires chrome version 62.0.3196.0 or above.

#无头模式(就是不打开浏览器)
chrome_options.add_argument("--headless")
browser = webdriver.Chrome(chrome_options=chrome_options)

browser.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')
params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': "E:\download"}}
command_result = browser.execute("send_command", params)

思路是这个思路,但结合RF没那么简单(中途放弃了,就跑去用firefox实现,firefox的坑也不小,firefox解决之后,不死心又来磕)经过我的反复尝试,在RF上终于成功了, 直接上代码 自己写了一个库

class HeadLessDownload(object):

ROBOT_LIBRARY_VERSION = 1.0

def __init__(self):
pass

@staticmethod
def download_in_headless_chrome(sl, url, download_dir):
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-gpu")
prefs = {
"download.default_directory": download_dir,
"download.prompt_for_download": False
}
chrome_options.add_experimental_option("prefs", prefs)
sl.open_browser(url=url, browser="Chrome", options=chrome_options)
driver = sl.driver
driver.command_executor._commands["send_command"] = ("POST", "/session/$sessionId/chromium/send_command")
params = {'cmd': 'Page.setDownloadBehavior',
'params': {'behavior': 'allow', 'downloadPath': download_dir}
}
command_res = driver.execute("send_command", params)
print(command_res)
print("response from browser:")
for key in command_res:
print("result:" + key + ":" + str(command_res[key]))

然后RF引用

OpenChromeDownloadHeadless
[Arguments] ${url}
${currentpath} evaluate os.getcwd() os #获取到项目所在目录
log ${currentpath}
${download_dir} set variable ${currentpath}${/}Doc${/}
${sl} get library instance SeleniumLibrary
download_in_headless_chrome ${sl} ${url} ${download_dir}

看到运行结果满眼的绿,欣慰的哭了

firefox

firefox要想去掉弹窗,设置的都要比chrome多,大概是这几个参数,网上大部分搜来的也是这

firefox_profile.set_preference("browser.download.dir", download_dir)
firefox_profile.set_preference("browser.download.folderList", 2)
firefox_profile.set_preference("browser.helperApps.neverAsk.openFile",
"image/webp, application/pdf")
firefox_profile.set_preference("browser.helperApps.neverAsk.saveToDisk",
"image/webp, application/pdf")

按照这几个设置,我兴冲冲的就去实现了,结果感人,弹窗还是照样弹,有个说法说是要下载的文件类型content-type必须要准确,我反复确认,试了仍然不ok, 这时我都想吐血了,后面终于被我逮到了症结所在,坑爹的firefox, 它初始化配置的时候必须传firefox profile文件,不然任你后面设置成花,也不会生效 来让我们正确打开firefox吧

(1) 本地手动打开firefox, 打开配置,修改download下载配置,然后保存 (2) 找到firefox配置文件,帮助--故障排除信息-配置文件夹, 这个就是配置文件, 你可以把它拷贝出来放到你的项目工程里,经过我一系列的试验,这个配置目录里只有两个文件对我有用,我只留了这两个,并改了名

robotframework--下载文件遇到的坑_配置文件

(3)再结合RF,终于成功了,我又一次喜极而泣,但是headless模式时,有个小问题,会先打开一个浏览器窗口,但是后续的操作也不会在这个窗口,估计是RF啥问题吧,还没轮到我去磕,后面如果解决,再来更新,但是用python纯代码实现,是完美的 python代码:涉及到项目隐私的已打码

robotframework--下载文件遇到的坑_firefox_02

RF代码,有小伙伴需要可以私我啊

总结

哪个浏览器都不是完美的,一个小小的download,迁出这么多问题, 学海无涯, 冲冲冲