Cum se descarcă un fișier prin HTTP? (Programare, Python, Http, Urllib)

Owen a intrebat.

Am un mic utilitar pe care îl folosesc pentru a descărca un fișier MP3 de pe un site web la un program și apoi construiește/actualizează un fișier XML de podcast pe care l-am adăugat la iTunes.

Procesarea textului care creează/actualizează fișierul XML este scrisă în Python. Cu toate acestea, folosesc wget în interiorul unui Windows .bat pentru a descărca fișierul MP3 propriu-zis. Aș prefera ca întregul utilitar să fie scris în Python.

M-am străduit să găsesc o modalitate de a descărca efectiv fișierul în Python, motiv pentru care am recurs la utilizarea lui wget.

Așadar, cum pot descărca fișierul folosind Python?

Comentarii

  • Vedeți și: Cum să salvez local o imagine folosind Python a cărei adresă URL o știu deja? –  > Por Martin Thoma.
  • Multe dintre răspunsurile de mai jos nu reprezintă un înlocuitor satisfăcător pentru wget. Printre altele, wget (1) păstrează marcajele de timp (2) determină automat numele de fișier din url, adăugând .1 (etc.) dacă fișierul există deja (3) are multe alte opțiuni, dintre care unele pe care este posibil să le fi pus în .wgetrc. Dacă doriți oricare dintre acestea, trebuie să le implementați singur în Python, dar este mai simplu să apelați doar la wget din Python. –  > Por ShreevatsaR.
  • Soluție scurtă pentru Python 3: import urllib.request; s = urllib.request.urlopen('http://example.com/').read().decode() –  > Por Basj.
25 răspunsuri
Corey

Utilizați urllib.request.urlopen():

import urllib.request
with urllib.request.urlopen('http://www.example.com/') as f:
    html = f.read().decode('utf-8')

Acesta este cel mai simplu mod de utilizare a bibliotecii, mai puțin gestionarea erorilor. De asemenea, puteți face lucruri mai complexe, cum ar fi schimbarea antetelor.

Pe Python 2, metoda se află în urllib2:

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

Comentarii

  • Aceasta nu va funcționa dacă există spații în adresa URL pe care o furnizați. În acest caz, va trebui să analizați url-ul și să codificați calea. –  > Por Jason Sundram.
  • 98

  • Iată soluția pentru Python 3: stackoverflow.com/questions/7243750/… –  > Por tommy.carstensen.
  • Doar pentru referință. Modul de a codifica calea prin url este urllib2.quote –  > Por André Puel.
  • @JasonSundram: Dacă există spații în ea, nu este un URI. –  > Por Zaz.
  • Acest lucru nu funcționează pe ferestre cu fișiere mai mari. Trebuie să citiți toate blocurile! –  > Por Avia.
PabloG

Încă una, folosind urlretrieve:

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

(pentru Python 3+ folosiți import urllib.request și urllib.request.urlretrieve)

Încă una, cu o „bară de progres”

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

Comentarii

  • În mod ciudat, aceasta a funcționat pentru mine pe Windows, când metoda urllib2 nu a funcționat. Metoda urllib2 a funcționat însă pe Mac. –  > Por InFreefall.
  • Bug: file_size_dl += block_sz ar trebui să fie += len(buffer), deoarece ultima citire nu este adesea un block_sz complet. De asemenea, pe Windows trebuie să deschideți fișierul de ieșire ca „wb” dacă nu este un fișier text. –  > Por Vinete Jeff.
  • Nici eu urllib și urllib2 nu au funcționat, dar urlretrieve a funcționat bine, devenisem frustrat – mulțumesc 🙂 –  > Por funk-shun.
  • Înfășurați întregul lucru (cu excepția definiției lui file_name) cu if not os.path.isfile(file_name): pentru a evita suprascrierea podcasturilor! util atunci când îl rulează ca un cronjob cu urlele găsite într-un fișier .html –  > Por Sriram Murali.
  • Conform documentației, urllib.request.urlretrieve este o „interfață moștenită” și „ar putea deveni depășită în viitor”. docs.python.org/3/library/urllib.request.html#legacy-interface –  > Por Louis Yang.
hughdbrown

În 2012, utilizați biblioteca python requests

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

Puteți rula pip install requests pentru a o obține.

Requests are multe avantaje față de alternative, deoarece API-ul este mult mai simplu. Acest lucru este valabil mai ales dacă trebuie să faceți autentificare. urllib și urllib2 sunt destul de neintuitive și dureroase în acest caz.


2015-12-30

