Wie lade ich eine Datei mit Python über HTTP herunter?

874

Ich habe ein kleines Dienstprogramm, mit dem ich eine MP3-Datei nach einem Zeitplan von einer Website herunterladen und dann eine Podcast-XML-Datei erstellen / aktualisieren kann, die ich zu iTunes hinzugefügt habe.

Die Textverarbeitung, mit der die XML-Datei erstellt / aktualisiert wird, ist in Python geschrieben. Ich verwende jedoch wget in einer Windows- .batDatei, um die eigentliche MP3-Datei herunterzuladen. Ich würde es vorziehen, das gesamte Dienstprogramm in Python zu schreiben.

Ich hatte Mühe, einen Weg zu finden, um die Datei tatsächlich in Python herunterzuladen, weshalb ich auf die Verwendung zurückgegriffen habe wget.

Wie lade ich die Datei mit Python herunter?

Owen
quelle
Viele der folgenden Antworten sind kein zufriedenstellender Ersatz für wget. Unter anderem werden wget(1) Zeitstempel beibehalten (2) der Dateiname wird automatisch anhand der URL ermittelt, .1(usw.) angehängt, wenn die Datei bereits vorhanden ist (3) und es stehen viele andere Optionen zur Verfügung, von denen einige möglicherweise in Ihre Datei eingefügt wurden .wgetrc. Wenn Sie eines davon möchten, müssen Sie es selbst in Python implementieren, aber es ist einfacher, es einfach wgetüber Python aufzurufen .
ShreevatsaR
2
Kurze Lösung für Python 3:import urllib.request; s = urllib.request.urlopen('http://example.com/').read().decode()
Basj

Antworten:

450

Verwenden Sie in Python 2 urllib2, das mit der Standardbibliothek geliefert wird.

import urllib2
response = urllib2.urlopen('http://www.example.com/')
html = response.read()

Dies ist die einfachste Art, die Bibliothek zu verwenden, abzüglich jeglicher Fehlerbehandlung. Sie können auch komplexere Aufgaben ausführen, z. B. das Ändern von Headern. Die Dokumentation finden Sie hier.

Corey
quelle
11
Dies funktioniert nicht, wenn die von Ihnen angegebene URL Leerzeichen enthält. In diesem Fall müssen Sie die URL analysieren und den Pfad mit einem Urlencode versehen.
Jason Sundram
91
Hier ist die Python 3-Lösung: stackoverflow.com/questions/7243750/…
tommy.carstensen
6
Nur als Referenz. Der Weg, um den Pfad zu urlencode isturllib2.quote
André Puel
11
@ JasonSundram: Wenn Leerzeichen darin sind, ist es keine URI.
Zaz
1
Dies funktioniert nicht unter Windows mit größeren Dateien. Sie müssen alle Blöcke lesen!
Avia
1115

Noch eine mit urlretrieve :

import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

(für Python 3+ verwenden import urllib.requestund urllib.request.urlretrieve)

Noch eine mit einem "Fortschrittsbalken"

import urllib2

url = "http://download.thinkbroadband.com/10MB.zip"

file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)

file_size_dl = 0
block_sz = 8192
while True:
    buffer = u.read(block_sz)
    if not buffer:
        break

    file_size_dl += len(buffer)
    f.write(buffer)
    status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
    status = status + chr(8)*(len(status)+1)
    print status,

f.close()
PabloG
quelle
1
Seltsamerweise funktionierte dies für mich unter Windows, wenn die urllib2-Methode dies nicht tat. Die urllib2-Methode funktionierte jedoch auf dem Mac.
InFreefall
6
Fehler: file_size_dl + = block_sz sollte + = len (Puffer) sein, da der letzte Lesevorgang oft kein vollständiger block_sz ist. Auch unter Windows müssen Sie die Ausgabedatei als "wb" öffnen, wenn es sich nicht um eine Textdatei handelt.
Aubergine Jeff
1
Ich auch urllib und urllib2 haben nicht funktioniert, aber urlretrieve hat gut funktioniert, wurde frustriert - danke :)
funk-shun
2
Wickeln Sie das Ganze (mit Ausnahme der Definition von Dateiname) ein if not os.path.isfile(file_name):, um ein Überschreiben von Podcasts zu vermeiden! nützlich, wenn es als Cronjob mit den URLs in einer HTML-Datei ausgeführt wird
Sriram Murali
2
@PabloG es ist ein kleines bisschen mehr als 31 Stimmen jetzt;) Wie auch immer, Statusleiste hat Spaß gemacht, also werde ich +1
Cinder
340

