wake-up-neo.net

Herunterladen mit kopflosem Chrom und Selen

Ich verwende Python-Selenium und Chrome 59 und versuche, eine einfache Download-Sequenz zu automatisieren. Wenn ich den Browser normal starte, funktioniert der Download, aber wenn ich dies im Headless-Modus mache, funktioniert der Download nicht.

# Headless implementation
from Selenium import webdriver

chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument("headless")

driver = webdriver.Chrome(chrome_options=chromeOptions)

driver.get('https://www.mockaroo.com/')
driver.find_element_by_id('download').click()
# ^^^ Download doesn't start

# Normal Mode
from Selenium import webdriver

driver = webdriver.Chrome()

driver.get('https://www.mockaroo.com/')
driver.find_element_by_id('download').click()
# ^^^ Download works normally

Ich habe sogar versucht, einen Standardpfad hinzuzufügen:

prefs = {"download.default_directory" : "/Users/Chetan/Desktop/"}
chromeOptions.add_argument("headless")
chromeOptions.add_experimental_option("prefs",prefs)

Das Hinzufügen eines Standardpfads funktioniert in der normalen Implementierung, das gleiche Problem bleibt jedoch in der Headless-Version bestehen.

Wie kann ich den Download im Headless-Modus starten?

30
TheChetan

Ja, es ist eine "Funktion" für die Sicherheit. Wie bereits erwähnt, ist hier die Bug-Diskussion: https://bugs.chromium.org/p/chromium/issues/detail?id=696481

In Chrome Version 62.0.3196.0 oder höher wurde Unterstützung hinzugefügt, um das Herunterladen zu ermöglichen.

Hier ist eine Python-Implementierung. Ich musste den Befehl zu den Chromedriver-Befehlen hinzufügen. Ich werde versuchen, eine PR einzureichen, damit sie in der Bibliothek enthalten ist. 

def enable_download_in_headless_chrome(self, driver, download_dir):
    # add missing support for chrome "send_command"  to Selenium webdriver
    driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')

    params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': download_dir}}
    command_result = driver.execute("send_command", params)

Hier finden Sie ein kleines Repo, um zu zeigen, wie Sie dies verwenden können: https://github.com/shawnbutton/PythonHeadlessChrome

33
Shawn Button

Dies ist eine Funktion von Chrome, um zu verhindern, dass Software Dateien auf Ihren Computer lädt. Es gibt jedoch eine Problemumgehung. Lies mehr darüber hier .

Was Sie tun müssen, ist die Aktivierung über DevTools. Etwas wie das:

async function setDownload () {
  const client = await CDP({tab: 'ws://localhost:9222/devtools/browser'});
  const info =  await client.send('Browser.setDownloadBehavior', {behavior : "allow", downloadPath: "/tmp/"});
  await client.close();
}

Dies ist die Lösung, die jemand im erwähnten Thema gegeben hat. Hier ist sein Kommentar .

15
Some1Else

Hier ist ein Arbeitsbeispiel für Python basierend auf Shawn Buttons Antwort . Ich habe dies mit Chrom 68.0.3440.75 & Chromedriver 2.38 getestet.

from Selenium import webdriver
from Selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_experimental_option("prefs", {
  "download.default_directory": "/path/to/download/dir",
  "download.Prompt_for_download": False,
})

chrome_options.add_argument("--headless")
driver = webdriver.Chrome(chrome_options=chrome_options)

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

driver.get('http://download-page.url/')
driver.find_element_by_css_selector("#download_link").click()
5
Fayçal

Möglicherweise gibt die von Ihnen behandelte Website verschiedene HTML-Seiten für Browser zurück. Dies bedeutet, dass der XPath oder die ID, die Sie im headless-Browser möchten, möglicherweise anders ist. Versuchen Sie, pageSource im headless-Browser herunterzuladen, und öffnen Sie es als HTML-Seite, um die ID oder den XPath-Code anzuzeigen Sie möchten ... Sie können dies als c # -Beispiel sehen Wie kann ich FirefoxDriver (mit Selenium) ohne findElement-Funktionsfehler in PhantomDriver ausblenden?

3
Hazem

Normalerweise ist es überflüssig, dasselbe zu sehen, nur in einer anderen Sprache geschrieben, aber weil mich dieses Thema verrückt gemacht hat, hoffe ich, dass ich jemanden vor dem Schmerz rette ... also hier die C # -Version von Shawn Buttons Antwort (getestet mit headless chrom = 71.0.3578.98, chromedriver = 2.45.615279, Plattform = Linux 4.9.125-linuxkit x86_64)):

            var enableDownloadCommandParameters = new Dictionary<string, object>
            {
                { "behavior", "allow" },
                { "downloadPath", downloadDirectoryPath }
            };
            var result = ((OpenQA.Selenium.Chrome.ChromeDriver)driver).ExecuteChromeCommandWithResult("Page.setDownloadBehavior", enableDownloadCommandParameters);
