在无头模式下通过 Google Chrome 下载文件

Posted

技术标签:

【中文标题】在无头模式下通过 Google Chrome 下载文件【英文标题】:Download file through Google Chrome in headless mode 【发布时间】:2019-12-27 05:07:45 【问题描述】:

我在 Cromedrive 中以“正常”模式编写代码并且工作正常。当我更改为无头模式时,它不会下载文件。我已经尝试了在互联网上找到的代码,但没有用。

chrome_options = Options()
chrome_options.add_argument("--headless")
self.driver = webdriver.Chrome(chrome_options=chrome_options, executable_path=r'/chromedriver'.format(os.getcwd()))
self.driver.set_window_size(1024, 768)
self.driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')

params = 'cmd': 'Page.setDownloadBehavior', 'params': 'behavior': 'allow', 'downloadPath': os.getcwd()
self.driver.execute("send_command", params)

有人知道如何解决这个问题吗?

PS:我不一定需要使用 Chomedrive。如果它在另一个驱动器上工作,那对我来说没问题。

【问题讨论】:

检查这个:***.com/questions/45631715/… (***.com/questions/56778991/…) 这正是我发布的代码。 只使用常规模式并使用 xvfb-run 运行它 就用这个:***.com/a/24347178/3124333 【参考方案1】:

先解决办法

最低要求:

Selenium 客户端版本:Selenium v3.141.59 Chrome 版本:Chrome v77.0 ChromeDriver 版本:ChromeDriver v77.0

要下载文件,请单击this website 中带有下载数据 文本的元素,您可以使用以下解决方案:

代码块:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless")
options.add_argument("--window-size=1920,1080")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe', service_args=["--log-path=./Logs/DubiousDan.log"])
print ("Headless Chrome Initialized")
params = 'behavior': 'allow', 'downloadPath': r'C:\Users\Debanjan.B\Downloads'
driver.execute_cdp_cmd('Page.setDownloadBehavior', params)
driver.get("https://www.mockaroo.com/")
driver.execute_script("scroll(0, 250)"); 
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button#download"))).click()
print ("Download button clicked")
#driver.quit()

控制台输出:

Headless Chrome Initialized
Download button clicked

文件下载快照:


详情

自Headless Chrome 推出以来,通过Headless Chromium 下载文件是最受欢迎的功能之一。

从那时起,不同的贡献者发布了不同的解决方法,其中一些是:

Downloading with chrome headless and selenium Python equivalent of a given wget command

现在,好消息是 Chromium 团队已经正式宣布了功能的到来通过Headless Chromium下载文件。


在Headless mode doesn't save file downloads@eseckler的讨论中提到:

headless 中的下载工作略有不同。有Page.setDownloadBehaviordevtools 命令来设置下载文件夹。我们正在研究一种使用 DevTools 网络拦截的方法,也可以通过 DevTools 流式传输下载的文件。

详细讨论可以在Issue 696481: Headless mode doesn't save file downloads找到

最后,@bugdroid 修订版似乎为我们解决了问题。


[ChromeDriver] 支持无头模式下载文件

以前,在无头模式下运行的 Chromedriver 无法正确下载文件,因为它会稀疏地解析为其提供的首选项文件。 headless chrome 团队的工程师建议使用 DevTools 的“Page.setDownloadBehavior”来解决此问题。此更改列表实现了此修复。下载的文件默认到当前目录,并且可以在实例化 chromedriver 实例时使用 download_dir 进行设置。还添加了测试以确保正确的下载功能。

这里是revision 和commit

来自ChromeDriver v77.0.3865.40 (2019-08-20) 发行说明:

Resolved issue 2454: Headless mode doesn't save file downloads [Pri-2]

解决方案

更新 ChromeDriver 到最新的ChromeDriver v77.0 级别。 将 Chrome 更新到 Chrome 版本 77.0 级别。 (根据ChromeDriver v76.0 release notes)

注意Chrome v77.0 尚未进行 GAed/推送发布,因此在此之前,您可以从以下位置下载并安装开发版本并进行测试:

Chrome Canary 来自Dev Channel 的最新版本

结尾

但是,Mac OSX 用户需要等待On Chromedriver, headless chrome crashes after sending Page.setDownloadBehavior on MacOSX。

【讨论】:

@CBury 请确保 Chrome beta 版本为 v77.0 我已将我的 chrome 和 chromedrive 更新到 77,但仍然无法下载 还有其他方法可以设置download_dir吗? @ShinichiMaeshima 查看更新后的答案,如果您需要进一步的帮助,请告诉我。 您的示例正在运行,但是我使用相同的代码设置 selenium 以在无头 chrome 中下载,但它不工作【参考方案2】:

对于javascript,请使用以下代码:

    const chrome = require('selenium-webdriver/chrome');
    let options = new chrome.Options();
    options.addArguments('--headless --window-size=1500,1200');
    options.setUserPreferences( 'plugins.always_open_pdf_externally': true,
    "profile.default_content_settings.popups": 0,
    "download.default_directory": Download_File_Path );
    driver = await new webdriver.Builder().setChromeOptions(options).forBrowser('chrome').build();

然后一点击下载按钮就切换标签:

    await driver.sleep(1000); 
    var Handle = await driver.getAllWindowHandles();
    await driver.switchTo().window(Handle[1]);

【讨论】:

【参考方案3】:

Chomedriver 版本:95.0.4638.54 Chrome 版本 95.0.4638.69

    from selenium.webdriver.chrome.options import Options    
 
    options = Options()
    options.add_argument("--headless")
    options.add_argument("--start-maximized")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-extensions")
    options.add_argument('--disable-dev-shm-usage')    
    options.add_argument("--disable-gpu")
    options.add_argument('--disable-software-rasterizer')
    options.add_argument("user-agent=Mozilla/5.0 (Windows Phone 10.0; android 4.2.1; Microsoft; Lumia 640 XL LTE) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Edge/12.10166")
    options.add_argument("--disable-notifications")

    options.add_experimental_option("prefs", 
        "download.default_directory": "C:\\link\\to\\folder",
        "download.prompt_for_download": False,
        "download.directory_upgrade": True,
        "safebrowsing_for_trusted_sources_enabled": False,
        "safebrowsing.enabled": False
        
    )

似乎可行的是我使用“\\”而不是“/”作为地址。后一种方法没有抛出任何错误,但也没有下载任何文档。但是,使用双反斜杠就可以了。

【讨论】:

【参考方案4】:

我认为您不应该使用浏览器来下载内容,请将其留给 Chrome 开发人员/测试人员。

我相信你更应该得到你想要下载的元素的href attribute并使用requests library获取它

如果您的站点需要身份验证,您可以从浏览器实例中获取cookies 并将它们传递给requests.Session。

【讨论】:

这是我第一次尝试,但是 href 属性是:href="javascript:void(0)"

以上是关于在无头模式下通过 Google Chrome 下载文件的主要内容,如果未能解决你的问题,请参考以下文章

在无头 debian 系统上通过 Selenium 启动 google-chrome

Nightwatch测试在Headless chrome模式下找不到元素

无法在Chrome无头模式下运行测试

Selenium webdriver 无法在 chrome 无头模式下定位元素

无敌爬虫之无头浏览器

无头 chrome + 忽略证书错误