Verwenden Sie 2012 die Python-Anforderungsbibliothek

>>> import requests
>>> 
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760

Du kannst rennen pip install requests , um es zu bekommen.

Anfragen haben viele Vorteile gegenüber den Alternativen, da die API viel einfacher ist. Dies gilt insbesondere dann, wenn Sie eine Authentifizierung durchführen müssen. urllib und urllib2 sind in diesem Fall ziemlich unintuitiv und schmerzhaft.


30.12.2015

Die Leute haben ihre Bewunderung für den Fortschrittsbalken zum Ausdruck gebracht. Es ist cool, klar. Es gibt jetzt mehrere Standardlösungen, darunter tqdm:

from tqdm import tqdm
import requests

url = "http://download.thinkbroadband.com/10MB.zip"
response = requests.get(url, stream=True)

with open("10MB", "wb") as handle:
    for data in tqdm(response.iter_content()):
        handle.write(data)

Dies ist im Wesentlichen die vor 30 Monaten beschriebene Implementierung @kvance.

hughdbrown
quelle
Wie speichere oder extrahiere ich, wenn die Zip-Datei tatsächlich ein Ordner mit vielen Dateien ist?
Abdul Muneer
6
Wie geht das mit großen Dateien um, wird alles im Speicher gespeichert oder kann dies ohne großen Speicherbedarf in eine Datei geschrieben werden?
Bibstha
8
Es ist möglich, große Dateien zu streamen, indem Sie in der Anforderung stream = True setzen. Sie können dann iter_content () für die Antwort aufrufen, um jeweils einen Block zu lesen.
Kvance
7
Warum sollte eine URL-Bibliothek über eine Funktion zum Entpacken von Dateien verfügen? Lesen Sie die Datei aus der URL, speichern Sie sie und entpacken Sie sie auf die Art und Weise, wie Ihr Boot schwimmt. Auch eine Zip-Datei ist kein "Ordner", wie er in Windows angezeigt wird. Es ist eine Datei.
Harel
2
@Ali :: r.textFür Text- oder Unicode-Inhalte. Als Unicode zurückgegeben. r.content: Für binären Inhalt. Wird als Byte zurückgegeben. Lesen Sie hier darüber: docs.python-requests.org/en/latest/user/quickstart
hughdbrown
159
import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
  output.write(mp3file.read())

Das wbIn open('test.mp3','wb')öffnet eine Datei (und löscht alle vorhandenen Dateien) im Binärmodus, sodass Sie damit Daten anstatt nur Text speichern können.

Gewähren
quelle
30
Der Nachteil dieser Lösung besteht darin, dass die gesamte Datei vor dem Speichern auf der Festplatte in den RAM geladen wird. Dies ist jedoch zu beachten, wenn Sie diese Option für große Dateien auf einem kleinen System wie einem Router mit begrenztem RAM verwenden.
Tripplet
2
@tripplet also wie würden wir das beheben?
Lucas Henrique
11
Um zu vermeiden, dass die gesamte Datei in den Speicher file.readeingelesen wird , übergeben Sie ein Argument an die Anzahl der zu lesenden Bytes. Siehe: gist.github.com/hughdbrown/c145b8385a2afa6570e2
hughdbrown
@hughdbrown Ich fand Ihr Skript nützlich, habe aber eine Frage: Kann ich die Datei für die Nachbearbeitung verwenden? Angenommen, ich lade eine JPG-Datei herunter, die ich mit OpenCV verarbeiten möchte. Kann ich die Variable 'data' verwenden, um weiter zu arbeiten? oder muss ich es nochmal aus der heruntergeladenen Datei lesen?
Rodrigo E. Principe
5
Verwenden Sie shutil.copyfileobj(mp3file, output)stattdessen.
Aurélien Ooms
129

