Como extrair imagens de um site em Python

Aprenda a extrair sem dificuldade imagens de sites usando Python e Selenium, aprimorando a coleta de dados para aprendizado de máquina, análise de mercado e curadoria de conteúdo.
17 min read
How to Scrape Images in Python blog image

Neste tutorial, você aprenderá:

  • Por que é útil extrair imagens de um site
  • Como extrair imagens de um site com Python usando Selenium

Vamos nos aprofundar!

Por que extrair imagens de um site?

O web scraping não trata apenas da extração de dados textuais. Em vez disso, pode-se ter como alvo qualquer tipo de dados, incluindo arquivos multimídia, como imagens. Em particular, extrair imagens de um site é útil em vários cenários. Isso inclui:

  • Recuperar imagens para treinar modelos de aprendizado de máquina e IA: treine um modelo usando imagens baixadas on-line para aprimorar sua precisão e eficácia.
  • Estudar como os concorrentes abordam a comunicação visual: entenda as tendências e estratégias dando à sua equipe de marketing acesso às imagens que os concorrentes usam para comunicar mensagens-chave ao público.
  • Obter automaticamente imagens visualmente atraentes de provedores on-line: use imagens de alta qualidade para obter alto engajamento em seu site e plataformas de mídia social, atraindo e retendo a atenção do público.

Python para extrair imagens: guia passo a passo

Para extrair imagens de uma página web, você precisa realizar a seguinte operação:

  1. Conecte-se ao site de destino
  2. Selecione todos os nós HTML de imagens de interesse na página
  3. Extraia os URLs das imagens de cada um deles
  4. Baixe os arquivos de imagem associados a esses URLs

Um bom site-alvo para essa tarefa é o Unsplash, um dos provedores de imagens mais populares da internet. Essa é a aparência do painel de imagens gratuitas quando pesquisamos a palavra “wallpaper” (papel de parede):

procurando imagens de papel de parede gratuitas

Como você pode ver, a página carrega novas imagens à medida que o usuário rola para baixo. Em outros termos, é um site interativo que exige uma ferramenta de automação do navegador para extração.

O URL dessa página é:

https://unsplash.com/s/photos/wallpaper?license=free

É hora de ver como extrair imagens desse site em Python!

Etapa 1: começando

Para seguir este tutorial, certifique-se de ter o Python 3 instalado em sua máquina. Se não tiver, baixe o instalador, dê um clique duplo nele para abri-lo e siga as instruções.

Inicialize seu projeto de extração de imagens em Python usando os comandos abaixo:

mkdir image-scraper
cd image-scraper
python -m venv env

Isso cria uma pasta image-scraper e adiciona um ambiente virtual Python dentro dela.

Abra a pasta do projeto em um IDE Python de sua escolha. PyCharm Community Edition ou Visual Studio Code com a extensão Python servem.

Crie um arquivo scraper.py na pasta do projeto e inicialize-o da seguinte forma:

print('Hello, World!')

No momento, esse arquivo é um script simples que imprime apenas “Hello, World!”, mas em breve conterá a lógica de extração de imagens.

Verifique se o script funciona pressionando o botão Run (executar) do seu IDE ou executando o comando abaixo:

python scraper.py

A seguinte mensagem deve aparecer em seu terminal:

Hello, World!

Ótimo! Agora você tem um projeto Python implementado. Implemente a lógica necessária para extrair imagens de um site nas próximas etapas.

Etapa 2: instale o Selenium

Selenium é uma excelente biblioteca para extrair imagens porque pode lidar com sites com conteúdo estático e dinâmico. Como uma ferramenta de automação de navegador, ele consegue renderizar páginas mesmo que elas exijam a execução de JavaScript. Saiba mais em nosso web scraping com Selenium.

Comparado a um analisador de HTML como BeautifoulSoup, o Selenium pode visar mais sites e cobrir mais casos de uso. Por exemplo, ele também funciona com provedores de imagens que dependem das interações do usuário para carregar novas imagens. Esse é exatamente o caso do Unsplash, o site-alvo deste guia.

