从Selenium和Chromedriver下载文件

5
我无法让Selenium和Chrome(Canary)下载文件。我正在使用Java和Chrome 59/60(因为我的测试既适用于Windows又适用于Linux),并且正在尝试从网页开始下载文件。 当我从selenium中不设置headless模式时,chrome窗口会打开并下载文件。 当我设置--headless标志时,chrome窗口不会打开,下载也不会开始。
    public static void chromeDownload() throws IOException, InterruptedException{
            
            ChromeOptions options = new ChromeOptions();
            String downloadFilepath = "";
            
            if (ValidateOS.isWindows()){
                System.out.println("This is a Windows system.");
                System.setProperty("webdriver.chrome.driver", "resources\\driver\\chromedriver.exe");
                options.setBinary("C:\\Users\\Juri\\AppData\\Local\\Google\\Chrome SxS\\Application\\chrome.exe");
                downloadFilepath = "C:\\";
            } else if (ValidateOS.isUnix()){
                System.out.println("This is a Unix system.");
                System.setProperty("webdriver.chrome.driver", "resources/driver/chromedriver");
                options.setBinary("/usr/bin/google-chrome");
                downloadFilepath = "/home/juri/";
            }
            
            // Manage the download
            HashMap<String, Object> chromePrefs = new HashMap<>();
            chromePrefs.put("profile.default_content_settings.popups", 0);
            chromePrefs.put("download.default_directory", downloadFilepath);
    
            // Save Chrome Options
            HashMap<String, Object> chromeOptionsMap = new HashMap<>();
            options.setExperimentalOption("prefs", chromePrefs);
            options.addArguments("--headless --disable-gpu");
            
            DesiredCapabilities cap = DesiredCapabilities.chrome();
            cap.setCapability(ChromeOptions.CAPABILITY, chromeOptionsMap);
            cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
            cap.setCapability(ChromeOptions.CAPABILITY, options);
            
            ChromeDriver driver = new ChromeDriver(cap);
                    
            driver.get("http://localhost/my-test-page.html");

            driver.findElement(By.id("download")).click(); 
            Thread.sleep(5000); // wait 5 seconds for a small file to download.. yes.. I know...
            driver.quit();
        }

在GUI模式下,点击后开始下载;在Headless模式下不会下载。如何解决?
OT
我使用的是Chrome Canary,版本为v.60,带有--headless功能。非常方便,在没有GUI的服务器上运行grabber。 但是,出于同样的原因……我觉得在没有GUI的服务器上下载Chrome是毫无意义的。除了主要问题之外……我想知道你们开发者是否认为,在Linux服务器上安装Chrome只是为了以Headless模式启动它这个做法可以接受。
更新: 如果有人看到这篇文章,并且知道解决方法,请告诉我:/搜索结果很少,我已经尝试了所有的解决方法。

最近有人问了一个类似的问题,已经得到了回答:https://dev59.com/hlcO5IYBdhLWcg3wjCMt。显然,无头浏览器只有在通过开发工具中的设置获得批准后才能下载。 - Karan Shishoo
@kshishoo 你好!很高兴有人注意到我的问题。新的问题正是我寻找了几周的东西。我会再次尝试这个项目,我的项目已经完成,但我在测试服务器上安装了Ubuntu GUI以使其工作。如果无头模式在这种解决方案中起作用,那就太棒了! - aPugLife
那个案子有任何更新吗?我在这里找到了一个Java的代码解决方案 https://bugs.chromium.org/p/chromium/issues/detail?id=696481#c93 我还没有测试过。不管怎样,我正在寻找一个更简短的解决方案。 - skymedium
2个回答

0

您是否预计使用"Docker"? 使用Selenium Grid和任意数量的浏览器启动dockerized Ubuntu。或者只是浏览器而没有Selenium网格。

另一方面,您不需要使用无头模式,但可以使用多线程。例如:

  1. 下载文件

  2. 然后只需使用以下命令启动:docker-compose up -d

  3. 根据您的服务器进行一些调整,以便在"localhost"上访问网格服务器
    http://localhost:4444/grid/console http://localhost:4444/wd/hub

  4. 使用以下代码:

    WebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub")); //在URL()构造函数上处理异常。

  5. 您拥有轻量级虚拟机,其中包含您的服务器可以处理的任意数量的浏览器。而且不需要--headless模式。

虽然这不是最初问题的解决方案。


0

通过调整在此链接中找到的代码解决了问题: 使用ChromeDriver和无头模式在Java、Selenium中下载文件

对于那些想知道我的代码现在是什么样子的人...

public static void chromeDownload(String address, String Headless, String DownDir) throws IOException, InterruptedException{

    ChromeOptions options = new ChromeOptions();
    String downloadFilepath = DownDir;

    if (ValidateOS.isWindows()){
        System.out.println("This is a Windows system.");
        System.setProperty("webdriver.chrome.driver", "resources\\driver\\chromedriver.exe");
        //options.setBinary("C:\\Users\\Juri\\AppData\\Local\\Google\\Chrome SxS\\Application\\chrome.exe");
        // If this is commented, the grabber will use the main Chrome
    } else if (ValidateOS.isUnix()){
        System.out.println("This is a Unix system.");
        System.setProperty("webdriver.chrome.driver", "resources/driver/chromedriver");
        options.setBinary("/usr/bin/google-chrome");
    }

    switch (Headless.toUpperCase()){
        case "TRUE":
            options.addArguments("--headless --disable-gpu");
            break;
        case "FALSE":
        default:
            options.addArguments("--window-size=1152,768");
            break;
    }
    options.addArguments("--test-type");
    options.addArguments("--disable-extension");

    ChromeDriverService driverService = ChromeDriverService.createDefaultService();
    ChromeDriver driver = new ChromeDriver(driverService, options);

    Map<String, Object> commandParams = new HashMap<>();
    commandParams.put("cmd", "Page.setDownloadBehavior");
    Map<String, String> params = new HashMap<>();
    params.put("behavior", "allow");
    params.put("downloadPath", downloadFilepath);
    params.put("cmd", "Page.setDownloadBehavior");

    commandParams.put("params", params);
    ObjectMapper objectMapper = new ObjectMapper();
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    String command = objectMapper.writeValueAsString(commandParams);
    String u = driverService.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
    HttpPost request = new HttpPost(u);
    request.addHeader("content-type", "application/json");
    request.setEntity(new StringEntity(command));
    httpClient.execute(request);

    driver.get(address);

    driver.findElement(By.id("download")).click(); 
    driver.quit();
}

2
你能否描述一下你的代码,而不是从别人的帖子中复制粘贴呢?你的代码似乎无法正常工作。 - Poltu
这对于在新标签页中打开的PDF文件无效。 - Poltu
@Poltu -- 请确保设置您的内容类型以支持pdf。同时请注意,Chrome尝试内联打开pdf文件,这可以被禁用(有其他相关主题:例如https://dev59.com/Ho3da4cB1Zd3GeqP0Xus) - A_Elric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接