Download di un'immagine tramite urllib e python


184

Quindi sto provando a creare uno script Python che scarica i fumetti web e li mette in una cartella sul mio desktop. Ho trovato alcuni programmi simili qui che fanno qualcosa di simile, ma nulla di simile a ciò di cui ho bisogno. Quello che ho trovato più simile è proprio qui ( http://bytes.com/topic/python/answers/850927-problem-using-urllib-download-images ). Ho provato a usare questo codice:

>>> import urllib
>>> image = urllib.URLopener()
>>> image.retrieve("http://www.gunnerkrigg.com//comics/00000001.jpg","00000001.jpg")
('00000001.jpg', <httplib.HTTPMessage instance at 0x1457a80>)

Ho quindi cercato nel mio computer un file "00000001.jpg", ma tutto quello che ho trovato è stata la sua cache. Non sono nemmeno sicuro che abbia salvato il file sul mio computer. Una volta capito come scaricare il file, penso di sapere come gestire il resto. In sostanza, basta usare un ciclo for e dividere la stringa in "00000000". "Jpg" e incrementare "00000000" fino al numero più grande, che dovrei in qualche modo determinare. Qualche consiglio sul modo migliore per farlo o su come scaricare correttamente il file?

Grazie!

MODIFICA 15/06/10

Ecco lo script completato, salva i file in qualsiasi directory tu scelga. Per qualche strana ragione, i file non si stavano scaricando e lo hanno fatto. Qualche suggerimento su come ripulirlo sarebbe molto apprezzato. Attualmente sto cercando di scoprire come esistono molti fumetti sul sito in modo da poterne avere solo uno più recente, piuttosto che far uscire il programma dopo che sono state sollevate alcune eccezioni.

import urllib
import os

comicCounter=len(os.listdir('/file'))+1  # reads the number of files in the folder to start downloading at the next comic
errorCount=0

def download_comic(url,comicName):
    """
    download a comic in the form of

    url = http://www.example.com
    comicName = '00000000.jpg'
    """
    image=urllib.URLopener()
    image.retrieve(url,comicName)  # download comicName at URL

while comicCounter <= 1000:  # not the most elegant solution
    os.chdir('/file')  # set where files download to
        try:
        if comicCounter < 10:  # needed to break into 10^n segments because comic names are a set of zeros followed by a number
            comicNumber=str('0000000'+str(comicCounter))  # string containing the eight digit comic number
            comicName=str(comicNumber+".jpg")  # string containing the file name
            url=str("http://www.gunnerkrigg.com//comics/"+comicName)  # creates the URL for the comic
            comicCounter+=1  # increments the comic counter to go to the next comic, must be before the download in case the download raises an exception
            download_comic(url,comicName)  # uses the function defined above to download the comic
            print url
        if 10 <= comicCounter < 100:
            comicNumber=str('000000'+str(comicCounter))
            comicName=str(comicNumber+".jpg")
            url=str("http://www.gunnerkrigg.com//comics/"+comicName)
            comicCounter+=1
            download_comic(url,comicName)
            print url
        if 100 <= comicCounter < 1000:
            comicNumber=str('00000'+str(comicCounter))
            comicName=str(comicNumber+".jpg")
            url=str("http://www.gunnerkrigg.com//comics/"+comicName)
            comicCounter+=1
            download_comic(url,comicName)
            print url
        else:  # quit the program if any number outside this range shows up
            quit
    except IOError:  # urllib raises an IOError for a 404 error, when the comic doesn't exist
        errorCount+=1  # add one to the error count
        if errorCount>3:  # if more than three errors occur during downloading, quit the program
            break
        else:
            print str("comic"+ ' ' + str(comicCounter) + ' ' + "does not exist")  # otherwise say that the certain comic number doesn't exist
print "all comics are up to date"  # prints if all comics are downloaded

Ok, li ho tutti da scaricare! Ora sono bloccato con una soluzione molto inelegante per determinare quanti fumetti sono online ... Fondamentalmente sto eseguendo il programma su un numero che conosco sia sul numero di fumetti e quindi eseguo un'eccezione per venire fuori quando un fumetto non lo fa non esiste, e quando l'eccezione si presenta più di due volte (dal momento che non credo che mancheranno più di due fumetti) si chiude il programma, pensando che non ci sia altro da scaricare. Dal momento che non ho accesso al sito Web, esiste un modo migliore per determinare quanti file ci sono sul sito Web? Pubblicherò il mio codice tra un secondo.
Mike,

creativebe.com/icombiner/merge-jpg.html Ho usato quel programma per unire tutti i file .jpg in un PDF. Funziona alla grande ed è gratis!
Mike,

7
Valuta di pubblicare la soluzione come risposta e rimuoverla dalla domanda. I post delle domande sono per porre domande, post di risposta per risposte :-)
BartoszKP

