robotframework--下载文件遇到的坑

892 阅读3分钟

前言

困扰我两天的问题,终于看到了一点曙光,下面来好好总结下, 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配置文件,帮助--故障排除信息-配置文件夹, 这个就是配置文件, 你可以把它拷贝出来放到你的项目工程里,经过我一系列的试验,这个配置目录里只有两个文件对我有用,我只留了这两个,并改了名

image.png

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

image.png

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

总结

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