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)
デフォルトパスの追加は通常の実装では機能しますが、ヘッドレスバージョンでも同じ問題が解決しません。
ダウンロードをヘッドレスモードで開始するにはどうすればよいですか?
はい、それはセキュリティのための「機能」です。前に述べたように、ここではバグの議論です: 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
これは、ソフトウェアがコンピューターにファイルをダウンロードするのを防ぐ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();
}
これは、前述のトピックで誰かが与えた解決策です。 ここに彼のコメントがあります 。
ショーンボタンの答え に基づいたPythonの動作例を次に示します。これをChromium 68.0.3440.75&chromedriver 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()
たぶん、あなたが扱うウェブサイトは、ブラウザごとに異なるHTMLページを返します。つまり、ヘッドレスブラウザでは、おそらく異なるXPathまたはIDを意味します。ヘッドレスブラウザーでpageSourceをダウンロードし、HTMLページとして開いて、必要なIdまたはXPathを確認してください。これはc#の例として見ることができます PhantomDriverでfindElement関数エラーなしでFirefoxDriverを非表示にする方法(Seleniumを使用)? .
通常、別の言語で書かれた同じものを見るのは冗長ですが、この問題が私を夢中にさせたので、私は他の人を痛みから救うことを望みます...だから、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);
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);
});
テスト済み:
以下は、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();
@Shawn Buttonが共有する回避策を使用し、 'downloadPath'パラメーターにフルパスを使用して、この問題を解決しました。 相対パスを使用しても機能せず、エラーが発生しました。
バージョン:
Chromeバージョン75.0.3770.100(公式ビルド)(32ビット)
ChromeDriver 75.0.3770.90