Téléchargement d'une image via urllib et python


184

J'essaie donc de créer un script Python qui télécharge des webcomics et les place dans un dossier sur mon bureau. J'ai trouvé ici quelques programmes similaires qui font quelque chose de similaire, mais rien de tout à fait ce dont j'ai besoin. Celui que j'ai trouvé le plus similaire est ici ( http://bytes.com/topic/python/answers/850927-problem-using-urllib-download-images ). J'ai essayé d'utiliser ce code:

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

J'ai ensuite cherché sur mon ordinateur un fichier "00000001.jpg", mais je n'ai trouvé que l'image en cache. Je ne suis même pas sûr qu'il ait enregistré le fichier sur mon ordinateur. Une fois que j'ai compris comment télécharger le fichier, je pense que je sais comment gérer le reste. Essentiellement, utilisez simplement une boucle for et divisez la chaîne au "00000000". "Jpg" et incrémentez le "00000000" jusqu'au plus grand nombre, que je devrais en quelque sorte déterminer. Des recommandations sur la meilleure façon de procéder ou comment télécharger le fichier correctement?

Merci!

MODIFIER 15/06/10

Voici le script terminé, il enregistre les fichiers dans le répertoire de votre choix. Pour une raison étrange, les fichiers n'étaient pas téléchargés et ils l'ont juste fait. Toute suggestion sur la façon de le nettoyer serait très appréciée. Je travaille actuellement sur la façon de découvrir que de nombreuses bandes dessinées existent sur le site afin que je puisse obtenir uniquement la dernière, plutôt que de laisser le programme se fermer après un certain nombre d'exceptions.

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, je les ai tous à télécharger! Maintenant, je suis coincé avec une solution très inélégante pour déterminer combien de bandes dessinées sont en ligne ... J'exécute essentiellement le programme vers un nombre dont je sais qu'il dépasse le nombre de bandes dessinées, puis j'exécute une exception à venir lorsqu'une bande dessinée ne le fait pas 'n'existe pas, et quand l'exception apparaît plus de deux fois (puisque je ne pense pas qu'il manquera plus de deux bandes dessinées), il quitte le programme, pensant qu'il n'y en a plus à télécharger. Étant donné que je n'ai pas accès au site Web, y a-t-il un meilleur moyen de déterminer le nombre de fichiers qu'il y a sur le site Web? Je posterai mon code dans une seconde.
Mike

creativebe.com/icombiner/merge-jpg.html J'ai utilisé ce programme pour fusionner tous les fichiers .jpg en un seul PDF. Fonctionne à merveille et c'est gratuit!
Mike

7
Pensez à publier votre solution en tant que réponse et à la supprimer de la question. Les messages de questions sont pour poser des questions, répondre aux messages pour les réponses :-)
BartoszKP

pourquoi est-ce étiqueté beautifulsoup? Ce message apparaît dans la liste des principales beautifulsoupquestions
P0W

1
@ P0W J'ai supprimé la balise discutée.
kmonsoor

Réponses:


252

Python 2

Utilisation de urllib.urlretrieve

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

Python 3

Utiliser urllib.request.urlretrieve (qui fait partie de l'ancienne interface de Python 3, fonctionne exactement de la même manière)

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

Il semble me couper l'extension de fichier lorsqu'elle est passée en argument (l'extension est présente dans l'URL d'origine). Une idée pourquoi?
JeffThompson

1
Le vôtre, oui. Je pense que j'ai supposé que si aucune extension de fichier n'était donnée, l'extension du fichier serait ajoutée. Cela avait du sens pour moi à l'époque, mais je pense que maintenant je comprends ce qui se passe.
JeffThompson

65
Remarque pour Python 3, vous devrez importer [url.request] ( docs.python.org/3.0/library/… ):import urllib.request urllib.request.retrieve("http://...")
wasabigeek

1
Notez que la liste des documents Python 3 retrieve () dans le cadre d'une "Legacy Interface" et dites qu'elle pourrait devenir obsolète à l'avenir.
Nathan Wailes

18
Remarque pour Python 3, c'est en fait import urllib.request urllib.request.urlretrieve("http://...jpg", "1.jpg"). C'est urlretrievemaintenant à partir de 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

Juste pour mémoire, en utilisant la bibliothèque de requêtes.

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

Bien qu'il devrait vérifier l'erreur requests.get ().


1
Même si cette solution n'utilise pas urllib, vous utilisez peut-être déjà la bibliothèque de requêtes déjà dans votre script python (c'était mon cas lors de la recherche de cela), vous voudrez peut-être l'utiliser également pour obtenir vos images.
Iam Zesh

Merci d'avoir posté cette réponse au-dessus des autres. J'ai fini par avoir besoin d'en-têtes personnalisés pour que mon téléchargement fonctionne, et le pointeur vers la bibliothèque de requêtes a considérablement raccourci le processus pour que tout fonctionne pour moi.
kuzzooroo

Impossible de faire fonctionner urllib en python3. Les demandes n'avaient aucun problème et il est déjà chargé! Le bien meilleur choix que je pense.
user3023715

@ user3023715 en python3, vous devez importer la demande d'urllib voir ici
Yassine Sedrani

34

Pour Python 3, vous devrez importer import urllib.request :

import urllib.request 

urllib.request.urlretrieve(url, filename)

pour plus d'informations, consultez le lien


15

Version Python 3 de la réponse de @ 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

J'ai trouvé cette réponse et je la modifie de manière plus fiable

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

De cela, vous n'obtenez jamais d'autres ressources ou exceptions lors du téléchargement.


1
Vous devriez supprimer le `` soi ''
Euphe

8

Si vous savez que les fichiers se trouvent dans le même répertoire dirdu site Web siteet ont le format suivant: filename_01.jpg, ..., filename_10.jpg alors téléchargez-les tous:

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

Il est plus simple de simplement .read()lire la réponse partielle ou entière, puis de l'écrire dans un fichier que vous avez ouvert dans un bon emplacement connu.


5

Peut-être avez-vous besoin de '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()

Peut-être que la page n'est pas disponible?
Alexander


3

Tous les codes ci-dessus, ne permettent pas de conserver le nom de l'image d'origine, ce qui est parfois obligatoire. Cela aidera à enregistrer les images sur votre lecteur local, en préservant le nom de l'image d'origine

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

Essayez ceci pour plus de détails.


3

Cela a fonctionné pour moi en utilisant python 3.

Il obtient une liste d'URL à partir du fichier csv et commence à les télécharger dans un dossier. Au cas où le contenu ou l'image n'existerait pas, il prend cette exception et continue à faire sa magie.

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

Une solution plus simple peut être (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;

Soyez prudent lorsque vous utilisez un bare sauf comme ça, voir stackoverflow.com/questions/54948548/… .
AMC

1

Et ça:

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

Si vous avez besoin d'un support proxy, vous pouvez le faire:

  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

Une autre façon de faire est via la bibliothèque fastai. Cela a fonctionné comme un charme pour moi. J'étais confronté à une SSL: CERTIFICATE_VERIFY_FAILED Errorutilisation urlretrievealors j'ai essayé ça.

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

Je faisais face à un SSL: Erreur CERTIFICATE_VERIFY_FAILED stackoverflow.com/questions/27835619/…
AMC

0

Utilisation des demandes

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

En utilisant urllib, vous pouvez le faire instantanément.

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")
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.