Herunterladen von Bildern und anderen Dateien aus dem Internet in Python (einzeln oder in Stapeln)

Geschäft

Im Folgenden wird erläutert, wie Sie in Python die URL einer Bild-, ZIP-, PDF- oder anderen Datei im Web angeben, sie herunterladen und als lokale Datei speichern.

  • Bilder durch Angabe der URL herunterladen.
    • Code-Beispiel
    • urllib.request.urlopen():URL öffnen
    • open():Schreiben in eine Datei im Binärmodus
    • Ein einfacheres Codebeispiel
  • Herunterladen von ZIP-Dateien, PDF-Dateien, usw.
  • Extrahieren Sie die URL des Bildes auf der Webseite.
    • Wenn die Nummer fortlaufend ist
    • Auszug mit Beautiful Soup
  • Batch-Download mehrerer Bilder aus einer Liste von URLs

Bilder durch Angabe der URL herunterladen.

Sie können die Standardbibliothek nur zum Herunterladen einzelner Dateien verwenden, indem Sie deren URLs angeben; eine zusätzliche Installation ist nicht erforderlich.

Code-Beispiel

Im Folgenden finden Sie ein Beispiel für eine Funktion, die eine Datei herunterlädt und speichert, indem sie die URL und den Zielpfad sowie deren Verwendung angibt. Dieser Code ist etwas ausführlich, um ihn zu erklären. Ein einfaches Beispiel ist unten angegeben.

import os
import pprint
import time
import urllib.error
import urllib.request

def download_file(url, dst_path):
    try:
        with urllib.request.urlopen(url) as web_file:
            data = web_file.read()
            with open(dst_path, mode='wb') as local_file:
                local_file.write(data)
    except urllib.error.URLError as e:
        print(e)
url = 'https://www.python.org/static/img/python-logo.png'
dst_path = 'data/temp/py-logo.png'
download_file(url, dst_path)

Um das Zielverzeichnis anzugeben und die Datei unter dem URL-Dateinamen zu speichern, gehen Sie wie folgt vor

def download_file_to_dir(url, dst_dir):
    download_file(url, os.path.join(dst_dir, os.path.basename(url)))

dst_dir = 'data/temp'
download_file_to_dir(url, dst_dir)

Es extrahiert den Dateinamen aus der URL mit os.path.basename() und verbindet ihn mit dem mit os.path.join() angegebenen Verzeichnis, um den Zielpfad zu erzeugen.

Die folgenden Abschnitte beschreiben den Teil der Datenerfassung und den Teil der Datenspeicherung als Datei.

urllib.request.urlopen(): URL öffnen

Verwenden Sie urllib.request.urlopen(), um die URL zu öffnen und die Daten abzurufen. Beachten Sie, dass urllib.urlopen() in Python 2.6 und früher veraltet ist. urllib.request.urlretrieve() ist noch nicht veraltet, könnte es aber in Zukunft sein.

Um zu vermeiden, dass Sie beim Auftreten einer Ausnahme anhalten, fangen Sie den Fehler mit try und except ab.

Im Beispiel wird urllib.error importiert und nur urllib.error.URLError wird explizit erfasst. Die Fehlermeldung wird angezeigt, wenn die URL der Datei nicht vorhanden ist.

url_error = 'https://www.python.org/static/img/python-logo_xxx.png'
download_file_to_dir(url_error, dst_dir)
# HTTP Error 404: Not Found

Wenn Sie beim lokalen Speichern auch Ausnahmen (FileNotFoundError usw.) abfangen wollen, gehen Sie wie folgt vor.
(urllib.error.URLError, FileNotFoundError)

Es ist auch möglich, die Drittanbieter-Bibliothek Requests anstelle der Standardbibliothek urllib zu verwenden, um die URL zu öffnen und die Daten zu erhalten.

Schreiben in eine Datei im Binärmodus in open()

Die Daten, die mit urllib.request.urlopen() abgerufen werden können, sind ein Byte-String (Typ Bytes).

Open() mit mode='wb' als zweitem Argument schreibt die Daten im Binärformat. w bedeutet write und b bedeutet binär.

Ein einfacheres Codebeispiel

Verschachtelte with-Anweisungen können auf einmal geschrieben werden, getrennt durch Kommas.

Daraus lässt sich folgendes ableiten.

def download_file(url, dst_path):
    try:
        with urllib.request.urlopen(url) as web_file, open(dst_path, 'wb') as local_file:
            local_file.write(web_file.read())
    except urllib.error.URLError as e:
        print(e)

Herunterladen von ZIP-Dateien, PDF-Dateien, usw.

Die bisherigen Beispiele beziehen sich auf das Herunterladen und Speichern von Bilddateien. Da wir jedoch lediglich eine Datei im Internet öffnen und als lokale Datei speichern, können die gleichen Funktionen auch für andere Dateitypen verwendet werden.

Sie können Dateien herunterladen und speichern, indem Sie die URL angeben.

url_zip = 'https://from-locas.com/sample_header.csv.zip'
download_file_to_dir(url_zip, dst_dir)

url_xlsx = 'https://from-locas/sample.xlsx'
download_file_to_dir(url_xlsx, dst_dir)

url_pdf = 'https://from-locas/sample1.pdf'
download_file_to_dir(url_pdf, dst_dir)