Python 3

  • urllib.request.urlopen

    import urllib.request
    response = urllib.request.urlopen('http://www.example.com/')
    html = response.read()
  • urllib.request.urlretrieve

    import urllib.request
    urllib.request.urlretrieve('http://www.example.com/songs/mp3.mp3', 'mp3.mp3')

    Hinweis: Laut Dokumentation urllib.request.urlretrievehandelt es sich um eine "Legacy-Schnittstelle" und "könnte in Zukunft veraltet sein" (danke gerrit )

Python 2

  • urllib2.urlopen(Danke Corey )

    import urllib2
    response = urllib2.urlopen('http://www.example.com/')
    html = response.read()
  • urllib.urlretrieve(danke PabloG )

    import urllib
    urllib.urlretrieve('http://www.example.com/songs/mp3.mp3', 'mp3.mp3')
Bmaupin
quelle
2
Es hat sicher eine Weile gedauert, aber da ist endlich die einfache API, die ich von einer Python-Stdlib erwarte :)
ThorSummoner
Sehr schöne Antwort für Python3, siehe auch docs.python.org/3/library/…
Edouard Thiel
@EdouardThiel Wenn Sie oben auf klicken urllib.request.urlretrieve, gelangen Sie zu genau diesem Link. Prost!
Bmaupin
2
urllib.request.urlretrievewird als "Legacy-Schnittstelle" dokumentiert und "könnte in Zukunft veraltet sein".
Gerrit
@gerrit Ich habe eine Notiz hinzugefügt, danke für das Heads-up!
Bmaupin
32

benutze das wget Modul:

import wget
wget.download('url')
Sara Santana
quelle
21

Eine verbesserte Version des PabloG-Codes für Python 2/3:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import ( division, absolute_import, print_function, unicode_literals )

import sys, os, tempfile, logging

if sys.version_info >= (3,):
    import urllib.request as urllib2
    import urllib.parse as urlparse
else:
    import urllib2
    import urlparse

def download_file(url, dest=None):
    """ 
    Download and save a file specified by url to dest directory,
    """
    u = urllib2.urlopen(url)

    scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
    filename = os.path.basename(path)
    if not filename:
        filename = 'downloaded.file'
    if dest:
        filename = os.path.join(dest, filename)

    with open(filename, 'wb') as f:
        meta = u.info()
        meta_func = meta.getheaders if hasattr(meta, 'getheaders') else meta.get_all
        meta_length = meta_func("Content-Length")
        file_size = None
        if meta_length:
            file_size = int(meta_length[0])
        print("Downloading: {0} Bytes: {1}".format(url, file_size))

        file_size_dl = 0
        block_sz = 8192
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break

            file_size_dl += len(buffer)
            f.write(buffer)

            status = "{0:16}".format(file_size_dl)
            if file_size:
                status += "   [{0:6.2f}%]".format(file_size_dl * 100 / file_size)
            status += chr(13)
            print(status, end="")
        print()

    return filename

if __name__ == "__main__":  # Only run if this file is called directly
    print("Testing with 10MB download")
    url = "http://download.thinkbroadband.com/10MB.zip"
    filename = download_file(url)
    print(filename)
Stan
quelle
Ich würde die Klammern aus der ersten Zeile entfernen, da es nicht zu alt ist.
Arpad Horvath
21

Einfache, aber Python 2 & Python 3kompatible Art und Weise kommt mit sixBibliothek:

from six.moves import urllib
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
Akif
quelle
1
Dies ist der beste Weg, um die 2 + 3-Kompatibilität zu gewährleisten.
Fush
21
import os,requests
def download(url):
    get_response = requests.get(url,stream=True)
    file_name  = url.split("/")[-1]
    with open(file_name, 'wb') as f:
        for chunk in get_response.iter_content(chunk_size=1024):
            if chunk: # filter out keep-alive new chunks
                f.write(chunk)


