Загрузка с хромированным безголовым и селеном
Я использую python-селен и 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)
Добавление пути по умолчанию работает в обычной реализации, но такая же проблема сохраняется и в безголовой версии.
Как загрузить загрузку в режиме безглавых?
Ответы
Ответ 1
Да, это "функция", для обеспечения безопасности. Как уже упоминалось, здесь обсуждается ошибка: 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
Ответ 2
Это функция 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();
}
Это решение, которое кто-то дал в упомянутой теме. Вот его комментарий.
Ответ 3
Вот рабочий пример для 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()
Ответ 4
Возможно, веб-сайт, который вы обрабатываете, возвращает разные HTML-страницы для браузеров, означает, что XPath или Id, которые вы хотите, возможно, по-другому в браузере без браузера.
Попробуйте загрузить pageSource в браузере без браузера и откройте его как HTML-страницу, чтобы увидеть Id или XPath, которые вы хотите.
Вы можете видеть это как пример С# Как скрыть FirefoxDriver (используя Selenium) без ошибки функции findElement в PhantomDriver?.
Ответ 5
Обычно это излишне видеть то же самое, только что написанное на другом языке, но поскольку эта проблема сводила меня с ума, я надеюсь, что спасаю кого-то еще от боли... так что здесь версия ответа Шона Баттона на С# (проверено с помощью headless chrome = 71.0.3578.98, chromedriver = 2.45.615279, платформа = 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);
Ответ 6
Полный рабочий пример для JavaScript с selenium-cucumber-js/selenium-webdriver:
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
- селен-огурец-JS 1.5.12
- selenium-webdriver 3.0.0
Ответ 7
Ниже приводится эквивалент в Java, селен, chromedriver и Chrome v 71.x. Код в является ключом для сохранения загрузок. Дополнительные файлы jar: com.fasterxml.jackson.core, com.fasterxml.jackson.annotation, com.fasterxml.jackson.databind
System.setProperty( "webdriver.chrome.driver", "C:\библиотеки\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();
Ответ 8
Я пытаюсь загрузить файл с безголовым Chrome, используя версию 73.0.3639.1 и драйвер Chrome версии 2.45, но я не получаю никакого действительного вывода, и процесс завершается. Мне нужна помощь очень срочно, пожалуйста, помогите мне! заранее спасибо
Ответ 9
Привет всем, кто сделал (Загрузка с Chrome без головы и селена) в коде С#...
Ответ 10
Я прошел это руководство сам с самого начала Windows 10 и MacOS Mojave и успешно запустил загрузку.
Вот руководство о том, как скачивать файлы с безголовым Chrome:
https://medium.com/@moungpeter/how-to-automate-downloading-files-using-python-selenium-and-headless-chrome-9014f0cdd196?fbclid=IwAR0zsMzb4lMBHXK4GSynfE-vIRiX2ubJXT60_ARd6vQ8uOSUGAzMbLfduJ8
Ответ 11
Я решил эту проблему, используя обходной путь @Shawn Button и используя полный путь для параметра "downloadPath". Использование относительного пути не сработало и выдает ошибку.
Версии:
Chrome версии 75.0.3770.100 (официальная сборка) (32-разрядная версия)
ChromeDriver 75.0.3770.90