Antes de instalar o Selenium, você precisa ativar o ambiente virtual Python. No Windows, faça isso com este comando:

env\Scripts\activate

No macOS e Linux, execute em vez disso:

source env/bin/activate

No terminal env, instale o pacote Selenium WebDriver com o seguinte comando pip :

pip install selenium

O processo de instalação pode demorar um pouco, então seja paciente.

Formidável! Você tem tudo o que precisa para extrair imagens em Python.

Etapa 3: conecte-se ao site-alvo
Importe o Selenium e as classes necessárias para controlar uma instância do Chrome adicionando as seguintes linhas ao scraper.py

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.chrome.options import Options

Agora você pode inicializar uma instância headless do Chrome WebDriver com este código:

# to run Chrome in headless mode
options = Options()
options.add_argument("--headless") # comment while developing

# initialize a Chrome WerbDriver instance
# with the specified options
driver = webdriver.Chrome(
    service=ChromeService(),
    options=options
)

Transforme a opção --headless em comentário, se quiser que o Selenium inicie uma janela do Chrome com a GUI. Isso permitirá que você acompanhe o que o script faz na página em tempo real, o que é útil para depuração. Na produção, mantenha a opção --headless ativada para economizar recursos.

Não se esqueça de fechar a janela do navegador adicionando esta linha no final do seu script:

# close the browser and free up its resources
driver.quit() 

Algumas páginas exibem imagens de forma diferente dependendo do tamanho da tela do dispositivo do usuário. Para evitar problemas com conteúdo responsivo, maximize a janela do Chrome com:

driver.maximize_window()

Agora você pode instruir o Chrome a se conectar à página-alvo através do Selenium usando o método get():

url = "https://unsplash.com/s/photos/wallpaper?license=free"
driver.get(url)

Junte tudo e você terá:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.chrome.options import Options

# to run Chrome in headless mode
options = Options()
options.add_argument("--headless")

# initialize a Chrome WerbDriver instance
# with the specified options
driver = webdriver.Chrome(
    service=ChromeService(),
    options=options
)

# to avoid issues with responsive content
driver.maximize_window()

# the URL of the target page
url = "https://unsplash.com/s/photos/wallpaper?license=free"
# visit the target page in the controlled browser
driver.get(url)

# close the browser and free up its resources
driver.quit()

Inicie o script de extração de imagens no modo headed. Isso mostrará a seguinte página numa fração de uma seção antes de fechar o Chrome:

Página mostrada por uma fração

A mensagem “o Chrome está sendo controlado por um software de teste automatizado” significa que o Selenium está em operação na janela do Chrome, como desejado.

Perfeito! Dê uma olhada no código HTML da página para saber como extrair imagens dela.

Etapa 4: inspecione o site-alvo

Antes de nos aprofundarmos na lógica de extração de imagens do Python, você deve inspecionar o código-fonte HTML da sua página-alvo. Somente dessa maneira você poderá entender como definir uma lógica efetiva de seleção de nós e descobrir como extrair os dados desejados.

Assim, visite o site-alvo em seu navegador, clique com o botão direito do mouse em uma imagem e selecione a opção “Inspecionar” para abrir o DevTools:

Inspecionando uma imagem no devtools

Aqui, você pode observar alguns fatos interessantes.

Primeiro, a imagem está contida em um elemento HTML <img>. Isso significa que o seletor CSS para selecionar os nós de imagem de interesse é:

[data-test="photo-grid-masonry-img"]

Segundo, os elementos de imagem têm o atributo tradicional src e o atributo srcset . Se você não estiver familiarizado com o último atributo, srcset especifica várias fontes de imagens junto com dicas para ajudar o navegador a escolher a correta com base nos breakpoints responsivos.