1
victorvartan

Ein vollständiges Arbeitsbeispiel für JavaScript mit Selenium-Gurke-js/Selenium-Treiber:

const chromedriver = require('chromedriver');
const Selenium = require('Selenium-webdriver');
const command = require('Selenium-webdriver/lib/command');
const chrome = require('Selenium-webdriver/chrome');

module.exports = function() {

  const chromeOptions = new chrome.Options()
    .addArguments('--no-sandbox', '--headless', '--start-maximized', '--ignore-certificate-errors')
    .setUserPreferences({
      'profile.default_content_settings.popups': 0, // disable download file dialog
      'download.default_directory': '/tmp/downloads', // default file download location
      "download.Prompt_for_download": false,
      'download.directory_upgrade': true,
      'safebrowsing.enabled': false,
      'plugins.always_open_pdf_externally': true,
      'plugins.plugins_disabled': ["Chrome PDF Viewer"]
    })
    .windowSize({width: 1600, height: 1200});

  const driver = new Selenium.Builder()
    .withCapabilities({
      browserName: 'chrome',
      javascriptEnabled: true,
      acceptSslCerts: true,
      path: chromedriver.path
    })
    .setChromeOptions(chromeOptions)
    .build();

  driver.manage().window().maximize();

  driver.getSession()
    .then(session => {
      const cmd = new command.Command("SEND_COMMAND")
        .setParameter("cmd", "Page.setDownloadBehavior")
        .setParameter("params", {'behavior': 'allow', 'downloadPath': '/tmp/downloads'});
      driver.getExecutor().defineCommand("SEND_COMMAND", "POST", `/session/${session.getId()}/chromium/send_command`);
      return driver.execute(cmd);
    });

  return driver;
};

Der Schlüsselteil ist:

  driver.getSession()
    .then(session => {
      const cmd = new command.Command("SEND_COMMAND")
        .setParameter("cmd", "Page.setDownloadBehavior")
        .setParameter("params", {'behavior': 'allow', 'downloadPath': '/tmp/downloads'});
      driver.getExecutor().defineCommand("SEND_COMMAND", "POST", `/session/${session.getId()}/chromium/send_command`);
      return driver.execute(cmd);
    });

Getestet mit:

  • Chrome 67.0.3396.99
  • Chromedriver 2.36.540469
  • Selen-Gurke-js 1.5.12
  • Selen-Webtreiber 3.0.0
0

Folgendes ist das Äquivalent in Java, Selenium, Chromdriver und Chrome v 71.x. Der Code in ist der Schlüssel zum Speichern von Downloads Zusätzliche Jars: com.fasterxml.jackson.core, com.fasterxml.jackson.annotation, com.fasterxml.jackson.databind

System.setProperty ("webdriver.chrome.driver", "C:\libraries\chromedriver.exe");

            String downloadFilepath = "C:\\Download";
            HashMap<String, Object> chromePreferences = new HashMap<String, Object>();
            chromePreferences.put("profile.default_content_settings.popups", 0);
            chromePreferences.put("download.Prompt_for_download", "false");
            chromePreferences.put("download.default_directory", downloadFilepath);
            ChromeOptions chromeOptions = new ChromeOptions();
            chromeOptions.setBinary("C:\\pathto\\Chrome SxS\\Application\\chrome.exe");

            //ChromeOptions options = new ChromeOptions();
            //chromeOptions.setExperimentalOption("prefs", chromePreferences);
            chromeOptions.addArguments("start-maximized");
            chromeOptions.addArguments("disable-infobars");


            //HEADLESS CHROME
            **chromeOptions.addArguments("headless");**

            chromeOptions.setExperimentalOption("prefs", chromePreferences);
            DesiredCapabilities cap = DesiredCapabilities.chrome();
            cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
            cap.setCapability(ChromeOptions.CAPABILITY, chromeOptions);

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

            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);
            commandParams.put("params", params);
            ObjectMapper objectMapper = new ObjectMapper();
            HttpClient 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));**
            try {
                httpClient.execute(request);
            } catch (IOException e2) {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            }**

        //Continue using the driver for automation  
    driver.manage().window().maximize();
0
Manasi Vora

Ich habe dieses Problem gelöst, indem ich die von @Shawn Button gemeinsam genutzte Problemumgehung und den vollständigen Pfad für den Parameter 'downloadPath' verwendet habe. Die Verwendung eines relativer Pfad hat nicht funktioniert und mir den Fehler gemeldet.

Versionen:
Chrome Version 75.0.3770.100 (offizieller Build) (32-Bit)
ChromeDriver 75.0.3770.90

0
Matheus Araujo