Как выполнять парсинг изображений с сайта на Python

Научитесь легко выполнять парсинг изображений с сайтов с помощью Python и Selenium, улучшая сбор данных для машинного обучения, анализа рынка и курирования контента.
7 min read
How to Scrape Images in Python blog image

Из этого руководства вы узнаете:

  • Почему полезно выполнять парсинг изображения с сайта
  • Как выполнять парсинг изображений с сайта в Python с помощью Selenium

Давайте рассмотрим эти вопросы подробнее!

Зачем нужен парсинг изображений с сайта?

Веб-парсинг — это извлечение не только текстовых данных. При парсинге можно нацелиться на любой тип данных, включая мультимедийные файлы, в том числе изображения. В частности, парсинг изображений с сайта полезен в нескольких ситуациях. Вот их примеры:

  • Получение изображений для обучения моделей машинного обучения и искусственного интеллекта: обучайте модель на скачанных из интернета изображениях, чтобы повысить точность и эффективность модели.
  • Изучение подхода конкурентов к визуальной коммуникации: изучайте тенденции и стратегии, предоставив маркетинговой команде доступ к изображениям, которые конкуренты используют для передачи ключевых идей своей аудитории.
  • Автоматическое получение визуально привлекательных изображений от онлайн-поставщиков: используйте высококачественные изображения для привлечения и удержания внимания аудитории на сайте и в соцсетях.

Парсинг изображений в Python: пошаговое руководство

Для парсинга изображений с веб-страницы нужно сделать следующее:

  1. подключитесь к целевому сайту;
  2. выберите все интересующие HTML-узлы изображений на странице;
  3. извлеките URL-адреса изображений из каждого из них;
  4. скачайте файлы изображений, связанные с этими URL-адресами.

Подходящим целевым сайтом для выполнения этой задачи является Unsplash — один из самых популярных поставщиков изображений в Интернете. Вот как выглядит панель поиска слова «обои» (wallpaper) для бесплатных изображений:

поиск бесплатных изображений обоев

Как вы видите, страница загружает новые изображения, когда пользователь прокручивает ее вниз. Другими словами, это интерактивный сайт, для парсинга которого требуется инструмент автоматизации браузера.

URL-адрес этой страницы:

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

Пора узнать, как выполнять парсинг изображений с этого сайта в Python!

Шаг 1. Подготовка

Для выполнения указаний этого руководства убедитесь, что на вашем компьютере установлен Python 3. В противном случае скачайте инсталлятор, дважды нажмите на его значок и следуйте инструкциям.

Инициализируйте проект парсинга изображений в Python с помощью следующих команд:

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

Это приведет к созданию папки для парсера изображений и добавит в нее виртуальную среду Python.

Откройте папку проекта в выбранной вами среде Python IDE. Подойдут расширения PyCharm Community Edition или Visual Studio Code with the Python.

Создайте файл scraper.py в папке проекта и инициализируйте его следующим образом:

print('Hello, World!')

На данный момент этот файл представляет собой простой скрипт, который выводит «Hello, World!» но вскоре он будет содержать логическую схему парсинга изображений.

Убедитесь, что скрипт работает, нажав кнопку запуска IDE или выполнив команду ниже:

python scraper.py

В терминале должно появиться следующее сообщение:

Hello, World!

Прекрасно! Теперь у вас есть проект Python. На следующих этапах вы создадите логическую схему, необходимую для парсинга изображений с сайта.

Шаг 2. Установка Selenium

Selenium — отличная библиотека для парсинга изображений, поскольку она может обрабатывать сайты как со статическим, так и с динамическим контентом. При ее использовании как инструмента автоматизации браузера, она может отображать страницы, даже если для них требуется выполнение JavaScript. Узнайте больше в нашем руководстве «Веб-парсинг с помощью Selenium».

По сравнению с парсером HTML, таким как BeautifoulSoup, Selenium может нацеливаться на большее количество сайтов и охватывать больше конкретных сценариев использования. Например, он также работает с поставщиками изображений, которые загружают новые изображения на основе взаимодействия с пользователями. Это касается и Unsplash — целевого сайта, использованного в качестве примера в этом руководстве.

Перед установкой Selenium необходимо активировать виртуальную среду Python. Выполните следующую команду в Windows:

env\Scripts\activate

В macOS и Linux вместо этого запустите:

source env/bin/activate

В терминале env установите пакет Selenium WebDriver с помощью следующей pip-команды:

pip install selenium

Процесс установки займет некоторое время, так что наберитесь терпения.

Потрясающе! У вас есть все необходимое для парсинга изображений в Python.

