web-dev-qa-db-fra.com

Comment ouvrir une image depuis Internet dans PIL?

Je voudrais retrouver les dimensions d'une image sur internet. J'ai essayé d'utiliser

from PIL import Image
import urllib2 as urllib
fd = urllib.urlopen("http://a/b/c")
im = Image.open(fd)
im.size

comme suggéré dans cette réponse , mais je reçois le message d'erreur

addinfourl instance has no attribute 'seek'

J'ai vérifié et les objets retournés par urllib2.urlopen(url) ne semblent pas avoir de méthode de recherche selon dir.

Alors, que dois-je faire pour pouvoir charger une image d'Internet dans PIL?

25
murgatroid99

Vous pourriez envisager d'utiliser io.BytesIO pour compatibilité ascendante .
Les modules StringIO et cStringIO n'existent pas dans Python 3.

from PIL import Image
import urllib2 as urllib
import io

fd = urllib.urlopen("http://a/b/c")
image_file = io.BytesIO(fd.read())
im = Image.open(image_file)
36
Snakes and Coffee

En utilisant votre même exemple, utilisez simplement StringIO pour envelopper le tampon dans un objet de type fichier approprié:

from PIL import Image
import urllib2 as urllib
from StringIO import StringIO

fd = urllib.urlopen("http://a/b/c")
im = Image.open(StringIO(fd.read()))
im.size
8
jdi

Utilisation de Python requests:

from PIL import Image
from StringIO import StringIO
import requests

r = requests.get("http://a/b/c")
im = Image.open(StringIO(r.content))
im.size
8
Matt Parrilla

Cette pull-request ajoute la prise en charge de la gestion des flux native de Pillow (la fourchette PIL conviviale) et devrait être disponible à partir de la version 2.8.0. Cela permet d'ouvrir des fichiers distants plus simplement avec rllib :

from PIL import Image
import urllib2
Image.open(urllib2.urlopen(url))

... ou en utilisant requêtes :

from PIL import Image
import requests
Image.open(requests.get(url, stream=True).raw)

Comme mentionné par mjpieters sur le PR les requêtes ne décodent pas automatiquement les réponses gzip, donc si vous téléchargez des images qui ont été encore compressées pour une raison quelconque, vous devez définir decode_content=True sur l'objet réponse avant d'accéder à .raw.

response = requests.get(url, stream=True)
response.raw.decode_content = True
image = Image.open(response.raw)
6
mfitzp

La documentation urllib mentionne qu'un objet renvoyé par urlopen ne prend pas en charge l'opération seek.

Ce module fournit une interface de haut niveau pour récupérer des données sur le World Wide Web. En particulier, la fonction urlopen () est similaire à la fonction intégrée open (), mais accepte les URL (Universal Resource Locators) au lieu des noms de fichiers. Certaines restrictions s'appliquent - il ne peut ouvrir que des URL pour la lecture et aucune opération de recherche n'est disponible.

Cependant, le PIL.open la fonction l'exige explicitement.

ouvert

Image.open (infile) => image

Image.open (infile, mode) => image

Ouvre et identifie le fichier d'image donné. Il s'agit d'une opération paresseuse; les données d'image réelles ne sont pas lues à partir du fichier jusqu'à ce que vous essayiez de traiter les données (appelez la méthode de chargement pour forcer le chargement). Si l'argument mode est donné, il doit être "r".

Vous pouvez utiliser une chaîne (représentant le nom de fichier) ou un objet fichier. Dans ce dernier cas, l'objet fichier doit implémenter les méthodes de lecture, de recherche et de lecture , et être ouvert en mode binaire.

Essayez d'utiliser le module cStringIO qui convertit une chaîne en objet de type fichier.

from PIL import Image
import urllib2 as urllib
import cStringIO

fd = urllib.urlopen("http://a/b/c")
image_file = cStringIO.StringIO(fd.read())
im = Image.open(image_file)
im.size
2
Maksim Skurydzin