Em detalhes, o valor de um atributo srcset tem o seguinte formato:

<image_source_1_url> <image_source_1_size>, <image_source_1_url> <image_source_2_size>, ...

Onde:

  • <image_source_1_url>, <image_source_2_url> etc. são os URLs para imagens com tamanhos diferentes.
  • <image_source_1_size>, <image_source_2_size> etc. são os tamanhos de cada fonte de imagem. Os valores permitidos são larguras de pixels (por exemplo, 200w) ou proporções de pixels (por exemplo, 1,5x).

Esse cenário em que uma imagem tem os dois atributos é bastante comum em sites responsivos modernos. Visar diretamente no URL da imagem em src não é a melhor abordagem, pois srcset pode conter URLs para imagens de maior qualidade.

No HTML acima, você também pode ver que todos os URLs das imagens são absolutos. Portanto, você não precisa concatenar o URL base do site com eles.

Na próxima etapa, você aprenderá como extrair as imagens certas em Python usando Selenium.

Etapa 5: recupere todos os URLs de imagens

Use o método findElements() para selecionar todos os nós HTML de imagem desejados na página:

image_html_nodes = driver.find_elements(By.CSS_SELECTOR, "[data-test=\"photo-grid-masonry-img\"]")  

Para funcionar, essa instrução precisa da seguinte importação:

from selenium.webdriver.common.by import By

Em seguida, inicialize uma lista que conterá os URLs extraídos dos elementos de imagem:

image_urls = []

Itere sobre os nós em image_html_nodes, colete o URL em src ou o URL da maior imagem em srcset (se houver) e adicione-o a image_urls:

for image_html_node in image_html_nodes:
  try:
    # use the URL in the "src" as the default behavior
    image_url = image_html_node.get_attribute("src")

    # extract the URL of the largest image from "srcset",
    # if this attribute exists
    srcset =  image_html_node.get_attribute("srcset")
    if srcset is not None:
      # get the last element from the "srcset" value
      srcset_last_element = srcset.split(", ")[-1]
      # get the first element of the value,
      # which is the image URL
      image_url = srcset_last_element.split(" ")[0]

    # add the image URL to the list
    image_urls.append(image_url)
  except StaleElementReferenceException as e:
    continue

Observe que o Unsplash é um site bastante dinâmico e, quando você executa esse loop, algumas imagens podem não estar mais na página. Para se proteger contra esse erro, capture StaleElementReferenceException.

Novamente, não se esqueça de adicionar esta importação:

from selenium.common.exceptions import StaleElementReferenceException

Agora você pode imprimir os URLs das imagens extraídas com:

print(image_urls)

O arquivo scraper.py atual deve conter:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.common.exceptions import StaleElementReferenceException

# to run Chrome in headless mode
options = Options()
options.add_argument("--headless")

# initialize a Chrome WerbDriver instance
# with the specified options
driver = webdriver.Chrome(
    service=ChromeService(),
    options=options
)

# to avoid issues with responsive content
driver.maximize_window()

# the URL of the target page
url = "https://unsplash.com/s/photos/wallpaper?license=free"
# visit the target page in the controlled browser
driver.get(url)

# select the node images on the page
image_html_nodes = driver.find_elements(By.CSS_SELECTOR, "[data-test=\"photo-grid-masonry-img\"]")

# where to store the scraped image url
image_urls = []

# extract the URLs from each image
for image_html_node in image_html_nodes:
  try:
    # use the URL in the "src" as the default behavior
    image_url = image_html_node.get_attribute("src")

    # extract the URL of the largest image from "srcset",
    # if this attribute exists
    srcset =  image_html_node.get_attribute("srcset")
    if srcset is not None:
      # get the last element from the "srcset" value
      srcset_last_element = srcset.split(", ")[-1]
      # get the first element of the value,
      # which is the image URL
      image_url = srcset_last_element.split(" ")[0]

    # add the image URL to the list
    image_urls.append(image_url)
  except StaleElementReferenceException as e:
    continue