download("https://example.com/example.jpg")
HS Umer farooq
quelle
17

Schrieb wget Bibliothek in reinem Python nur für diesen Zweck. Es ist urlretrievemit diesen Funktionen ab Version 2.0 aufgepumpt .

anatoly techtonik
quelle
3
Keine Option zum Speichern mit benutzerdefiniertem Dateinamen?
Alex
2
@ Alex hinzugefügt -o FILENAME Option zu Version 2.1
anatoly techtonik
Der Fortschrittsbalken wird nicht angezeigt, wenn ich dieses Modul unter Cygwin verwende.
Joe Coder
Sie sollten von -ozu wechseln -O, um Verwirrung zu vermeiden, wie es in GNU wget ist. Oder zumindest sollten beide Optionen gültig sein.
Erik
@eric Ich bin mir nicht sicher, ob ich wget.pyeinen echten Ersatz für real machen möchte wget. Das -overhält sich schon anders - es ist damit kompatibel curl. Würde ein Hinweis in der Dokumentation helfen, das Problem zu beheben? Oder ist es das wesentliche Merkmal, dass ein Dienstprogramm mit einem solchen Namen befehlszeilenkompatibel ist?
Anatoly Techtonik
16

Im Folgenden sind die am häufigsten verwendeten Aufrufe zum Herunterladen von Dateien in Python aufgeführt:

  1. urllib.urlretrieve ('url_to_file', file_name)

  2. urllib2.urlopen('url_to_file')

  3. requests.get(url)

  4. wget.download('url', file_name)

Hinweis: urlopenund urlretrievegefunden werden relativ schlecht durchzuführen mit dem Herunterladen von großen Dateien (Größe> 500 MB). requests.getspeichert die Datei im Speicher, bis der Download abgeschlossen ist.

Jaydev
quelle
14

Ich stimme Corey zu, urllib2 ist vollständiger als urllib und sollte wahrscheinlich das Modul sein, das verwendet wird, wenn Sie komplexere Dinge tun möchten. Um die Antworten vollständiger zu machen, ist urllib ein einfacheres Modul, wenn Sie nur die Grundlagen wünschen:

import urllib
response = urllib.urlopen('http://www.example.com/sound.mp3')
mp3 = response.read()

Wird gut funktionieren. Wenn Sie sich nicht mit dem "Antwort" -Objekt befassen möchten, können Sie read () direkt aufrufen :

import urllib
mp3 = urllib.urlopen('http://www.example.com/sound.mp3').read()
Akdom
quelle
10

In Python3 können Sie urllib3 und shutil libraires verwenden. Laden Sie sie mit pip oder pip3 herunter (je nachdem, ob python3 Standard ist oder nicht)

pip3 install urllib3 shutil

Führen Sie dann diesen Code aus

import urllib.request
import shutil

url = "http://www.somewebsite.com/something.pdf"
output_file = "save_this_name.pdf"
with urllib.request.urlopen(url) as response, open(output_file, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)

Beachten Sie, dass Sie herunterladen, urllib3aber urllibim Code verwenden

Apoorv Agarwal
quelle
7

Sie können das Fortschrittsfeedback auch mit urlretrieve erhalten:

def report(blocknr, blocksize, size):
    current = blocknr*blocksize
    sys.stdout.write("\r{0:.2f}%".format(100.0*current/size))

def downloadFile(url):
    print "\n",url
    fname = url.split('/')[-1]
    print fname
    urllib.urlretrieve(url, fname, report)
Marcin Cuprjak
quelle
7

Wenn Sie wget installiert haben, können Sie parallel_sync verwenden.

pip install parallel_sync

from parallel_sync import wget
urls = ['http://something.png', 'http://somthing.tar.gz', 'http://somthing.zip']
wget.download('/tmp', urls)
# or a single file:
wget.download('/tmp', urls[0], filenames='x.zip', extract=True)

Doc: https://pythonhosted.org/parallel_sync/pages/examples.html

Das ist ziemlich mächtig. Es kann Dateien parallel herunterladen, bei einem Fehler erneut versuchen und sogar Dateien auf einen Remotecomputer herunterladen.

