¿Cómo guardar una imagen localmente usando Python cuya dirección URL ya conozco?


Respuestas:


316

Python 2

Aquí hay una forma más directa si todo lo que quiere hacer es guardarlo como un archivo:

import urllib

urllib.urlretrieve("http://www.digimouth.com/news/media/2011/09/google-logo.jpg", "local-filename.jpg")

El segundo argumento es la ruta local donde se debe guardar el archivo.

Python 3

Como sugirió SergO, el siguiente código debería funcionar con Python 3.

import urllib.request

urllib.request.urlretrieve("http://www.digimouth.com/news/media/2011/09/google-logo.jpg", "local-filename.jpg")

55
Una buena manera de obtener el nombre de archivo del enlace esfilename = link.split('/')[-1]
heltonbiker

2
con urlretrieve acabo de obtener un archivo de 1 KB con un dict y un texto de error 404 dentro. ¿Por qué? Si ingreso la URL en mi navegador, puedo obtener la imagen
Yebach

2
@Yebach: el sitio desde el que está descargando puede estar utilizando cookies, el Agente de usuario u otros encabezados para determinar qué contenido le servirá. Estos serán diferentes entre su navegador y Python.
Liquid_Fire

27
Python 3 : import urllib.request yurllib.request.urlretrieve(), en consecuencia.
SergO

1
@SergO: ¿puede agregar la parte de Python 3 a la respuesta original?
Sreejith Menon

27
import urllib
resource = urllib.urlopen("http://www.digimouth.com/news/media/2011/09/google-logo.jpg")
output = open("file01.jpg","wb")
output.write(resource.read())
output.close()

file01.jpg contendrá su imagen.


2
Debe abrir el archivo en modo binario: de lo open("file01.jpg", "wb")contrario, puede dañar la imagen.
Liquid_Fire

2
urllib.urlretrievePuede guardar la imagen directamente.
heltonbiker

17

Escribí un script que hace exactamente esto , y está disponible en mi github para su uso.

Utilicé BeautifulSoup para permitirme analizar cualquier sitio web en busca de imágenes. Si va a hacer mucho raspado web (o tiene la intención de usar mi herramienta), le sugiero sudo pip install BeautifulSoup. La información sobre BeautifulSoup está disponible aquí .

Por conveniencia aquí está mi código:

from bs4 import BeautifulSoup
from urllib2 import urlopen
import urllib

# use this image scraper from the location that 
#you want to save scraped images to

def make_soup(url):
    html = urlopen(url).read()
    return BeautifulSoup(html)

def get_images(url):
    soup = make_soup(url)
    #this makes a list of bs4 element tags
    images = [img for img in soup.findAll('img')]
    print (str(len(images)) + "images found.")
    print 'Downloading images to current working directory.'
    #compile our unicode list of image links
    image_links = [each.get('src') for each in images]
    for each in image_links:
        filename=each.split('/')[-1]
        urllib.urlretrieve(each, filename)
    return image_links

#a standard call looks like this
#get_images('http://www.wookmark.com')

11

Esto se puede hacer con solicitudes. Cargue la página y descargue el contenido binario en un archivo.

import os
import requests

url = 'https://apod.nasa.gov/apod/image/1701/potw1636aN159_HST_2048.jpg'
page = requests.get(url)

f_ext = os.path.splitext(url)[-1]
f_name = 'img{}'.format(f_ext)
with open(f_name, 'wb') as f:
    f.write(page.content)

1
encabezados por el usuario en las solicitudes si conseguir solicitud incorrecta :)
1UC1F3R616

8

Python 3

urllib.request: biblioteca extensible para abrir URL

from urllib.error import HTTPError
from urllib.request import urlretrieve

try:
    urlretrieve(image_url, image_local_path)
except FileNotFoundError as err:
    print(err)   # something wrong with local path
except HTTPError as err:
    print(err)  # something wrong with url

6

Una solución que funciona con Python 2 y Python 3:

try:
    from urllib.request import urlretrieve  # Python 3
except ImportError:
    from urllib import urlretrieve  # Python 2

url = "http://www.digimouth.com/news/media/2011/09/google-logo.jpg"
urlretrieve(url, "local-filename.jpg")

o, si el requisito adicional de requestses aceptable y si es una URL de http:

def load_requests(source_url, sink_path):
    """
    Load a file from an URL (e.g. http).

    Parameters
    ----------
    source_url : str
        Where to load the file from.
    sink_path : str
        Where the loaded file is stored.
    """
    import requests
    r = requests.get(source_url, stream=True)
    if r.status_code == 200:
        with open(sink_path, 'wb') as f:
            for chunk in r:
                f.write(chunk)

5