# log in the terminal the scraped data
print(image_urls)

# close the browser and free up its resources
driver.quit()

Execute o script para extrair imagens e você obterá uma saída semelhante a esta:

[
'https://images.unsplash.com/photo-1707343843598-39755549ac9a?w=2000&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxzZWFyY2h8MXx8d2FsbHBhcGVyfGVufDB8fDB8fHwy', 

# omitted for brevity...

'https://images.unsplash.com/photo-1507090960745-b32f65d3113a?w=2000&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MjB8fHdhbGxwYXBlcnxlbnwwfHwwfHx8Mg%3D%3D'
]

Vamos lá! O conjunto acima contém os URLs das imagens a serem recuperadas. Só resta ver como baixar imagens em Python.

Etapa 6: baixe as imagens

A maneira mais fácil de baixar uma imagem em Python é usar o método urlretrieve() do pacote url.request da Biblioteca Padrão. Essa função copia um objeto de rede especificado por um URL para um arquivo local.

Importe url.request adicionando a seguinte linha no topo do seu arquivo scraper.py:

import urllib.request

Na pasta do projeto, crie um diretório images:

mkdir images

É aqui que o script gravará os arquivos de imagem.

Agora, repita a lista com os URLs das imagens extraídas. Para cada imagem, gere um nome de arquivo incremental e baixe a imagem com urlretrieve():

image_name_counter = 1

# download each image and add it
# to the "/images" local folder
for image_url in image_urls:
  print(f"downloading image no. {image_name_counter} ...")

  file_name = f"./images/{image_name_counter}.jpg"
  # download the image
  urllib.request.urlretrieve(image_url, file_name)

  print(f"images downloaded successfully to \"{file_name}\"\n")

  # increment the image counter
  image_name_counter += 1

Isso é tudo o que você precisa para baixar imagens em Python. As instruções print() não são obrigatórias, mas são úteis para entender o que o script está fazendo.

Uau! Você acabou de aprender a extrair imagens de um site em Python. É hora de ver todo o código do script Python para extrair imagens.

Etapa 7: junte tudo

Este é o código final do scraper.py:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.common.exceptions import StaleElementReferenceException
import urllib.request

# to run Chrome in headless mode
options = Options()
options.add_argument("--headless")

# initialize a Chrome WerbDriver instance
# with the specified options
driver = webdriver.Chrome(
    service=ChromeService(),
    options=options
)

# to avoid issues with responsive content
driver.maximize_window()

# the URL of the target page
url = "https://unsplash.com/s/photos/wallpaper?license=free"
# visit the target page in the controlled browser
driver.get(url)

# select the node images on the page
image_html_nodes = driver.find_elements(By.CSS_SELECTOR, "[data-test=\"photo-grid-masonry-img\"]")

# where to store the scraped image url
image_urls = []

# extract the URLs from each image
for image_html_node in image_html_nodes:
  try:
    # use the URL in the "src" as the default behavior
    image_url = image_html_node.get_attribute("src")

    # extract the URL of the largest image from "srcset",
    # if this attribute exists
    srcset =  image_html_node.get_attribute("srcset")
    if srcset is not None:
      # get the last element from the "srcset" value
      srcset_last_element = srcset.split(", ")[-1]
      # get the first element of the value,
      # which is the image URL
      image_url = srcset_last_element.split(" ")[0]

    # add the image URL to the list
    image_urls.append(image_url)
  except StaleElementReferenceException as e:
    continue

# to keep track of the images saved to disk
image_name_counter = 1

# download each image and add it
# to the "/images" local folder
for image_url in image_urls:
  print(f"downloading image no. {image_name_counter} ...")

  file_name = f"./images/{image_name_counter}.jpg"
  # download the image
  urllib.request.urlretrieve(image_url, file_name)

  print(f"images downloaded successfully to \"{file_name}\"\n")

  # increment the image counter
  image_name_counter += 1