max
quelle
Beachten Sie, dass dies nur für Linux ist
jjj
4

Wenn Geschwindigkeit für Sie wichtig ist, habe ich einen kleinen Leistungstest für die Module urllibund wgetund in Bezug auf durchgeführtwget auf Ich habe einmal versucht , mit Statusleiste und einmal ohne. Ich habe drei verschiedene 500-MB-Dateien zum Testen genommen (verschiedene Dateien - um die Möglichkeit auszuschließen, dass unter der Haube etwas Caching stattfindet). Getestet auf einem Debian-Computer mit Python2.

Erstens sind dies die Ergebnisse (sie sind in verschiedenen Läufen ähnlich):

$ python wget_test.py 
urlretrive_test : starting
urlretrive_test : 6.56
==============
wget_no_bar_test : starting
wget_no_bar_test : 7.20
==============
wget_with_bar_test : starting
100% [......................................................................] 541335552 / 541335552
wget_with_bar_test : 50.49
==============

Die Art und Weise, wie ich den Test durchgeführt habe, ist die Verwendung eines "Profil" -Dekorators. Dies ist der vollständige Code:

import wget
import urllib
import time
from functools import wraps

def profile(func):
    @wraps(func)
    def inner(*args):
        print func.__name__, ": starting"
        start = time.time()
        ret = func(*args)
        end = time.time()
        print func.__name__, ": {:.2f}".format(end - start)
        return ret
    return inner

url1 = 'http://host.com/500a.iso'
url2 = 'http://host.com/500b.iso'
url3 = 'http://host.com/500c.iso'

def do_nothing(*args):
    pass

@profile
def urlretrive_test(url):
    return urllib.urlretrieve(url)

@profile
def wget_no_bar_test(url):
    return wget.download(url, out='/tmp/', bar=do_nothing)

@profile
def wget_with_bar_test(url):
    return wget.download(url, out='/tmp/')

urlretrive_test(url1)
print '=============='
time.sleep(1)

wget_no_bar_test(url2)
print '=============='
time.sleep(1)

wget_with_bar_test(url3)
print '=============='
time.sleep(1)

urllib scheint der schnellste zu sein

Omer Dagan
quelle
Unter der Motorhaube muss etwas völlig Schreckliches vor sich gehen, damit die Stange die Zeit so sehr verlängert.
Alistair Carscadden
4

Der Vollständigkeit halber ist es auch möglich, jedes Programm zum Abrufen von Dateien mit dem subprocessPaket aufzurufen . Programme zum Abrufen von Dateien sind leistungsfähiger als Python-Funktionen wie urlretrieve. Sie können beispielsweise wgetVerzeichnisse rekursiv herunterladen ( -R), FTP verarbeiten, umleiten, HTTP-Proxys verwenden, das erneute Herunterladen vorhandener Dateien vermeiden ( -nc) und aria2Downloads mit mehreren Verbindungen durchführen, wodurch Ihre Downloads möglicherweise beschleunigt werden.

import subprocess
subprocess.check_output(['wget', '-O', 'example_output_file.html', 'https://example.com'])

In Jupyter Notebook kann man Programme auch direkt mit der folgenden !Syntax aufrufen :

!wget -O example_output_file.html https://example.com
Robin Dinse
quelle
3

Quellcode kann sein:

import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()                            
sock.close()                                        
print htmlSource  
Olu Smith
quelle
3

Sie können PycURL für Python 2 und 3 verwenden.

import pycurl

FILE_DEST = 'pycurl.html'
FILE_SRC = 'http://pycurl.io/'

with open(FILE_DEST, 'wb') as f:
    c = pycurl.Curl()
    c.setopt(c.URL, FILE_SRC)
    c.setopt(c.WRITEDATA, f)
    c.perform()
    c.close()
Gzerone
quelle
2

Ich habe folgendes geschrieben, das in Vanille Python 2 oder Python 3 funktioniert.


import sys
try:
    import urllib.request
    python3 = True
except ImportError:
    import urllib2
    python3 = False


