Hvordan kan jeg laste ned en fil over HTTP bruke Python?

stemmer
698

Jeg har et lite verktøy som jeg bruker til å laste ned en MP3 fra en nettside på en tidsplan og bygger deretter / oppdaterer en podcast XML-fil som jeg har åpenbart lagt til iTunes.

Teksten behandling som skaper / oppdaterer XML-filen er skrevet i Python. Jeg bruker wget i en Windows .bat-fil for å laste ned selve MP3 imidlertid. Jeg foretrekker å ha hele verktøyet skrevet i Python skjønt.

Jeg kjempet om å finne en måte å faktisk ned laste ned filen i Python, og dermed hvorfor jeg tydd til wget.

Så, hvordan kan jeg laste ned filen ved hjelp av Python?

Publisert på 22/08/2008 klokken 15:34
kilden bruker
På andre språk...                            


22 svar

stemmer
953

One more, ved hjelp av urlretrieve:

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

(For Python 3+ bruke 'import urllib.request' og urllib.request.urlretrieve)

Enda en, med en "progressbar"

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()
Svarte 22/08/2008 kl. 16:19
kilden bruker

stemmer
389

I Python 2, bruke urllib2 som leveres med standard bibliotek.

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

Dette er den mest grunnleggende måten å bruke biblioteket, minus eventuelle feilbehandling. Du kan også gjøre mer komplekse ting som endrer overskrifter. Dokumentasjonen kan bli funnet her.

Svarte 22/08/2008 kl. 15:38
kilden bruker

stemmer
299

I 2012 bruker python forespørsler bibliotek

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

Du kan kjøre pip install requestsfor å få det.

Forespørsler har mange fordeler fremfor alternativene fordi API er mye enklere. Dette gjelder spesielt hvis du trenger å gjøre godkjenning. urllib og urllib2 er ganske unintuitive og smertefull i dette tilfellet.


2015-12-30

Folk har uttrykt beundring for fremdriftslinjen. Det er kult, sikkert. Det er flere off-the-sokkel løsninger nå, inkludert 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)

Dette er egentlig gjennomføringen @kvance beskrevet 30 måneder siden.

Svarte 24/05/2012 kl. 20:08
kilden bruker

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

Den wbi open('test.mp3','wb')åpner en fil (og sletter alle eksisterende fil) i binær modus slik at du kan lagre data med det i stedet for bare tekst.

Svarte 22/08/2008 kl. 15:58
kilden bruker

stemmer
67

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

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

    import urllib
    urllib.urlretrieve('http://www.example.com/songs/mp3.mp3', 'mp3.mp3')
    
Svarte 06/08/2015 kl. 13:30
kilden bruker

stemmer
18

En forbedret versjon av PabloG koden for 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)
Svarte 13/05/2013 kl. 08:59
kilden bruker

stemmer
16

bruke wget modul:

import wget
wget.download('url')
Svarte 25/03/2015 kl. 12:59
kilden bruker

stemmer
16

Skrev wget bibliotek i ren Python nettopp for dette formålet. Det pumpes opp urlretrievemed disse funksjonene fra versjon 2.0.

Svarte 25/09/2013 kl. 17:55
kilden bruker

stemmer
12

Jeg er enig med Corey, urllib2 er mer komplett enn urllib og bør trolig være modulen brukes hvis du ønsker å gjøre mer komplekse ting, men for å gjøre svarene mer komplett, urllib er en enklere modul hvis du vil bare grunnleggende:

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

Vil fungere fint. Eller, hvis du ikke ønsker å forholde seg til "svar" objekt du kan ringe lese () direkte:

import urllib
mp3 = urllib.urlopen('http://www.example.com/sound.mp3').read()
Svarte 22/08/2008 kl. 15:58
kilden bruker

stemmer
11

Følgende er de mest brukte samtaler for å laste ned filer i python:

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

  2. urllib2.urlopen('url_to_file')

  3. requests.get(url)

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

Merk: urlopenog urlretrieveer funnet å utføre relativt dårlig med nedlasting av store filer (størrelse> 500 MB). requests.getlagrer filen i minnet før nedlastingen er fullført.

Svarte 19/09/2016 kl. 12:45
kilden bruker

stemmer
10

Enkel, men Python 2 & Python 3kompatibel måte kommer med sixbibliotek:

from six.moves import urllib
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
Svarte 22/06/2017 kl. 07:59
kilden bruker

stemmer
6
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")
Svarte 05/11/2018 kl. 11:28
kilden bruker

stemmer
6

Du kan få fremgang tilbakemelding urlretrieve også:

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)
Svarte 26/01/2014 kl. 13:12
kilden bruker

stemmer
5

Hvis du wget har installert, kan du bruke parallel_sync.

PIP installere 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

Dette er ganske kraftig. Den kan laste ned filer i parallell, prøve på nytt ved svikt, og det kan til og med laste ned filer på en ekstern maskin.

Svarte 19/11/2015 kl. 23:48
kilden bruker

stemmer
3

I python3 kan du bruke urllib3 og shutil libraires. Last dem ned ved hjelp av pip eller PIP3 (Avhengig av om python3 er standard eller ikke)

pip3 install urllib3 shutil

Deretter kjører denne koden

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)

Merk at du laster ned urllib3, men bruker urllibi kode

Svarte 08/02/2018 kl. 17:30
kilden bruker

stemmer
3

Hvis hastigheten er viktig for deg, gjorde jeg en liten ytelsestest for modulene urllibog wget, og om wgetjeg prøvde en gang med statuslinje og en gang uten. Jeg tok tre forskjellige 500 MB filer for å teste med (forskjellige filer-å eliminere sjansen for at det er noen caching skjer under panseret). Testet på debian maskin, med python2.

Først er det disse resultatene (de er like i forskjellige løyper):

$ 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
==============

Slik jeg utførte testen er å bruke "profil" dekoratør. Dette er den fullstendige kode:

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 synes å være den raskeste

Svarte 03/11/2017 kl. 14:25
kilden bruker

stemmer
2

Kildekoden kan være:

import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()                            
sock.close()                                        
print htmlSource  
Svarte 26/11/2013 kl. 13:21
kilden bruker

stemmer
1

Jeg skrev følgende, som arbeider i vanilje Python to eller Python tre.


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

Merknader:

  • Støtter en "progress bar" tilbakeringing.
  • Nedlastingen er en 4 MB test .zip fra min nettside.
Svarte 13/05/2017 kl. 21:33
kilden bruker

stemmer
0

Bare for fullstendighetens skyld, er det også mulig å ringe hvilket som helst program for å hente filer ved hjelp av subprocesspakken. Programmer dedikert for å hente filer er kraftigere enn Python funksjoner som urlretrievef.eks wgetkan laste ned kataloger rekursivt ( -R), kan håndtere FTP, omdirigeringer, HTTP proxyer, kan unngå re-laste ned eksisterende filer ( -nc), og aria2kan Parallell nedlastinger.

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

I Jupyter bærbare, kan man også ringe programmer direkte med !syntaks:

!wget -O example_output_file.html https://example.com
Svarte 29/08/2018 kl. 12:24
kilden bruker

stemmer
0

hvorfor ikke bruke pycurl, innbygget modul på Py2 & 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()
Svarte 08/08/2018 kl. 03:51
kilden bruker

stemmer
0

urlretrieve og requests.get er enkel, men realiteten ikke. Jeg har hentet data for par nettsteder, inkludert tekst og bilder, de to ovennevnte trolig løse de fleste oppgaver. men for en mer universell løsning jeg foreslå bruk av urlopen. Som det er inkludert i Python tre standard bibliotek, kan koden kjøres på hvilken som helst maskin som kjører Python tre uten pre-installere site-nivå

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

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

Dette svaret gir en løsning på HTTP 403 Forbidden når du laster ned filen over http bruke Python. Jeg har prøvd bare forespørsler og urllib moduler, den andre modulen kan gi noe bedre, men dette er den jeg brukte til å løse de fleste problemer.

Svarte 13/03/2017 kl. 13:12
kilden bruker

stemmer
0

Dette kan være litt sent, men jeg så pabloG kode og kunne ikke hjelpe å legge en os.system ( 'CLS') for å gjøre det ser utrolig! Sjekk det ut :

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

Hvis du kjører i et annet miljø enn Windows, må du bruke noe annet så 'CLS'. I Mac OS X og Linux bør det være 'klar'.

Svarte 14/10/2013 kl. 02:54
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more