Шаг 3. Подключение к целевому сайту
Импортируйте Selenium и классы, необходимые для управления экземпляром Chrome, добавив следующие строки в scraper.py

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

Теперь вы можете инициализировать экземпляр безголового Chrome WebDriver следующим кодом:

# 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
)

Добавьте комментарий к опции --headless, если хотите, чтобы Selenium запускал окно Chrome с графическим интерфейсом. Оно позволит вам следить за тем, что скрипт делает на странице в режиме реального времени. Это полезно для отладки. В рабочей среде оставьте включенной опцию --headless для экономии ресурсов.

Не забудьте закрыть окно браузера, добавив следующую строку в конце скрипта:

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

На некоторых страницах изображения отображаются по-разному в зависимости от размера экрана устройства пользователя. Чтобы избежать проблем с адаптивным контентом, разверните окно Chrome с помощью следующего:

driver.maximize_window()

Теперь вы можете проинструктировать Chrome подключиться к целевой странице через Selenium, используя метод get():

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

Соберите все это вместе, и вы получите:

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()

Запустите скрипт парсинга изображений в режиме с заголовком. Он отобразит на долю секунды следующую страницу перед закрытием Chrome:

Страница, отображаемая на долю секунды

Сообщение «Chrome контролируется программным обеспечением автоматического тестирования» (Chrome is being controlled by automated test software) означает, что Selenium работает в окне Chrome так, как требуется.

Превосходно! Ознакомьтесь с HTML-кодом страницы, чтобы узнать, как извлекать из нее изображения.

Шаг 4. Изучение целевого сайта

Прежде чем углубляться в логическую схему парсинга изображений в Python, следует ознакомиться с исходным HTML-кодом целевой страницы. Только так можно понять, как определить эффективную логику выбора узлов, и выяснить, как извлечь нужные данные.

Поэтому зайдите на целевой сайт в браузере, нажмите правой кнопкой мыши на изображении и выберите опцию «Просмотреть код» (Inspect), чтобы открыть DevTools:

просмотр кода изображения в devtools

Здесь обратите внимание на несколько интересных фактов.

Во-первых, изображение содержится в HTML-элементе <img>. Из-за этого CSS-селектор для выбора интересующих узлов изображения выглядит следующим образом:

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

Во-вторых, элементы изображения имеют как традиционный атрибут src, так и атрибут srcset. Если вы не знакомы с последним атрибутом, имейте в виду, что srcset указывает на несколько исходных изображений, а также дает подсказки, которые помогут браузеру выбрать подходящее изображение на основе адаптивных точек останова.

В частности, значение атрибута srcset имеет следующий формат:

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

Где:

  • <image_source_1_url>, <image_source_2_url> и т.д.— это URL-адреса изображений разных размеров.
  • <image_source_1_size>, <image_source_2_size>, и т.д. — размеры каждого источника изображения. Допустимые значения: ширина в пикселях (например, 200w) или соотношение пикселей (например, 1,5x).

Изображения с обоими атрибутами довольно часто встречаются на современных адаптивных сайтах. Таргетинг непосредственно по URL-адресу изображения в src — это не лучший подход, поскольку srcset может содержать URL-адреса изображений более высокого качества.

Из приведенного выше HTML-кода также видно, что все URL-адреса изображений являются абсолютными. Поэтому вам не нужно объединять с ними базовый URL-адрес сайта.

На следующем шаге вы узнаете, как извлекать нужные изображения в Python с помощью Selenium.

Шаг 5. Получение всех URL-адресов изображений

Используйте метод findElements() , чтобы выбрать все нужные узлы HTML-изображений на странице:

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

Для работы этой инструкции требуется следующий импорт:

from selenium.webdriver.common.by import By

Затем инициализируйте список, который будет содержать URL-адреса, извлеченные из элементов изображения:

image_urls = []

Проведите итерацию по узлам в image_html_nodes, соберите URL-адреса в src или URL-адрес самого большого изображения из srcset (если есть) и добавьте его в 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

Обратите внимание, что Unsplash — довольно динамичный сайт, и к моменту выполнения этого цикла некоторые изображения могут исчезнуть со страницы. Чтобы защититься от этой ошибки, выполните захват StaleElementReferenceException.

Опять же, не забудьте добавить этот импорт:

from selenium.common.exceptions import StaleElementReferenceException

Теперь вы можете вывести URL-адреса изображений, которые подверглись парсингу, с помощью:

print(image_urls)

Текущий файл 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

# 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()

Запустите скрипт для парсинга изображений, и вы получите следующий результат:

[
'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'
]

Вперед! Приведенный выше массив содержит URL-адреса изображений, которые необходимо извлечь. Осталось только посмотреть, как скачать изображения с помощью Python.

