¿Cómo leo los datos de imagen de una URL?

4 minutos de lectura

Avatar de usuario de Daniel Quinn
Daniel Quinn

Lo que trato de hacer es bastante simple cuando se trata de un archivo local, pero el problema surge cuando trato de hacer esto con una URL remota.

Básicamente, estoy tratando de crear un objeto de imagen PIL a partir de un archivo extraído de una URL. Claro, siempre podría obtener la URL y almacenarla en un archivo temporal, luego abrirla en un objeto de imagen, pero eso se siente muy ineficiente.

Esto es lo que tengo:

Image.open(urlopen(url))

Se escama quejándose de que seek() no está disponible, así que probé esto:

Image.open(urlopen(url).read())

Pero eso tampoco funcionó. ¿Hay una mejor manera de hacer esto, o es escribir en un archivo temporal la forma aceptada de hacer este tipo de cosas?

  • Ver también: ¿Cómo guardar una imagen localmente usando Python cuya dirección URL ya conozco?

    – Martín Tomas

    14/03/2016 a las 11:25

  • Debe haber un problema en el que las solicitudes no pueden obtener la imagen de la URL. Intente lo mismo (solo con fines de prueba) desde otra URL.

    – Aashish Chaubey

    17 de noviembre de 2021 a las 11:46

Avatar de usuario de Andrés Kull
Andrés Kull

En Python3, los módulos StringIO y cStringIO desaparecieron.

En Python3 deberías usar:

from PIL import Image
import requests
from io import BytesIO

response = requests.get(url)
img = Image.open(BytesIO(response.content))

  • ¿Cómo recuperar la imagen de response.content?

    – Amresh Giri

    7 de febrero de 2019 a las 11:33

  • requests el paquete arroja un código de estado 503 al obtener una imagen de una URL. En cambio, tuve que recurrir a http.client para obtener la imagen.

    – SMS

    8 de agosto de 2019 a las 6:46

  • Cuando intento esto, obtengo: AttributeError: el módulo ‘solicitudes’ no tiene el atributo ‘obtener’.

    – apiljic

    26 de agosto de 2019 a las 23:21

  • Ya no es necesario envolver manualmente en BytesIO desde PIL >= 2.8.0. Solo usa Image.open(response.raw). PIL verifica automáticamente eso ahora y hace el envoltorio BytesIO debajo del capó. Desde: almohada.readthedocs.io/en/3.0.x/releasenotes/2.8.0.html

    – Vinícius M

    6 de febrero de 2020 a las 15:21

  • Es un poco molesto que se necesiten 3 bibliotecas… ¡La almohada debería agregar esta funcionalidad!

    -Nic Scozzaro

    29 abr 2021 a las 22:15

Avatar de usuario de Fábio Diniz
Fábio Diniz

Usando un StringIO

import urllib, cStringIO

file = cStringIO.StringIO(urllib.urlopen(URL).read())
img = Image.open(file)

  • Gracias, solo me gustaría agregar que el mismo código exacto funcionará con urllib2 (con Python2)

    – Entonces, vuela

    3 de diciembre de 2014 a las 18:59

  • en python 3 sería de urllib.request importar urlopen y io.io.BytesIO en lugar de StringIO

    – matyas

    13 de diciembre de 2016 a las 16:38

  • AYUDA, IOError: no se puede identificar el archivo de imagen <_io.bytesio objeto en> mi URL es: …model=product.template&id=16&field=image_medium

    – C. Дэлгэрцэцэг

    3 de septiembre de 2018 a las 12:43


Avatar de usuario de Giovanni Cappellotto
giovanni cappellotto

Lo siguiente funciona para Python 3:

from PIL import Image
import requests

im = Image.open(requests.get(url, stream=True).raw)

Referencias:

  • Creo que urllib2 era para Python2, que está desactualizado. Para Python 3 es urllib.requests: urllib.request.urlopen(url).read()

    – palabras para el sabio

    24 de enero de 2021 a las 1:03

  • Como menciona @wordsforthewise, urllib está desactualizado. Usé la segunda opción ya que estaba usando ‘solicitudes’ de todos modos en mi código y funcionó, así que voté a favor. ¿Debería eliminarse la parte urllib de la solución para que los lectores no pierdan tiempo probando el primer enfoque solo para darse cuenta de que no funciona y luego pasar al siguiente?

    – Mugdha

    4 de marzo de 2021 a las 13:40


  • ¡Hola, esto funcionó muy bien para mi proyecto! Solo me preguntaba, ¿esto acumula algún búfer o caché? ¿Necesito cerrar estas imágenes/borrar algo?

    – Banquero cabreado

    14 de diciembre a las 17:21

Avatar de usuario de Saurav
Saurav

Usando requests:

from PIL import Image
import requests
from StringIO import StringIO

response = requests.get(url)
img = Image.open(StringIO(response.content))

Avatar de usuario de Miladiouss
Miladiosas

Pitón 3

from urllib.request import urlopen
from PIL import Image

img = Image.open(urlopen(url))
img

Jupyter Notebook e IPython

import IPython
url="https://newevolutiondesigns.com/images/freebies/colorful-background-14.jpg"
IPython.display.Image(url, width = 250)

A diferencia de otros métodos, ¡este método también funciona en un bucle for!

avatar de usuario de henry sneed
henry estornudo

Usar StringIO para convertir la cadena de lectura en un objeto similar a un archivo:

from StringIO import StringIO
from PIL import Image
import urllib

Image.open(StringIO(urllib.request.urlopen(url).read()))

Avatar de usuario de Ben
ben

Para aquellos que realizan algún procesamiento posterior sklearn/numpy (es decir, aprendizaje profundo), pueden envolver el objeto PIL con np.array(). Esto podría evitar que tengas que buscarlo en Google como lo hice yo:

from PIL import Image
import requests
import numpy as np
from StringIO import StringIO

response = requests.get(url)
img = np.array(Image.open(StringIO(response.content)))

¿Ha sido útil esta solución?