perché questo è taggato con beautifulsoup? Questo post compare nell'elenco delle beautifulsoupdomande più
frequenti

1
@ P0W Ho rimosso il tag discusso.
kmonsoor,

Risposte:


252

Python 2

Utilizzando urllib.urlretrieve

import urllib
urllib.urlretrieve("http://www.gunnerkrigg.com//comics/00000001.jpg", "00000001.jpg")

Python 3

Utilizzando urllib.request.urlretrieve (parte dell'interfaccia legacy di Python 3, funziona esattamente allo stesso modo)

import urllib.request
urllib.request.urlretrieve("http://www.gunnerkrigg.com//comics/00000001.jpg", "00000001.jpg")

Sembra tagliare l'estensione del file per me quando viene passato come argomento (l'estensione è presente nell'URL originale). Qualche idea sul perché?
JeffThompson,

1
Sì, sì. Penso di aver assunto che se non fosse stata fornita alcuna estensione, sarebbe stata aggiunta l'estensione del file. In quel momento aveva senso per me, ma ora penso di capire cosa sta succedendo.
JeffThompson,

65
Nota per Python 3 dovresti importare [url.request] ( docs.python.org/3.0/library/… ):import urllib.request urllib.request.retrieve("http://...")
wasabigeek


18
Nota per Python 3 è in realtà import urllib.request urllib.request.urlretrieve("http://...jpg", "1.jpg"). E ' urlretrieveora come di 3.x.
user1032613

81
import urllib
f = open('00000001.jpg','wb')
f.write(urllib.urlopen('http://www.gunnerkrigg.com//comics/00000001.jpg').read())
f.close()

70

Solo per la cronaca, utilizzando la libreria delle richieste.

import requests
f = open('00000001.jpg','wb')
f.write(requests.get('http://www.gunnerkrigg.com//comics/00000001.jpg').content)
f.close()

Anche se dovrebbe verificare l'errore request.get ().


1
Anche se questa soluzione non utilizza urllib, potresti già utilizzare la libreria delle richieste già nel tuo script Python (era il mio caso durante la ricerca di questo), quindi potresti volerlo usare anche per ottenere le tue foto.
Iam Zesh,

Grazie per aver pubblicato questa risposta in cima alle altre. Ho finito per aver bisogno di intestazioni personalizzate per far funzionare il mio download e il puntatore alla libreria delle richieste ha abbreviato il processo di far funzionare tutto per me in modo considerevole.
kuzzooroo,

Non è nemmeno riuscito a far funzionare urllib in python3. Le richieste non hanno avuto problemi ed è già caricata! La scelta molto migliore credo.
user3023715,

@ user3023715 in python3 devi importare la richiesta da urllib vedi qui
Yassine Sedrani,

34

Per Python 3 dovrai importare import urllib.request:

import urllib.request 

urllib.request.urlretrieve(url, filename)

per maggiori informazioni consulta il link


15

Versione Python 3 della risposta di @ DiGMi:

from urllib import request
f = open('00000001.jpg', 'wb')
f.write(request.urlopen("http://www.gunnerkrigg.com/comics/00000001.jpg").read())
f.close()

10

Ho trovato questa risposta e la modifico in modo più affidabile

def download_photo(self, img_url, filename):
    try:
        image_on_web = urllib.urlopen(img_url)
        if image_on_web.headers.maintype == 'image':
            buf = image_on_web.read()
            path = os.getcwd() + DOWNLOADED_IMAGE_PATH
            file_path = "%s%s" % (path, filename)
            downloaded_image = file(file_path, "wb")
            downloaded_image.write(buf)
            downloaded_image.close()
            image_on_web.close()
        else:
            return False    
    except:
        return False
    return True

Da questo non otterrai mai altre risorse o eccezioni durante il download.


1
Dovresti rimuovere il "sé"
Euphe,

8

Se sai che i file si trovano nella stessa directory dirdel sito Web sitee hanno il seguente formato: nome_file_01.jpg, ..., nome_file_10.jpg quindi scaricali tutti:

import requests

for x in range(1, 10):
    str1 = 'filename_%2.2d.jpg' % (x)
    str2 = 'http://site/dir/filename_%2.2d.jpg' % (x)

    f = open(str1, 'wb')
    f.write(requests.get(str2).content)
    f.close()

7

È più semplice utilizzare solo .read()per leggere la risposta parziale o completa, quindi scriverla in un file che hai aperto in una buona posizione nota.


5

Forse hai bisogno di 'User-Agent':

import urllib2
opener = urllib2.build_opener()
opener.addheaders = [('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36')]
response = opener.open('http://google.com')
htmlData = response.read()
f = open('file.txt','w')
f.write(htmlData )
f.close()

Forse la pagina non è disponibile?
Alexander,


3

Tutti i codici sopra riportati non consentono di conservare il nome dell'immagine originale, che a volte è necessario. Ciò contribuirà a salvare le immagini sul disco locale, preservando il nome dell'immagine originale

    IMAGE = URL.rsplit('/',1)[1]
    urllib.urlretrieve(URL, IMAGE)

Prova questo per maggiori dettagli.


3

Questo ha funzionato per me usando Python 3.

Ottiene un elenco di URL dal file CSV e inizia a scaricarli in una cartella. Nel caso in cui il contenuto o l'immagine non esistano, prende quell'eccezione e continua a fare la sua magia.

import urllib.request
import csv
import os

errorCount=0

file_list = "/Users/$USER/Desktop/YOUR-FILE-TO-DOWNLOAD-IMAGES/image_{0}.jpg"

# CSV file must separate by commas
# urls.csv is set to your current working directory make sure your cd into or add the corresponding path
with open ('urls.csv') as images:
    images = csv.reader(images)
    img_count = 1
    print("Please Wait.. it will take some time")
    for image in images:
        try:
            urllib.request.urlretrieve(image[0],
            file_list.format(img_count))
            img_count += 1
        except IOError:
            errorCount+=1
            # Stop in case you reach 100 errors downloading images
            if errorCount>100:
                break
            else:
                print ("File does not exist")

print ("Done!")

2

Una soluzione più semplice potrebbe essere (python 3):

import urllib.request
import os
os.chdir("D:\\comic") #your path
i=1;
s="00000000"
while i<1000:
    try:
        urllib.request.urlretrieve("http://www.gunnerkrigg.com//comics/"+ s[:8-len(str(i))]+ str(i)+".jpg",str(i)+".jpg")
    except:
        print("not possible" + str(i))
    i+=1;

Fare attenzione all'utilizzo di un bare tranne quello, vedere stackoverflow.com/questions/54948548/… .
AMC

1

Che dire di questo:

import urllib, os

def from_url( url, filename = None ):
    '''Store the url content to filename'''
    if not filename:
        filename = os.path.basename( os.path.realpath(url) )

    req = urllib.request.Request( url )
    try:
        response = urllib.request.urlopen( req )
    except urllib.error.URLError as e:
        if hasattr( e, 'reason' ):
            print( 'Fail in reaching the server -> ', e.reason )
            return False
        elif hasattr( e, 'code' ):
            print( 'The server couldn\'t fulfill the request -> ', e.code )
            return False
    else:
        with open( filename, 'wb' ) as fo:
            fo.write( response.read() )
            print( 'Url saved as %s' % filename )
        return True

##

def main():
    test_url = 'http://cdn.sstatic.net/stackoverflow/img/favicon.ico'

    from_url( test_url )

if __name__ == '__main__':
    main()

0

Se hai bisogno del supporto proxy puoi farlo:

  if needProxy == False:
    returnCode, urlReturnResponse = urllib.urlretrieve( myUrl, fullJpegPathAndName )
  else:
    proxy_support = urllib2.ProxyHandler({"https":myHttpProxyAddress})
    opener = urllib2.build_opener(proxy_support)
    urllib2.install_opener(opener)
    urlReader = urllib2.urlopen( myUrl ).read() 
    with open( fullJpegPathAndName, "w" ) as f:
      f.write( urlReader )

0

Un altro modo per farlo è tramite la libreria fastai. Questo ha funzionato come un incanto per me. Stavo affrontando un SSL: CERTIFICATE_VERIFY_FAILED Errorutilizzo, urlretrievequindi l'ho provato.

url = 'https://www.linkdoesntexist.com/lennon.jpg'
fastai.core.download_url(url,'image1.jpg', show_progress=False)

Stavo affrontando un SSL: CERTIFICATE_VERIFY_FAILED Errore stackoverflow.com/questions/27835619/…
AMC

0

Utilizzando le richieste

import requests
import shutil,os

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
currentDir = os.getcwd()
path = os.path.join(currentDir,'Images')#saving images to Images folder

def ImageDl(url):
    attempts = 0
    while attempts < 5:#retry 5 times
        try:
            filename = url.split('/')[-1]
            r = requests.get(url,headers=headers,stream=True,timeout=5)
            if r.status_code == 200:
                with open(os.path.join(path,filename),'wb') as f:
                    r.raw.decode_content = True
                    shutil.copyfileobj(r.raw,f)
            print(filename)
            break
        except Exception as e:
            attempts+=1
            print(e)

if __name__ == '__main__':
    ImageDl(url)

0

Usando urllib, puoi farlo immediatamente.

import urllib.request

opener=urllib.request.build_opener()
opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')]
urllib.request.install_opener(opener)

urllib.request.urlretrieve(URL, "images/0.jpg")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.