Oamenii și-au exprimat admirația pentru bara de progres. Este mișto, sigur. Există acum mai multe soluții din comerț, inclusiv 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)

Aceasta este, în esență, implementarea descrisă de @kvance acum 30 de luni.

Comentarii

  • Cum se descurcă acest lucru cu fișierele mari, totul este stocat în memorie sau poate fi scris într-un fișier fără a necesita o memorie mare? –  > Por bibstha.
  • Este posibilă transmiterea în flux a fișierelor mari prin setarea stream=True în cerere. Apoi puteți apela iter_content() pe răspuns pentru a citi câte o bucată pe rând. –  > Por kvance.
  • De ce ar trebui ca o bibliotecă url să aibă o facilitate de descompunere a fișierelor? Citiți fișierul din url, salvați-l și apoi descompuneți-l în orice mod vă place. De asemenea, un fișier zip nu este un „folder”, așa cum apare în Windows, ci un fișier. –  > Por Harel.
  • @Ali: r.text: Pentru text sau conținut unicode. Se returnează ca unicode. r.content: Pentru conținut binar. Se returnează ca octeți. Citiți despre aceasta aici: docs.python-requests.org/en/latest/user/quickstart –  > Por hughdbrown.
  • Cred că un chunk_size argument este de dorit împreună cu stream=True. Valoarea implicită chunk_size este 1, , ceea ce înseamnă că fiecare bucată poate fi la fel de mică ca 1 byte și, prin urmare, este foarte ineficient. –  > Por haridsv.
Grant
import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
  output.write(mp3file.read())

Site-ul wb în open('test.mp3','wb') deschide un fișier (și șterge orice fișier existent) în modul binar, astfel încât să puteți salva date cu el în loc de doar text.

Comentarii

    31

  • Dezavantajul acestei soluții este, că întregul fișier este încărcat în ram înainte de a fi salvat pe disc, doar ceva de care trebuie să țineți cont dacă folosiți acest lucru pentru fișiere mari pe un sistem mic, cum ar fi un router cu ram limitată. –  > Por tripplet.
  • @tripplet deci cum am putea rezolva asta? –  > Por Lucas Henrique.
  • Pentru a evita citirea întregului fișier în memorie, încercați să treceți un argument pentru file.read care reprezintă numărul de octeți care trebuie citiți. A se vedea: gist.github.com/hughdbrown/c145b8385a2afa6570e2 –  > Por hughdbrown.
  • @hughdbrown Mi s-a părut util scriptul tău, dar am o întrebare: pot folosi fișierul pentru post-procesare? să presupunem că descarc un fișier jpg pe care vreau să îl procesez cu OpenCV, pot folosi variabila „data” pentru a continua să lucrez sau trebuie să o citesc din nou din fișierul descărcat? –  > Por Rodrigo E. Principe.
  • Utilizați shutil.copyfileobj(mp3file, output) în schimb. –  > Por Aurélien Ooms.
bmaupin

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

    Notă: În conformitate cu documentația, urllib.request.urlretrieve este o „interfață moștenită” și „ar putea deveni depășită în viitor” (mulțumiri gerrit)

Python 2

  • urllib2.urlopen (mulțumiri Corey)

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

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

Comentarii

  • Cu siguranță a durat ceva timp, dar iată că, în sfârșit, există api-ul simplu și direct pe care îl aștept de la un stdlib python 🙂 –  > Por ThorSummoner.
  • Un răspuns foarte frumos pentru python3, vezi și docs.python.org/3/library/… –  > Por Edouard Thiel.
  • @EdouardThiel Dacă faceți clic pe urllib.request.urlretrieve de mai sus, vă va duce la acel link exact. Noroc! –  > Por bmaupin.
  • urllib.request.urlretrieve este documentată ca fiind o „interfață moștenită” și „ar putea deveni depășită în viitor”. –  > Por gerrit.
  • Ar trebui să menționați că primiți o mulțime de octeți care trebuie gestionați după aceea. –  > Por thoroc.
Sara Santana

folosiți modulul wget:

import wget
wget.download('url')

Comentarii

  • Se pare că repo-ul a fost eliminat. –  > Por Bahman Eslami.
  • proiectul a fost mutat pe github, dar apoi a fost arhivat de către autorul său –  > Por Alleo.
H S Umer farooq
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")

Comentarii

  • Mulțumesc, de asemenea, înlocuiți with open(file_name,... cu with open('thisname'...) pentru că s-ar putea să apară o eroare –  > Por Anindya Prithvi.
Stan

O versiune îmbunătățită a codului PabloG pentru 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)