Шаг 6. Скачивание изображений

Самый простой способ скачать изображение в Python — использовать метод urlretrieve() из пакета url.request стандартной библиотеки. Эта функция копирует сетевой объект, указанный URL-адресом, в локальный файл.

Импортируйте url.request, добавив следующую строку поверх файла scraper.py:

import urllib.request

В папке проекта создайте каталог images:

mkdir images

Скрипт запишет в него файлы изображений.

Теперь выполните перебор списка с URL-адресами изображений, подвергшихся парсингу. Для каждого изображения создайте дополнительное имя файла и загрузите изображение с помощью 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

Это все, что вам нужно для скачивания изображений в Python. Инструкции print() не обязательны, но они полезны для понимания того, что делает скрипт.

Ура! Вы только что узнали, как выполнять парсинг изображений с сайта в Python. Пора просмотреть весь код скрипта Python для парсинга изображений.

Шаг 7. Полная сборка

Вот код финального файла 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()

Великолепно! Вы можете создать автоматический скрипт для скачивания изображений с сайта на языке Python, содержащий менее 100 строк кода.

Выполните его с помощью следующей команды:

python scraper.py

Python-скрипт парсинга изображений запишет следующую строку:

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"

Откройте папку /images, и вы увидите изображения, автоматически скачанные скриптом:

Ознакомление с содержимым папки изображений

Обратите внимание, что эти изображения отличаются от изображений на скриншоте страницы Unsplash, которые вы видели ранее, так как контент на сайте постоянно обновляется.

Все готово! Миссия выполнена.

Шаг 8. Следующие шаги

Хотя мы и достигли цели, существует несколько возможных реализаций для улучшения вашего Python-скрипта. Вот самые важные из них:

  • Экспортируйте URL-адреса изображений в файл CSV или храните их в базе данных: таким образом вы сможете загружать или использовать их в будущем.
  • Избегайте скачивания изображений, уже находящихся в папке /images: это улучшение экономит сетевые ресурсы, пропуская уже скачанные изображения.
  • Также выполняйте парсинг метаданных: извлечение тегов и информации об авторах может быть полезно для получения полной информации о скачанных изображениях. Узнайте, как это сделать, в нашем руководстве по веб-парсингу в Python.
  • Выполняйте парсинг большего количества изображений: смоделируйте взаимодействие с бесконечной прокруткой, загружайте больше изображений и скачивайте их все.

Заключение

Из этого руководства вы узнали, почему полезно выполнять парсинг изображений с сайта и как это сделать в Python. В частности, вы ознакомились с пошаговыми инструкциями по созданию Python-скрипта для парсинга изображений, который может автоматически скачивать изображения с сайта. Как показано здесь, это несложно и требует всего нескольких строк кода.

В то же время не стоит упускать из виду системы защиты от ботов. Selenium — отличный инструмент, но он ничего не может сделать против таких передовых технологий. Они могут распознать ваш скрипт как бота и запретить ему доступ к изображениям сайта.

Чтобы избежать этого, вам нужен инструмент, который может отображать JavaScript, а также обрабатывать цифровые отпечатки, капчи и защиту от парсинга. Именно это и призван делать Scraping Browser от Bright Data!

Поговорите с одним из наших экспертов по данным о наших решениях в области парсинга.

Кредитная карта не требуется

ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ

Законно ли выполнять парсинг изображений с сайта?

Парсинг изображений с сайта сам по себе не является незаконной деятельностью. В то же время важно скачивать только общедоступные изображения, соблюдать правила файла robots.txt в отношении парсинга, а также правила и условия сайта. Многие считают, что веб-парсинг является незаконным, но это миф. Узнайте больше из нашей статьи о мифах о веб-парсинге.

Какие библиотеки лучше всего подходят для скачивания изображений с помощью Python?

На сайтах со статическим контентом достаточно HTTP-клиента типа requests и HTML-парсера, такого как beautifulsoup4. На сайтах с динамическим контентом или высокоинтерактивных страницах вам понадобится инструмент автоматизации браузера, такой как Selenium или Playwright. Ознакомьтесь со списком лучших безголовых браузерных инструментов для веб-парсинга.

Как устранить ошибку «HTTP Error 403: Forbidden» в urllib.request?

Ошибка HTTP 403 возникает из-за того, что целевой сайт распознает запрос, сделанный с помощью urllib.request, как полученный от автоматического скрипта. Эффективный способ избежать этой проблемы — присвоить заголовку User-Agent реальное значение. При использовании метода urlretrieve() это можно сделать следующим образом:

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(...)