Ich gebe zu, diese Lösung ist ein bisschen "hacky" als das Firefox-Profil saveToDisk Alternative, aber es funktioniert sowohl Chrome und Firefox, und verlässt sich nicht auf eine browserspezifische Funktion, die jederzeit ändern könnte . Und wenn nicht anders, vielleicht wird dies jemandem eine andere Perspektive geben, wie zukünftige Herausforderungen zu lösen sind.
Voraussetzungen: Stellen Sie sicher, Sie haben Selen und pyvirtualdisplay installiert ...
- Python 2:
sudo pip install selenium pyvirtualdisplay
- Python 3:
sudo pip3 install selenium pyvirtualdisplay
The Magic
import pyvirtualdisplay
import selenium
import selenium.webdriver
import time
import base64
import json
root_url = 'https://www.google.com'
download_url = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
print('Opening virtual display')
display = pyvirtualdisplay.Display(visible=0, size=(1280, 1024,))
display.start()
print('\tDone')
print('Opening web browser')
driver = selenium.webdriver.Firefox()
#driver = selenium.webdriver.Chrome() # Alternately, give Chrome a try
print('\tDone')
print('Retrieving initial web page')
driver.get(root_url)
print('\tDone')
print('Injecting retrieval code into web page')
driver.execute_script("""
window.file_contents = null;
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
window.file_contents = reader.result;
};
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', %(download_url)s);
xhr.send();
""".replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ') % {
'download_url': json.dumps(download_url),
})
print('Looping until file is retrieved')
downloaded_file = None
while downloaded_file is None:
# Returns the file retrieved base64 encoded (perfect for downloading binary)
downloaded_file = driver.execute_script('return (window.file_contents !== null ? window.file_contents.split(\',\')[1] : null);')
print(downloaded_file)
if not downloaded_file:
print('\tNot downloaded, waiting...')
time.sleep(0.5)
print('\tDone')
print('Writing file to disk')
fp = open('google-logo.png', 'wb')
fp.write(base64.b64decode(downloaded_file))
fp.close()
print('\tDone')
driver.close() # close web browser, or it'll persist after python exits.
display.popen.kill() # close virtual display, or it'll persist after python exits.
Explaination
Wir sind auf der Domäne zuerst eine URL laden wir aus einer Datei herunterladen Targeting sind. Auf diese Weise können wir eine AJAX-Anfrage für diese Domain durchführen, ohne auf cross site scripting Probleme zu stoßen.
Als nächstes injizieren wir etwas Javascript in das DOM, das eine AJAX-Anfrage auslöst. Sobald die AJAX-Anforderung eine Antwort zurückgibt, nehmen wir die Antwort und laden sie in ein FileReader-Objekt. Von dort können wir den Base64-codierten Inhalt der Datei durch Aufrufen von readAsDataUrl() extrahieren. Wir nehmen dann den base64-codierten Inhalt und fügen ihn an window
an, eine Variable, die für alle zugänglich ist.
Schließlich, da die AJAX-Anfrage asynchron ist, geben wir eine Python-while-Schleife ein, die darauf wartet, dass der Inhalt an das Fenster angehängt wird. Sobald es angehängt ist, dekodieren wir den Base64-Inhalt aus dem Fenster und speichern ihn in einer Datei.
Diese Lösung sollte in allen modernen Browsern funktionieren, die von Selenium unterstützt werden, und funktioniert sowohl in Text- als auch in Binärdateien und für alle MIME-Typen.
alternativer Ansatz
Während ich dies nicht getestet haben, hat Selen Sie die Möglichkeit, sich leisten zu warten, bis ein Element im DOM vorhanden ist. Anstatt eine Schleife zu erstellen, bis eine global zugängliche Variable gefüllt ist, können Sie ein Element mit einer bestimmten ID im DOM erstellen und die Bindung dieses Elements als Auslöser zum Abrufen der heruntergeladenen Datei verwenden.
Ich empfehle, 'urllib' zu verwenden und' urllib.urlretrieve (url) 'zu verwenden, um den Download zu erhalten, wobei' url' die URL ist, die der Link sendet Sie zu – Serial
nein, weil es nur mit Click-Ereignis funktioniert. – sam
aber wenn Sie den HTML der Seite analysieren, können Sie die Verbindung erhalten, die das Klickereignis an den Browser sendet und das – Serial