def progress_callback_simple(downloaded,total):
    sys.stdout.write(
        "\r" +
        (len(str(total))-len(str(downloaded)))*" " + str(downloaded) + "/%d"%total +
        " [%3.2f%%]"%(100.0*float(downloaded)/float(total))
    )
    sys.stdout.flush()

def download(srcurl, dstfilepath, progress_callback=None, block_size=8192):
    def _download_helper(response, out_file, file_size):
        if progress_callback!=None: progress_callback(0,file_size)
        if block_size == None:
            buffer = response.read()
            out_file.write(buffer)

            if progress_callback!=None: progress_callback(file_size,file_size)
        else:
            file_size_dl = 0
            while True:
                buffer = response.read(block_size)
                if not buffer: break

                file_size_dl += len(buffer)
                out_file.write(buffer)

                if progress_callback!=None: progress_callback(file_size_dl,file_size)
    with open(dstfilepath,"wb") as out_file:
        if python3:
            with urllib.request.urlopen(srcurl) as response:
                file_size = int(response.getheader("Content-Length"))
                _download_helper(response,out_file,file_size)
        else:
            response = urllib2.urlopen(srcurl)
            meta = response.info()
            file_size = int(meta.getheaders("Content-Length")[0])
            _download_helper(response,out_file,file_size)

import traceback
try:
    download(
        "https://geometrian.com/data/programming/projects/glLib/glLib%20Reloaded%200.5.9/0.5.9.zip",
        "output.zip",
        progress_callback_simple
    )
except:
    traceback.print_exc()
    input()

Anmerkungen:

  • Unterstützt einen "Fortschrittsbalken" -Rückruf.
  • Download ist ein 4 MB Test .zip von meiner Website.
imallett
quelle
funktioniert super, lauf es durch jupyter habe was ich will :-)
Samir Ouldsaadi
1

Dies mag etwas spät sein, aber ich habe den Code von pabloG gesehen und konnte nicht anders, als ein Betriebssystem ('cls') hinzuzufügen, damit es fantastisch aussieht! Hör zu :

    import urllib2,os

    url = "http://download.thinkbroadband.com/10MB.zip"

    file_name = url.split('/')[-1]
    u = urllib2.urlopen(url)
    f = open(file_name, 'wb')
    meta = u.info()
    file_size = int(meta.getheaders("Content-Length")[0])
    print "Downloading: %s Bytes: %s" % (file_name, file_size)
    os.system('cls')
    file_size_dl = 0
    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break

        file_size_dl += len(buffer)
        f.write(buffer)
        status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
        status = status + chr(8)*(len(status)+1)
        print status,

    f.close()

Wenn Sie in einer anderen Umgebung als Windows ausgeführt werden, müssen Sie etwas anderes als 'cls' verwenden. In MAC OS X und Linux sollte es "klar" sein.

JD3
quelle
3
clsmacht nichts auf meinem OS X oder auf einem meiner Ubuntu-Server. Einige Klarstellungen könnten gut sein.
kqw
Ich denke, Sie sollten clearfür Linux verwenden oder noch besser die Druckzeile ersetzen, anstatt die gesamte Befehlszeilenausgabe zu löschen.
Arijoon
4
Diese Antwort kopiert nur eine andere Antwort und fügt einer veralteten Funktion ( os.system()) einen Aufruf hinzu, der einen Unterprozess startet, um den Bildschirm mit einem plattformspezifischen Befehl ( cls) zu löschen . Wie hat das irgendwelche Upvotes? Absolut wertlose "Antwort" IMHO.
Corey Goldberg
1

urlretrieve und request.get sind einfach, die Realität jedoch nicht. Ich habe Daten für einige Websites abgerufen, einschließlich Text und Bilder. Die beiden oben genannten lösen wahrscheinlich die meisten Aufgaben. Für eine universellere Lösung empfehle ich jedoch die Verwendung von urlopen. Da es in der Python 3-Standardbibliothek enthalten ist, kann Ihr Code auf jedem Computer ausgeführt werden, auf dem Python 3 ausgeführt wird, ohne das Site-Paket vorinstallieren zu müssen