Hice un guión ampliando el guión de Yup. Arreglé algunas cosas. Ahora evitará 403: problemas prohibidos. No se bloqueará cuando una imagen no se pueda recuperar. Intenta evitar vistas previas corruptas. Obtiene las URL absolutas correctas. Da más información. Se puede ejecutar con un argumento desde la línea de comandos.

# getem.py
# python2 script to download all images in a given url
# use: python getem.py http://url.where.images.are

from bs4 import BeautifulSoup
import urllib2
import shutil
import requests
from urlparse import urljoin
import sys
import time

def make_soup(url):
    req = urllib2.Request(url, headers={'User-Agent' : "Magic Browser"}) 
    html = urllib2.urlopen(req)
    return BeautifulSoup(html, 'html.parser')

def get_images(url):
    soup = make_soup(url)
    images = [img for img in soup.findAll('img')]
    print (str(len(images)) + " images found.")
    print 'Downloading images to current working directory.'
    image_links = [each.get('src') for each in images]
    for each in image_links:
        try:
            filename = each.strip().split('/')[-1].strip()
            src = urljoin(url, each)
            print 'Getting: ' + filename
            response = requests.get(src, stream=True)
            # delay to avoid corrupted previews
            time.sleep(1)
            with open(filename, 'wb') as out_file:
                shutil.copyfileobj(response.raw, out_file)
        except:
            print '  An error occured. Continuing.'
    print 'Done.'

if __name__ == '__main__':
    url = sys.argv[1]
    get_images(url)

3

Usar la biblioteca de solicitudes

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)


ImageDl(url)

Parece que el encabezado es realmente importante en mi caso, estaba recibiendo 403 errores. Funcionó.
Ishtiyaq Husain

2

Esta es una respuesta muy corta.

import urllib
urllib.urlretrieve("http://photogallery.sandesh.com/Picture.aspx?AlubumId=422040", "Abc.jpg")

2

Versión para Python 3

Ajusté el código de @madprops para Python 3

# getem.py
# python2 script to download all images in a given url
# use: python getem.py http://url.where.images.are

from bs4 import BeautifulSoup
import urllib.request
import shutil
import requests
from urllib.parse import urljoin
import sys
import time

def make_soup(url):
    req = urllib.request.Request(url, headers={'User-Agent' : "Magic Browser"}) 
    html = urllib.request.urlopen(req)
    return BeautifulSoup(html, 'html.parser')

def get_images(url):
    soup = make_soup(url)
    images = [img for img in soup.findAll('img')]
    print (str(len(images)) + " images found.")
    print('Downloading images to current working directory.')
    image_links = [each.get('src') for each in images]
    for each in image_links:
        try:
            filename = each.strip().split('/')[-1].strip()
            src = urljoin(url, each)
            print('Getting: ' + filename)
            response = requests.get(src, stream=True)
            # delay to avoid corrupted previews
            time.sleep(1)
            with open(filename, 'wb') as out_file:
                shutil.copyfileobj(response.raw, out_file)
        except:
            print('  An error occured. Continuing.')
    print('Done.')

if __name__ == '__main__':
    get_images('http://www.wookmark.com')

1

Algo nuevo para Python 3 usando Solicitudes:

Comentarios en el código. Listo para usar la función.


import requests
from os import path

def get_image(image_url):
    """
    Get image based on url.
    :return: Image name if everything OK, False otherwise
    """
    image_name = path.split(image_url)[1]
    try:
        image = requests.get(image_url)
    except OSError:  # Little too wide, but work OK, no additional imports needed. Catch all conection problems
        return False
    if image.status_code == 200:  # we could have retrieved error page
        base_dir = path.join(path.dirname(path.realpath(__file__)), "images") # Use your own path or "" to use current working directory. Folder must exist.
        with open(path.join(base_dir, image_name), "wb") as f:
            f.write(image.content)
        return image_name

get_image("https://apod.nasddfda.gov/apod/image/2003/S106_Mishra_1947.jpg")

0

Respuesta tardía, pero python>=3.6puede usar dload , es decir:

import dload
dload.save("http://www.digimouth.com/news/media/2011/09/google-logo.jpg")

si necesita la imagen como bytes, use:

img_bytes = dload.bytes("http://www.digimouth.com/news/media/2011/09/google-logo.jpg")

instalar usando pip3 install dload


-2
img_data=requests.get('https://apod.nasa.gov/apod/image/1701/potw1636aN159_HST_2048.jpg')

with open(str('file_name.jpg', 'wb') as handler:
    handler.write(img_data)

44
¡Bienvenido a Stack Overflow! Si bien es posible que haya resuelto el problema de este usuario, las respuestas de solo código no son muy útiles para los usuarios que vengan a esta pregunta en el futuro. Edite su respuesta para explicar por qué su código resuelve el problema original.
Joe C

1
TypeError: a bytes-like object is required, not 'Response'. Debe serhandler.write(img_data.content)
TitanFighter

Debería ser handler.write(img_data.read()).
jdhao
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.