Como salvar uma imagem localmente usando Python cujo endereço de URL eu já conheço?

Respostas:

316

Python 2

Aqui está uma maneira mais direta, se tudo o que você quer fazer é salvá-lo como um arquivo:

import urllib

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

O segundo argumento é o caminho local em que o arquivo deve ser salvo.

Python 3

Como o SergO sugeriu, o código abaixo deve funcionar com o Python 3.

import urllib.request

urllib.request.urlretrieve("http://www.digimouth.com/news/media/2011/09/google-logo.jpg", "local-filename.jpg")
Liquid_Fire
fonte
55
Uma boa maneira de obter filename a partir da ligação éfilename = link.split('/')[-1]
heltonbiker
2
com urlretrieve eu apenas recebo um arquivo de 1 KB com um dict e um texto de erro 404 dentro. Se eu digitar URL no meu navegador eu posso obter a imagem
Yebach
2
@Yebach: O site do qual você está baixando pode estar usando cookies, o User-Agent ou outros cabeçalhos para determinar qual conteúdo servir. Estes serão diferentes entre o seu navegador e o Python.
Liquid_Fire
27
Python 3 : import urllib.request eurllib.request.urlretrieve(), consequentemente.
SergO 22/01
1
@SergO - você pode adicionar a parte Python 3 à resposta 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 conterá sua imagem.

Noufal Ibrahim
fonte
2
Você deve abrir o arquivo no modo binário: open("file01.jpg", "wb")caso contrário, poderá corromper a imagem.
Liquid_Fire
2
urllib.urlretrievepode salvar a imagem diretamente.
Heltonbiker
17

Eu escrevi um script que faz exatamente isso , e está disponível no meu github para seu uso.

Utilizei o BeautifulSoup para analisar qualquer site em busca de imagens. Se você fará muito scraping na web (ou pretende usar minha ferramenta), sugiro sudo pip install BeautifulSoup. Informações sobre o BeautifulSoup estão disponíveis aqui .

Por conveniência, aqui está o meu 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')
Sim.
fonte
11

Isso pode ser feito com solicitações. Carregue a página e despeje o conteúdo binário em um arquivo.

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)
AlexG
fonte
1
cabeçalhos de usuário em solicitações se a solicitação for ruim :)
1UC1F3R616 26/03
8

Python 3

urllib.request - Biblioteca extensível para abrir URLs

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
SergO
fonte
6

Uma solução que funciona com Python 2 e 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")

ou, se o requisito adicional de requestsfor aceitável e se for um URL http (s):

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)
Martin Thoma
fonte
5

Eu criei um script expandindo o script de Yup. Eu consertei algumas coisas. Agora ele ignorará 403: Problemas proibidos. Não falha quando uma imagem falha ao ser recuperada. Ele tenta evitar visualizações corrompidas. Ele obtém os URLs absolutos certos. Dá mais informações. Pode ser executado com um argumento na linha de comando.

# 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)
madprops
fonte
3

Usando biblioteca de pedidos

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)
Sohan Das
fonte
Parece que o cabeçalho é realmente importante no meu caso, eu estava recebendo 403 erros. Funcionou.
Ishtiyaq Husain
2

Esta é uma resposta muito curta.

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

Versão para Python 3

Eu ajustei o 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')
Giovanni G. PY
fonte
1

Algo novo para o Python 3 usando Solicitações:

Comentários no código. Pronto para usar a função.


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")
Pavel Pančocha
fonte
0

Resposta tardia, mas para python>=3.6você pode usar o dload , ou seja:

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

se você precisar da imagem como bytes, use:

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

instale usando pip3 install dload

CONvid19
fonte
-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)
Lewis Mann
fonte
4
Bem-vindo ao Stack Overflow! Embora você possa ter resolvido o problema desse usuário, as respostas somente de código não são muito úteis para os usuários que chegarem a essa pergunta no futuro. Edite sua resposta para explicar por que seu código resolve o problema original.
Joe C
1
TypeError: a bytes-like object is required, not 'Response'. Deve ser #handler.write(img_data.content)
TitanFighter
Deveria ser handler.write(img_data.read()).
jdhao 16/06