Frage

Ich habe ein kleines Dienstprogramm, mit dem ich nach einem Zeitplan eine MP3-Datei von einer Website herunterlade und dann eine Podcast-XML-Datei erstelle/aktualisiere, die ich offensichtlich zu iTunes hinzugefügt habe.

Die Textverarbeitung, die die XML-Datei erstellt/aktualisiert, ist in Python geschrieben.Ich verwende wget in einem Windows .bat Datei, um die eigentliche MP3 herunterzuladen.Ich würde es allerdings vorziehen, wenn das gesamte Dienstprogramm in Python geschrieben wäre.

Ich hatte jedoch Mühe, eine Möglichkeit zu finden, die Datei tatsächlich in Python herunterzuladen, weshalb ich darauf zurückgegriffen habe wget.

Wie lade ich die Datei mit Python herunter?

War es hilfreich?

Lösung

Verwenden Sie in Python 2 urllib2, das in der Standardbibliothek enthalten ist.

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

Dies ist die einfachste Art, die Bibliothek zu verwenden, ohne jegliche Fehlerbehandlung.Sie können auch komplexere Aufgaben wie das Ändern von Headern erledigen.Die Dokumentation ist zu finden Hier.

Andere Tipps

Noch eins, mit urlretrieve:

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

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

Noch einer, 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()

Im Jahr 2012 nutzen Sie die Python fordert Bibliothek an

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

Du kannst rennen pip install requests es bekommen.

Requests hat gegenüber den Alternativen viele Vorteile, 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.


2015-12-30

Die Leute haben ihre Bewunderung für den Fortschrittsbalken zum Ausdruck gebracht.Es ist cool, klar.Mittlerweile gibt es 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 Implementierung, die @kvance vor 30 Monaten beschrieben hat.

import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
  output.write(mp3file.read())

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

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')
    

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')
    

Verwenden Sie das Wget-Modul:

import wget
wget.download('url')

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)

Schrieb wget Bibliothek in reinem Python nur für diesen Zweck.Es wird aufgepumpt urlretrieve mit die Merkmale ab Version 2.0.

Einfach und doch Python 2 & Python 3 Kompatibler Weg kommt mit six Bibliothek:

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

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, aber um die Antworten vollständiger zu machen, ist urllib ein einfacheres Modul, wenn Sie nur die Grundlagen wollen:

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 es auch aufrufen lesen() direkt:

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

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)

Notiz: urlopen Und urlretrieve haben sich beim Herunterladen großer Dateien (Größe > 500 MB) als relativ schlecht erwiesen. requests.get speichert die Datei im Speicher, bis der Download abgeschlossen ist.

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")

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)

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)

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

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

In Python3 können Sie die Bibliotheken urllib3 und Shutil verwenden.Laden Sie sie mit pip oder pip3 herunter (je nachdem, ob Python3 die Standardeinstellung 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 urllib3 aber nutzen urllib in Code

Wenn Ihnen Geschwindigkeit wichtig ist, habe ich einen kleinen Leistungstest für die Module durchgeführt urllib Und wget, und bezüglich wget Ich habe es einmal mit Statusleiste und einmal ohne versucht.Ich habe zum Testen drei verschiedene 500-MB-Dateien verwendet (verschiedene Dateien, um die Möglichkeit auszuschließen, dass unter der Haube etwas zwischengespeichert wird).Getestet auf einem Debian-Rechner mit Python2.

Dies sind zunächst die Ergebnisse (sie sind in verschiedenen Durchlä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
==============

Ich habe den Test mit dem „Profile“-Dekorator durchgeführt.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 am schnellsten zu sein

Der Vollständigkeit halber ist es auch möglich, jedes beliebige Programm zum Abrufen von Dateien mit dem aufzurufen subprocess Paket.Programme zum Abrufen von Dateien sind leistungsfähiger als vergleichbare Python-Funktionen urlretrieve.Zum Beispiel, wget kann Verzeichnisse rekursiv herunterladen (-R), kann mit FTP, Weiterleitungen und HTTP-Proxys umgehen und kann das erneute Herunterladen vorhandener Dateien vermeiden (-nc), Und aria2 kann Downloads über mehrere Verbindungen durchführen, was Ihre Downloads potenziell beschleunigen kann.

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

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

!wget -O example_output_file.html https://example.com

Quellcode kann sein:

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

Ich habe Folgendes geschrieben, was in Vanilla 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.
  • Der Download ist eine 4 MB große Test-.zip-Datei von meiner Website.

Sie können verwenden PycURL auf Python 2 und 3.

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

Das ist vielleicht etwas spät, aber ich habe den Code von pabloG gesehen und konnte nicht anders, als ein os.system('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 arbeiten, müssen Sie etwas anderes als „cls“ verwenden.Unter MAC OS X und Linux sollte es „klar“ sein.

urlretrieve und request.get sind einfach, die Realität jedoch nicht.Ich habe Daten für mehrere Websites abgerufen, einschließlich Text und Bildern. Die beiden oben genannten lösen wahrscheinlich die meisten Aufgaben.aber für eine universellere Lösung schlage ich die Verwendung von Urlopen vor.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 dass das Site-Paket vorinstalliert werden muss

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 Forbidden beim Herunterladen von Dateien über HTTP mit Python.Ich habe nur die Module „requests“ und „urllib“ ausprobiert. Das andere Modul bietet vielleicht etwas Besseres, aber mit diesem habe ich die meisten Probleme gelöst.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top