In diesem kurzen Python-Tutorial geht es darum, wie du mit Python Dateien von URLs schnell und schmerzlos herunterladen kannst.
Ich werde dafür die beliebte Bibliothek Requests verwenden. Ich werde dir Methoden zeigen, um Binärdateien von URLs herunterzuladen und ihre Dateinamen festzulegen.
Requests Bibliothek installieren
Wenn du die requests Bibliothek noch nicht installiert hast, dann öffne deine Kommandozeile. Führe dort folgenden Befehl aus:
pip install requests
Sobald die requests-Bibliothek installiert ist, können wir damit arbeiten.
Bilder mit Python herunterladen
Fangen wir Schritt-für-Schritt an, um mit Hilfe von Python-Requests Dateien herunterzuladen:
import requests
url = 'https://www.python.org/favicon.ico'
r = requests.get(url, allow_redirects=True)
open('meinfavicon.ico', 'wb').write(r.content)
Der oben gezeigte Code wird das Favicon (Bild) von https://www.python.org/favicon.ico herunterladen und als "meinfavicon.ico" abspeichern.
Geht es auch mit anderen Medien?
Jetzt kostenlosen Crashkurs sichern (Online Programmieren, keine Installation nötig)
Videos mit Python herunterladen (z.B. YouTube)
Jetzt schauen wir uns folgenden YouTube-Link an: https://www.youtube.com/watch?v=TTAfn22UF70
Was glaubst du, was passiert, wenn wir den YouTube-Link in unseren Code einfügen?
Wenn du glaubst, dass er einfach die HTML-Seite herunterlädt, ohne die Video-Datei zu berücksichtigen, liegst du goldrichtig!
Wenn ein Link (bzw. eine URL) auf eine Webseite, anstatt auf eine Binärdatei (wie z.B. ein MP4-Video), dann wird einfach nur die HTML-Seite heruntergeladen. Doch wie kommen wir jetzt an die Videodatei? Um das zu lösen, habe ich mir die Header der URL angeschaut. Üblicherweise haben Header einen "Content-Type" Parameter. Dieser Parameter sagt uns auf welchen Datentypen die URL verlinkt. Hier ist der Code:
r = requests.get(url, allow_redirects=True)
print(r.headers.get('content-type'))
Probiere den o.g. Code einfach aus. Es ist nicht wirklich optimal, da immer noch die HTML-Datei heruntergeladen wird, um den Header herauszufinden.
Wenn es sich um eine große Datei (wie bei einem langen Video) handelt, dann verschwendest du eine Menge Datenvolumen.
Doch es gibt einen eleganteren Weg an den Header zu kommen, ohne die HTML-Datei herunterladen zu müssen. Die Lösung dafür habe ich in der Request-Dokumentation gefunden. Hier der Code:
import requests
def herunterladen(url):
# Pruefe den content-type der URL
x = requests.head(url, allow_redirects=True)
header = x.headers
content_type = header.get('content-type')
if 'text' in content_type.lower():
return False
if 'html' in content_type.lower():
return False
return True
print(herunterladen('https://www.youtube.com/watch?v=TTAfn22UF70')) # Gibt "False" aus
print(herunterladen('https://www.python.org/favicon.ico')) # Gibt "True" aus
Es bietet sich noch an, die Dateigröße zu beschränken. Dafür benutzen wir die "Content-Length" im Header.
content_length = header.get('content-length', None)
if content_length and content_length > 2e8: # Das sind ca. 200 MB
return False
Super! Mit unserer Funktion können wir URL's überspringen, die nicht auf Medien verlinken.
Jetzt brauchen wir noch den Dateinamen der URL, der auf unsere Medien verlinkt.
Dateinamen aus URL's auslesen / parsen mit Python
Wir können mit Python den Dateinamen aus einer URL parsen.
Als Beispiel nehmen wir unser LerneProgrammieren-Logo: https://lerneprogrammieren.de/wp-content/uploads/Logo-blau3.png
Die einfachste Lösung dafür ist es, alle Zeichen nach dem letzten Slash (/) zu parsen, also alles hinter uploads/.
url = 'https://lerneprogrammieren.de/wp-content/uploads/Logo-blau3.png'
if url.find('/'):
print(url.rsplit('/', 1)[1])
In einigen Fällen wird der Dateiname durch diesen Code korrekt erfasst. Es gibt jedoch Fälle, in denen die Informationen zum Dateinamen nicht in der URL stehen.
Beispiel: http://test.com/download
Wie können wir dieses Problem lösen? Der Header "Content-Disposition" kommt hier zur Rettung. So ruft man den Dateinamen elegant ab:
import requests
import re
def dateiname_content_dispo(cd):
if not cd:
return None
dname = re.findall('dateiname=(.+)', cd)
if len(dname) == 0:
return None
return dname[0]
url = 'https://lerneprogrammieren.de/wp-content/uploads/Logo-blau3.png'
req = requests.get(url, allow_redirects=True)
dateiname = dateiname_content_dispo(req.headers.get('content-disposition'))
open(dateiname, 'wb').write(req.content)
Die obige Methode funktioniert in den meisten Fällen um den Dateinamen aus dem "Content-Disposition" Header auszulesen. So kannst du jedenfalls ganz einfach Dateien in Python 3 herunterladen.
(Tipp: Wenn du Python lernen möchtest, schau dir auch unseren ausführlichen Ratgeber an)
Teste den fertigen Code selbst aus und sag mir, was du davon hältst. Vielleicht hast du ja auch noch eine Idee, den Python-Code zu verbessern?
- Programmiere echte Apps als Anfänger
- Keine Installation, sofort loslegen
- Komplett praxisbezogen
- Zugriff auf Online-Editor