Comentarii

  • Aș elimina parantezele de pe prima linie, deoarece nu este o caracteristică prea veche. –  > Por Arpad Horvath.
Akif

Simplu, dar totuși Python 2 & Python 3 compatibil vine cu six bibliotecă:

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

Comentarii

  • Acesta este cel mai bun mod de a face acest lucru pentru compatibilitatea 2+3. –  > Por Fush.
anatoly techtonik

A scris wget în Python pur doar pentru acest scop. Este pompat urlretrieve cu aceste caracteristici începând cu versiunea 2.0.

Comentarii

  • Nu există opțiunea de a salva cu nume de fișier personalizat ? –  > Por Alex.
  • @Alex a adăugat opțiunea -o FILENAME la versiunea 2.1 –  > Por anatoly techtonik.
  • Bara de progres nu apare atunci când folosesc acest modul sub Cygwin. –  > Por Joe Coder.
  • Ar trebui să schimbați din -o la -O pentru a evita confuzia, așa cum este în GNU wget. Sau cel puțin ambele opțiuni ar trebui să fie valabile. –  > Por erik.
  • @eric Nu sunt sigur că vreau să fac ca wget.py un înlocuitor în loc pentru real wget. The -o se comportă deja diferit – este compatibil cu curl în acest mod. O notă în documentație ar ajuta la rezolvarea problemei? Sau este caracteristica esențială pentru un utilitar cu un astfel de nume să fie compatibil cu linia de comandă? –  > Por anatoly techtonik.
Jaydev

Următoarele sunt cele mai frecvent utilizate apeluri pentru descărcarea fișierelor în 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)

Notă: urlopen și urlretrieve se pare că se comportă relativ prost la descărcarea fișierelor mari (dimensiune > 500 MB). requests.get stochează fișierul în memorie până la finalizarea descărcării.

akdom

Sunt de acord cu Corey, urllib2 este mai complet decât urllib și ar trebui să fie probabil modulul utilizat dacă doriți să faceți lucruri mai complexe, dar pentru a face răspunsurile mai complete, urllib este un modul mai simplu dacă doriți doar elementele de bază:

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

Va funcționa bine. Sau, dacă nu doriți să aveți de-a face cu obiectul „răspuns”, puteți apela la read() direct:

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

Apoorv Agarwal

În python3 puteți utiliza urllib3 și shutil libraires.Download-le folosind pip sau pip3 (în funcție de faptul dacă python3 este implicit sau nu)

pip3 install urllib3 shutil

Apoi rulați acest cod

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)

Rețineți că descărcați urllib3 dar folosiți urllib în cod

max

Dacă aveți wget instalat, puteți folosi parallel_sync.

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

Acest lucru este destul de puternic. Poate descărca fișiere în paralel, poate încerca din nou în caz de eșec și poate chiar descărca fișiere de pe o mașină de la distanță.

Comentarii

  • Rețineți că este numai pentru Linux –  > Por jjjj.
Marcin Cuprjak

Puteți obține feedback-ul de progres cu urlretrieve, de asemenea:

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

def downloadFile(url):
    print "
",url
    fname = url.split('/')[-1]
    print fname
    urllib.urlretrieve(url, fname, report)

Omer Dagan

Dacă viteza contează pentru dumneavoastră, am făcut un mic test de performanță pentru modulele urllib și wget, , iar în ceea ce privește wget Am încercat o dată cu bara de stare și o dată fără. Am luat trei fișiere diferite de 500 MB pentru a testa (fișiere diferite- pentru a elimina șansa ca sub capotă să se întâmple ceva caching). Am testat pe o mașină debian, cu python2.

În primul rând, acestea sunt rezultatele (sunt similare în diferite rulări):

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

Modul în care am efectuat testul este folosind decoratorul „profile”. Acesta este codul complet:

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 pare a fi cel mai rapid

Comentarii

  • Trebuie să fie ceva complet oribil care se întâmplă sub capotă pentru ca bara să crească timpul atât de mult. –  > Por Alistair Carscadden.
Robin Dinse

Doar de dragul completitudinii, este de asemenea posibil să apelați orice program de recuperare a fișierelor folosind funcția subprocess pachet. Programele dedicate recuperării fișierelor sunt mai puternice decât funcțiile Python precum urlretrieve. De exemplu, wget poate descărca directoare în mod recursiv (-R), se poate ocupa de FTP, redirecționări, proxy-uri HTTP, poate evita reîncărcarea fișierelor existente (-nc), și aria2 poate efectua descărcări cu mai multe conexiuni, ceea ce poate accelera descărcările.

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

