2017-08-11 1 views
20

J'utilise python-selenium et Chrome 59 et j'essaie d'automatiser une simple séquence de téléchargement. Quand je lance le navigateur normalement, le téléchargement fonctionne, mais quand je le fais en mode sans tête, le téléchargement ne fonctionne pas.Téléchargement avec chrome sans tête et sélénium

# 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 

J'ai même essayé d'ajouter un chemin par défaut:

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

Ajout d'un chemin par défaut fonctionne dans la mise en œuvre normale, mais le même problème persiste dans le version sans tête.

Comment lancer le téléchargement en mode sans écran?

+0

J'ai aussi essayé d'utiliser '' submit' et envoyer Keys.ENTER'. Cela fonctionne pour le navigateur normal, mais pas pour le navigateur sans écran. – TheChetan

+0

voulez-vous que ce soit fait en utilisant seulement le chrome ?? ou firefox ferait aussi? –

+0

Préférez chrome ou phantomjs – TheChetan

Répondre

14

Cette fonctionnalité de Chrome empêche le logiciel de télécharger des fichiers sur votre ordinateur. Il y a une solution de contournement cependant. Read more about it here.

Ce que vous devez faire est de permettre via DevTools, quelque chose comme ça:

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

Ceci est la solution quelqu'un a dans le sujet mentionné. Here is his comment.

+4

Cette solution nécessite de patcher Chrome, ce n'est pas une solution de contournement. La commande 'Browser.setDownloadBehavior' est ** non présente ** dans Chrome v62.0.3186.0. –

+0

J'ai sauté dans le même problème il y a quelques mois. Je n'ai trouvé aucune solution jusqu'à aujourd'hui, grâce à un mec commentant ma question et me pointant ici. La lecture de cette réponse me rend heureux, mais je n'ai aucune idée de la façon de copier ou d'adapter ce code dans ma source. – Nihvel

+0

@Nihvel, https://stackoverflow.com/a/36613546/4110233 pourrait aider! – TheChetan

3

Peut-être que le site Web que vous gérez renvoie des pages HTML différentes pour les navigateurs, le XPath ou l'Id que vous voulez peut-être différemment dans un navigateur sans écran. Essayez de télécharger pageSource dans un navigateur sans tête et ouvrez-le en tant que page HTML pour voir l'ID ou XPath que vous voulez. Vous pouvez voir ceci comme exemple C# How to hide FirefoxDriver (using Selenium) without findElement function error in PhantomDriver?.

+0

Après avoir obtenu la page et fait 'driver.get_screenshot_as_file ('foo.png')', je reçois une image de la chose réelle et ça a l'air ok. En outre, le conducteur est capable de trouver le bouton. Enquêter sur ceci. –

8

Oui, c'est une "fonctionnalité", pour des raisons de sécurité. Comme mentionné précédemment ici est la discussion de bogue: https://bugs.chromium.org/p/chromium/issues/detail?id=696481

Le support a été ajouté dans la version de chrome 62.0.3196.0 ou ci-dessus pour permettre le téléchargement.

Voici une implémentation python. J'ai dû ajouter la commande aux commandes chromedriver. Je vais essayer de soumettre un PR afin qu'il soit inclus dans la bibliothèque à l'avenir.

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) 

Pour référence ici est un peu repo pour démontrer comment utiliser ceci: https://github.com/shawnbutton/PythonHeadlessChrome

+0

Cela a fonctionné pour moi. Belle solution de contournement. –