web-dev-qa-db-ja.com

chromeヘッドレスおよびセレンを使用したダウンロード

Python-SeleniumとChrome 59を使用して、簡単なダウンロードシーケンスを自動化しようとしています。ブラウザを正常に起動するとダウンロードは機能しますが、ヘッドレスモードで起動するとダウンロードが機能しません。

# 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

私もデフォルトのパスを追加しようとしました:

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

デフォルトパスの追加は通常の実装では機能しますが、ヘッドレスバージョンでも同じ問題が解決しません。

ダウンロードをヘッドレスモードで開始するにはどうすればよいですか?

47
TheChetan

はい、それはセキュリティのための「機能」です。前に述べたように、ここではバグの議論です: https://bugs.chromium.org/p/chromium/issues/detail?id=696481

ダウンロードを有効にするために、chromeバージョン62.0.3196.0以降でサポートが追加されました。

python実装です。 chromedriverコマンドにコマンドを追加する必要がありました。将来的にライブラリに含まれるように、PRを送信しようとします。

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)

ここでの参照用に、これを使用する方法を示すための小さなリポジトリがあります。 https://github.com/shawnbutton/PythonHeadlessChrome

47
Shawn Button

これは、ソフトウェアがコンピューターにファイルをダウンロードするのを防ぐChromeの機能です。ただし、回避策があります。 詳細はこちら

あなたがする必要があるのは、DevToolsを介してそれを有効にすることです、そのような何か:

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();
}

これは、前述のトピックで誰かが与えた解決策です。 ここに彼のコメントがあります

17
Some1Else

ショーンボタンの答え に基づいたPythonの動作例を次に示します。これをChromium 68.0.3440.75chromedriver 2.38でテストしました

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()
11
Fayçal

たぶん、あなたが扱うウェブサイトは、ブラウザごとに異なるHTMLページを返します。つまり、ヘッドレスブラウザでは、おそらく異なるXPathまたはIDを意味します。ヘッドレスブラウザーでpageSourceをダウンロードし、HTMLページとして開いて、必要なIdまたはXPathを確認してください。これはc#の例として見ることができます PhantomDriverでfindElement関数エラーなしでFirefoxDriverを非表示にする方法(Seleniumを使用)? .

4
Hazem

通常、別の言語で書かれた同じものを見るのは冗長ですが、この問題が私を夢中にさせたので、私は他の人を痛みから救うことを望みます...だから、C#バージョンの ショーンボタンの答え =(ヘッドレスchrome = 71.0.3578.98、chromedriver = 2.45.615279、platform = 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

Selenium-cucumber-js/Selenium-webdriverを使用したJavaScriptの完全な実例:

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;
};

重要な部分は次のとおりです。

  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);
    });

テスト済み:

  • Chrome 67.0.3396.99
  • Chromedriver 2.36.540469
  • Selenium-cucumber-js 1.5.12
  • Selenium-webdriver 3.0.0
0

以下は、Java、Selenium、chromedriver、およびchrome v 71.xの同等のものです。のコードは、ダウンロードの保存を可能にするキーです。追加のjar: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

@Shawn Buttonが共有する回避策を使用し、 'downloadPath'パラメーターにフルパスを使用して、この問題を解決しました。 相対パスを使用しても機能せず、エラーが発生しました。

バージョン:
Chromeバージョン75.0.3770.100(公式ビルド)(32ビット)
ChromeDriver 75.0.3770.90

0
Matheus Araujo