În Jupyter Notebook, se pot, de asemenea, apela programe direct cu ajutorul funcției ! sintaxa:

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

Zuko

Codul sursă poate fi:

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

imallett

Am scris următoarele, care funcționează în vanilla Python 2 sau Python 3.


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

Note:

  • Suportă un callback „progress bar”.
  • Descărcarea este un .zip de test de 4 MB de pe site-ul meu.

Comentarii

  • funcționează foarte bine, rulat prin jupyter a obținut ceea ce am vrut 🙂 –  > Por Samir Ouldsaadi.
gzerone

Puteți utiliza PycURL pe Python 2 și 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()

JD3

Poate că este puțin cam târziu, dar am văzut codul lui pabloG și nu m-am putut abține să nu adaug un os.system(‘cls’) pentru a face să arate INCREDIBIL! Check it out :

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

Dacă rulați într-un alt mediu decât Windows, va trebui să folosiți altceva decât ‘cls’. În MAC OS X și Linux ar trebui să fie ‘clear’.

Comentarii

  • cls nu face nimic pe OS X și nici pe un server Ubuntu al meu. Niște clarificări ar fi bune. –  > Por kqw.
  • Cred că ar trebui să folosiți clear pentru linux, sau chiar mai bine să înlocuiți linia de imprimare în loc să ștergeți întreaga ieșire a liniei de comandă. –  > Por Arijoon.
  • acest răspuns doar copiază un alt răspuns și adaugă un apel la o funcție depreciată (os.system()) care lansează un subproces pentru a șterge ecranul folosind o comandă specifică platformei (cls). Cum are acest lucru orice Upvotes?? Un „răspuns” complet inutil, IMHO. –  > Por Corey Goldberg.
Sphynx-HenryAY

urlretrieve și requests.get sunt simple, însă realitatea nu. am preluat date pentru câteva site-uri, inclusiv text și imagini, cele două de mai sus rezolvă probabil majoritatea sarcinilor. dar pentru o soluție mai universală sugerez utilizarea urlopen. Deoarece este inclus în biblioteca standard Python 3, codul dvs. ar putea rula pe orice mașină care rulează Python 3, fără a preinstala site-package.

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

Acest răspuns oferă o soluție pentru HTTP 403 Forbidden atunci când descărcați un fișier prin http folosind Python. Am încercat doar modulele requests și urllib, este posibil ca celălalt modul să ofere ceva mai bun, dar acesta este cel pe care l-am folosit pentru a rezolva majoritatea problemelor.

Pedro Lobito

Răspuns târziu, dar pentru python>=3.6 puteți utiliza:

import dload
dload.save(url)

Instalați dload cu:

pip3 install dload

Comentarii

  • Pot să întreb – unde se salvează fișierul după ce programul rulează? De asemenea, există o modalitate de a-l numi și de a-l salva într-o anumită locație? Acesta este linkul cu care lucrez – atunci când faceți clic pe link, acesta descarcă imediat un fișier Excel: ons.gov.uk/generator?format=xls&uri=/economy/… –  > Por Joshua Tinashe.
  • Puteți furniza locația de salvare ca al doilea argument, de ex: dload.save(url, "/home/user/test.xls") –  > Por Pedro Lobito.
gibbone

Am vrut să descarc toate fișierele de pe o pagină web. Am încercat wget dar nu reușea, așa că m-am decis pentru ruta Python și am găsit acest fir de discuție.

După ce l-am citit, am făcut o mică aplicație în linie de comandă, soupget, , dezvoltând răspunsurile excelente ale lui PabloG și Stan și adăugând câteva opțiuni utile.

Aceasta utilizează BeatifulSoup pentru a colecta toate URL-urile paginii și apoi le descarcă pe cele cu extensia (extensiile) dorită (dorite). În cele din urmă, poate descărca mai multe fișiere în paralel.

Iată-l aici:

#!/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)

Un exemplu de utilizare a acestuia este:

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

Și un exemplu real, dacă doriți să îl vedeți în acțiune:

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

firebfm

O altă modalitate este de a apela un proces extern, cum ar fi curl.exe. Curl afișează în mod implicit o bară de progres, viteza medie de descărcare, timpul rămas și multe altele, toate formatate frumos într-un tabel.Puneți curl.exe în același director cu scriptul dvs.

from subprocess import call
url = ""
call(["curl", {url}, '--output', "song.mp3"])

Notă: Nu puteți specifica o cale de ieșire cu curl, așa că faceți un os.rename după aceea