# close the browser and free up its resources
driver.quit()

Excelente! Você pode criar um script automatizado para baixar imagens de um site em Python com menos de 100 linhas de código.

Execute-o com o seguinte comando:

python scraper.py

O script de extração de imagens em Python registrará a seguinte string:

downloading image no. 1 ...
images downloaded successfully to "./images/1.jpg"

# omitted for brevity...

downloading image no. 20 ...
images downloaded successfully to "./images/20.jpg"

Explore a pasta /images e você verá as imagens baixadas automaticamente pelo script:

Explorando a pasta de imagens

Note que essas imagens são diferentes daquelas na captura de tela da página Unsplash vista anteriormente porque o site continua recebendo conteúdo atualizado.

E pronto! Missão cumprida.

Etapa 8: próximas etapas

Embora tenhamos alcançado a meta, existem algumas implementações possíveis para melhorar seu script Python. As mais importantes são:

  • Exportar URLs de imagens para CSV ou armazená-las em um banco de dados: dessa forma, você poderá baixá-las ou usá-las no futuro.
  • Evitar baixar imagens que já estão na pasta /images: essa melhoria economiza recursos de rede ao ignorar imagens que já foram baixadas.
  • Extrair também as informações de metadados: recuperar tags e informações do autor pode ser útil para obter informações completas sobre as imagens baixadas. Saiba como em nosso guia de web scraping em Python.
  • Extrair mais imagens: simule a interação de rolagem infinita, carregue mais imagens e baixe todas elas.

Conclusão

Neste guia, você aprendeu por que extrair imagens de um site é útil e como fazer isso em Python. Em particular, você viu um tutorial passo a passo sobre como criar um script de extração de imagens em Python que pode baixar imagens automaticamente de um site. Conforme comprovado aqui, não é complexo e exige apenas algumas linhas de código.

Ao mesmo tempo, você não pode ignorar os sistemas antibot. O Selenium é uma ótima ferramenta, mas não consegue fazer nada contra essas tecnologias avançadas. Elas podem detectar seu script como um bot e impedir que ele acesse imagens do site.

Para evitar isso, você precisará de uma ferramenta que possa renderizar JavaScript e seja capaz de lidar com impressões digitais, CAPTCHAs e antiscraping para você. É exatamente disso que trata o Scraping Browser da Bright Data!

Fale com um dos nossos especialistas em dados sobre as nossas soluções de scraping.

Não é necessário cartão de crédito

Perguntas frequentes

É legal extrair imagens de um site?

Extrair imagens de um site não é uma atividade ilegal por si só. Ao mesmo tempo, é essencial baixar somente imagens públicas, respeitar o arquivo robots.txt para scrapinge cumprir os Termos e Condições do site. Muitas pessoas pensam que o web scraping não é legal, mas isso é um mito. Saiba mais em nosso artigo que fala dos mitos sobre web scraping.

Quais são as melhores bibliotecas para baixar imagens com Python?

Em sites de conteúdo estático, um cliente HTTP como requests e um analisador HTML como beautifulsoup4 serão suficientes. Em sites de conteúdo dinâmico ou páginas altamente interativas, você precisará de uma ferramenta de automação de navegador, como Selenium ou Playwright. Confira a lista das melhores ferramentas de navegador headless para web scraping.

Como resolver o “Erro HTTP 403: Proibido” em urllib.request?

O erro HTTP 403 ocorre porque o site-alvo reconhece a solicitação feita com urllib.request como proveniente de um script automatizado. Uma forma eficaz de evitar esse problema é definir o cabeçalho User-Agent com um valor real. Ao usar o método urlretrieve(), é assim que você pode fazer:

opener = urllib.request.build_opener()
user_agent_string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
opener.addheaders = [("User-Agent", user_agent_header)]
urllib.request.install_opener(opener)
# urllib.request.urlretrieve(...)