import urllib.request
url_request = urllib.request.Request(url, headers=headers)
url_connect = urllib.request.urlopen(url_request)

#remember to open file in bytes mode
with open(filename, 'wb') as f:
    while True:
        buffer = url_connect.read(buffer_size)
        if not buffer: break

        #an integer value of size of written data
        data_wrote = f.write(buffer)

#you could probably use with-open-as manner
url_connect.close()

Diese Antwort bietet eine Lösung für HTTP 403 Verboten beim Herunterladen von Dateien über http mit Python. Ich habe nur Anfragen und Urllib-Module ausprobiert, das andere Modul bietet möglicherweise etwas Besseres, aber dies ist dasjenige, mit dem ich die meisten Probleme gelöst habe.

Sphynx-HenryAY
quelle
0

Späte Antwort, aber für python>=3.6Sie können verwenden:

import dload
dload.save(url)

Installieren dloadmit:

pip3 install dload
CONvid19
quelle
0

Ich wollte alle Dateien von einer Webseite herunterladen. Ich habe es versuchtwget aber es ist fehlgeschlagen, also habe ich mich für die Python-Route entschieden und diesen Thread gefunden.

Nachdem ich es gelesen habe, habe ich eine kleine Befehlszeilenanwendung erstellt soupget, die die hervorragenden Antworten von PabloG und Stan erweitert und einige nützliche Optionen hinzugefügt.

Es verwendet BeatifulSoup , um alle URLs der Seite zu sammeln und dann diejenigen mit den gewünschten Erweiterungen herunterzuladen. Schließlich können mehrere Dateien gleichzeitig heruntergeladen werden.

Hier ist es:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import (division, absolute_import, print_function, unicode_literals)
import sys, os, argparse
from bs4 import BeautifulSoup

# --- insert Stan's script here ---
# if sys.version_info >= (3,): 
#...
#...
# def download_file(url, dest=None): 
#...
#...

# --- new stuff ---
def collect_all_url(page_url, extensions):
    """
    Recovers all links in page_url checking for all the desired extensions
    """
    conn = urllib2.urlopen(page_url)
    html = conn.read()
    soup = BeautifulSoup(html, 'lxml')
    links = soup.find_all('a')

    results = []    
    for tag in links:
        link = tag.get('href', None)
        if link is not None: 
            for e in extensions:
                if e in link:
                    # Fallback for badly defined links
                    # checks for missing scheme or netloc
                    if bool(urlparse.urlparse(link).scheme) and bool(urlparse.urlparse(link).netloc):
                        results.append(link)
                    else:
                        new_url=urlparse.urljoin(page_url,link)                        
                        results.append(new_url)
    return results

if __name__ == "__main__":  # Only run if this file is called directly
    # Command line arguments
    parser = argparse.ArgumentParser(
        description='Download all files from a webpage.')
    parser.add_argument(
        '-u', '--url', 
        help='Page url to request')
    parser.add_argument(
        '-e', '--ext', 
        nargs='+',
        help='Extension(s) to find')    
    parser.add_argument(
        '-d', '--dest', 
        default=None,
        help='Destination where to save the files')
    parser.add_argument(
        '-p', '--par', 
        action='store_true', default=False, 
        help="Turns on parallel download")
    args = parser.parse_args()

    # Recover files to download
    all_links = collect_all_url(args.url, args.ext)

    # Download
    if not args.par:
        for l in all_links:
            try:
                filename = download_file(l, args.dest)
                print(l)
            except Exception as e:
                print("Error while downloading: {}".format(e))
    else:
        from multiprocessing.pool import ThreadPool
        results = ThreadPool(10).imap_unordered(
            lambda x: download_file(x, args.dest), all_links)
        for p in results:
            print(p)

Ein Beispiel für seine Verwendung ist:

python3 soupget.py -p -e <list of extensions> -d <destination_folder> -u <target_webpage>

Und ein aktuelles Beispiel, wenn Sie es in Aktion sehen möchten:

python3 soupget.py -p -e .xlsx .pdf .csv -u https://healthdata.gov/dataset/chemicals-cosmetics
Gibbone
quelle