Beachten Sie, dass die in dieser Funktion angegebene URL ein Link auf die Datei selbst sein muss.

Im Falle einer GitHub-Repository-Datei hat die folgende URL beispielsweise eine PDF-Erweiterung, ist aber eigentlich eine HTML-Seite. Wenn diese URL in der obigen Funktion angegeben wird, wird die HTML-Quelle heruntergeladen.

  • https://github.com/from-locals/python-snippets/blob/master/notebook/data/src/pdf/sample1.pdf

Der Link zur Datei-Entität ist die folgende URL, die Sie angeben müssen, wenn Sie die Datei herunterladen und speichern möchten.

  • https://github.com/from-locals/python-snippets/raw/master/notebook/data/src/pdf/sample1.pdf

Es gibt auch Fälle, in denen der Zugang durch einen Benutzer-Agenten, einen Referrer usw. eingeschränkt ist, so dass ein Download nicht möglich ist. Wir garantieren nicht, dass alle Dateien heruntergeladen werden können.

Es ist einfach, Requests zum Ändern oder Hinzufügen von Request-Headern wie z. B. User Agent zu verwenden.

Extrahieren Sie die URL des Bildes auf der Webseite.

Um alle Bilder einer Seite auf einmal herunterzuladen, extrahieren Sie zunächst die URLs der Bilder und erstellen Sie eine Liste.

Wenn die Nummer fortlaufend ist

Wenn die URL des Bildes, das Sie herunterladen möchten, eine einfache fortlaufende Nummer ist, ist es einfach. Wenn die URLs nicht nur fortlaufende Nummern sind, sondern auch eine gewisse Regelmäßigkeit aufweisen, ist es einfacher, eine Liste von URLs nach den Regeln zu erstellen, als mit Beautiful Soup zu scrapen (siehe unten).

Verwenden Sie die Notation des Listenverständnisses.

url_list = ['https://example.com/basedir/base_{:03}.jpg'.format(i) for i in range(5)]
pprint.pprint(url_list)
# ['https://example.com/basedir/base_000.jpg',
#  'https://example.com/basedir/base_001.jpg',
#  'https://example.com/basedir/base_002.jpg',
#  'https://example.com/basedir/base_003.jpg',
#  'https://example.com/basedir/base_004.jpg']

Im obigen Beispiel wird {:03} für eine dreistellige, mit Nullen aufgefüllte fortlaufende Nummer verwendet; {} wird verwendet, wenn das Auffüllen mit Nullen nicht notwendig ist, und {:05} wird für eine fünfstellige Nummer anstelle von drei Ziffern verwendet. Weitere Informationen über die Formatierungsmethode von string str finden Sie im folgenden Artikel.

Außerdem verwenden wir hier pprint, um die Ausgabe besser lesbar zu machen.

Auszug mit Beautiful Soup

Um Bild-URLs aus Webseiten in Massen zu extrahieren, verwenden Sie Beautiful Soup.

import os
import time
import urllib.error
import urllib.request

from bs4 import BeautifulSoup

url = 'https://de.from-locals.com/'
ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) '\
     'AppleWebKit/537.36 (KHTML, like Gecko) '\
     'Chrome/55.0.2883.95 Safari/537.36 '

req = urllib.request.Request(url, headers={'User-Agent': ua})
html = urllib.request.urlopen(req)

soup = BeautifulSoup(html, "html.parser")

url_list = [img.get('data-src') for img in soup.find(class_='list').find_all('img')]

In diesem Beispiel wird die URL des Miniaturbildes dieser Website extrahiert.

Die Struktur variiert je nach Webseite, aber im Grunde wird sie wie folgt erhalten.

  • Rufen Sie eine Liste von <img>-Tag-Objekten ab, indem Sie die Klasse, ID usw. des Blocks angeben, der die mehreren Bilder enthält, die Sie herunterladen möchten.
    • soup.find(class_='list').find_all('img')
  • Beziehen Sie die URL des Bildes aus dem src-Element oder data-src-Element des <img>-Tags.
    • img.get('data-src')

Der obige Beispielcode ist nur ein Beispiel und garantiert nicht, dass er funktioniert.

Batch-Download mehrerer Bilder aus einer Liste von URLs

Wenn Sie eine Liste von URLs haben, können Sie diese einfach in eine for-Schleife verwandeln und die Funktion zum Herunterladen und Speichern der Datei mit der ersten angezeigten URL aufrufen. Wegen der temporären URL-Liste ist der Funktionsaufruf download_image_dir() hier auskommentiert.

download_dir = 'data/temp'
sleep_time_sec = 1

for url in url_list:
    print(url)
#     download_file_dir(url, download_dir)
    time.sleep(sleep_time_sec)
# https://example.com/basedir/base_000.jpg
# https://example.com/basedir/base_001.jpg
# https://example.com/basedir/base_002.jpg
# https://example.com/basedir/base_003.jpg
# https://example.com/basedir/base_004.jpg

Um den Server nicht zu überlasten, verwende ich time.sleep(), um eine Wartezeit für jeden Bilddownload zu erzeugen. Die Einheit ist in Sekunden, daher wird im obigen Beispiel das Zeitmodul importiert und verwendet.

Das Beispiel bezieht sich auf Bilddateien, aber auch andere Dateitypen können zusammen heruntergeladen werden, sofern sie aufgelistet sind.