🐍 Самоучитель по Python для начинающих. Часть 17: Основы скрапинга и парсинга
Научимся извлекать данные из статического и динамического контента с помощью регулярных выражений, XPath, BeautifulSoup, MechanicalSoup и Selenium. В конце статьи – код 10 скриптов для скрапинга данных и изображений с Wikipedia, Habr, LiveLib, IMDb и TIOBE.
Веб-скрапинг – это процесс автоматического сбора информации
из онлайн-источников. Для выбора нужных сведений из массива «сырых» данных,
полученных в ходе скрапинга, нужна дальнейшая обработка – парсинг. В процессе
парсинга выполняются синтаксический анализ, разбор и очистка данных. Результат
парсинга – очищенные, упорядоченные, структурированные данные, представленные в
формате, понятном конечному пользователю (или приложению).
Скрипты для скрапинга создают определенную нагрузку на
сайт, с которого они собирают данные – могут, например, посылать чрезмерное
количество GET запросов к серверу. Это одна из причин, по которой
скрапинг относится к спорным видам деятельности. Чтобы не выходить за рамки
сетевого этикета, необходимо всегда соблюдать главные правила сбора публичной
информации:
Если на сайте есть API, нужно запрашивать данные у него.
Частота и количество GET запросов должны быть разумными.
Следует передавать информацию о клиенте в User-Agent.
Если на сайте есть личные данные пользователей, необходимо учитывать настройки приватности в robots.txt.
Необходимо отметить, что универсальных рецептов скрапинга и
парсинга не существует. Это связано со следующими причинами:
Некоторые сервисы активно блокируют скраперов. Динамическая смена прокси не всегда помогает решить эту проблему.
Контент многих современных сайтов генерируется динамически – результат обычного GET запроса из приложения к таким сайтам вернется практически пустым. Эта проблема решается с помощью Selenium WebDriver либо MechanicalSoup, которые имитируют действия браузера и пользователя.
Для извлечения данных со страниц с четкой, стандартной
структурой эффективнее использовать язык запросов XPath. И напротив, для
получения нужной информации с нестандартных страниц с произвольным синтаксисом
лучше использовать средства библиотеки BeautifulSoup. Ниже мы подробно рассмотрим оба подхода.
Экосистема Pythonрасполагает множеством инструментов для скрапинга и
парсинга. Начнем с самого простого примера – получения веб-страницы и
извлечения из ее кода ссылки.
Скрапинг содержимого страницы
Воспользуемся модулем urllib.request стандартной библиотеки urllib
для получения исходного кода одностраничного сайта example.com:
Результат:
Точно такой же результат можно получить с помощью requests:
Этот результат – те самые сырые данные, которые нужно
обработать (подвергнуть парсингу), чтобы извлечь из них нужную информацию,
например, адрес указанной на странице ссылки:
Парсинг полученных данных
Извлечь адрес ссылки можно 4 разными способами – с помощью:
Методов строк.
Регулярного выражения.
Запроса XPath.
Обработки BeautifulSoup.
Рассмотрим все эти способы по порядку.
Методы строк
Это самый трудоемкий способ – для извлечения каждого
элемента нужно определить 2 индекса – начало и конец вхождения. При этом к
индексу вхождения надо добавить длину стартового фрагмента:
Результат:
Регулярное выражение
В предыдущей главе мы подробно рассматривали способы
извлечения конкретных подстрок из текста. Точно так же регулярные выражения
можно использовать для поиска данных в исходном коде страниц:
Результат:
Запрос XPath
Язык запросов XPath(XMLPathLanguage) позволяет извлекать данные из определенных узлов XML-документа. Для работы с HTML кодом в Pythonиспользуют
модуль etree:
Результат:
Чтобы узнать путь к нужному элементу страницы, в браузерах
Chromeи FireFox надо
кликнуть правой кнопкой по элементу и выбрать «Просмотреть код», после чего
откроется консоль. В консоли по интересующему элементу нужно еще раз кликнуть
правой кнопкой, выбрать «Копировать», а затем – копировать путь XPath:
В приведенном выше примере для извлечения ссылки к пути
/html/body/div/p[2]/a/ мы добавили указание для получения значения ссылки @href,
и индекс [0], поскольку результат возвращается в виде списка. Если @href
заменить на text(), программа вернет текст ссылки, а не сам URL:
Результат:
Парсер BeautifulSoup
Регулярные выражения и XPathпредоставляют огромные возможности
для извлечения нужной информации из кода страниц, но у них есть свои
недостатки: составлять Regex-шаблоны
сложно, а запросы XPath
хорошо работают только на страницах с безупречной, стандартной структурой. К
примеру, страницы Википедии не отличаются идеальной структурой, и использование
XPath для извлечения
нужной информации из определенных элементов статей, таких как таблицы infobox, часто оказывается
неэффективным. В этом случае оптимальным вариантом становится BeautifulSoup,
специально разработанный для парсинга HTML-кода.
Библиотека BeautifulSoup не входит в стандартный набор Python, ее нужно установить
самостоятельно:
В приведенном ниже примере мы будем извлекать из исходного
кода страницы уникальные ссылки, за исключением внутренних:
Результат:
При использовании XPath точно такой же результат даст следующий скрипт:
Имитация действий пользователя в браузере
При скрапинге сайтов очень часто требуется авторизация,
нажатие кнопок «Читать дальше», переход по ссылкам, отправка форм,
прокручивание ленты и так далее. Отсюда возникает необходимость имитации
действий пользователя. Как правило, для этих целей используют Selenium, однако есть и более легкое
решение – библиотека MechanicalSoup:
По сути, MechanicalSoup исполняет роль браузера без
графического интерфейса. Помимо имитации нужного взаимодействия с элементами
страниц, MechanicalSoup также парсит HTML-код, используя для этого все функции BeautifulSoup.
Воспользуемся тестовым сайтом http://httpbin.org/,
на котором есть возможность отправки формы заказа пиццы:
В приведенном выше примере браузер MechanicalSoup перешел по
внутренней ссылке http://httpbin.org/forms/post
и вернул описание полей ввода:
Перейдем к имитации заполнения формы:
Теперь форму можно отправить:
Результат можно вывести с помощью print(response.text):
Скрапинг и парсинг динамического контента
Все примеры, которые мы рассмотрели выше, отлично работают
на статических страницах. Однако на множестве платформ используется
динамический подход к генерации и загрузке контента – к примеру, для просмотра
всех доступных товаров в онлайн-магазине страницу нужно не только открыть, но и
прокрутить до футера. Для работы с динамическим контентом в Python нужно установить:
Если установка прошла успешно, выполнение этого кода приведет к
автоматическому открытию страницы:
Бывает, что даже после установки оптимальной версии драйвера
интерпретатор Pythonвозвращает ошибку OSError: [WinError 216] Версия
"%1" не совместима с версией Windows. В этом случае нужно
воспользоваться модулем webdriver-manager, который самостоятельно
установит подходящий драйвер для нужного браузера:
Имитация прокрутки страницы и парсинг данных
В качестве примера скрапинга и парсинга динамического сайта
мы воспользуемся разделом тестового
онлайн-магазина. Здесь расположены карточки с информацией о планшетах.
Карточки загружаются ряд за рядом при прокрутке страницы:
Пока страница не прокручена, полный HTML-код с информацией о планшетах
получить невозможно. Для имитации прокрутки мы воспользуемся скриптом 'window.scrollTo(0,
document.body.scrollHeight);'. Цены планшетов находятся в тегах h4 класса pull-right price, а
названия моделей – в тексте ссылок aкласса title. Готовыйкодвыглядиттак:
Результат:
Практика
Задание 1
Напишите программу для получения названий последних статей из блога издательства O’Reilly:
Пример результата:
Решение:
Задание 2
Напишите программу для определения 10 слов, которые чаще
всего встречаются в тексте сказки «Колобок» (без учета регистра). Предлоги
учитывать не нужно.
Ожидаемый результат:
Решение:
Задание 3
Напишите программу, которая на основе данных
таблицы создает список цитат из фильмов, выпущенных после 1995 года.
Ожидаемый результат:
Решение:
Задание 4
Напишите программу, которая извлекает
данные о моделях, конфигурации и стоимости 117-ти ноутбуков, и записывает
полученную информацию в csv
файл.
Ожидаемый результат:
Решение:
Задание 5
Напишите программу для скачивания полноразмерных обложек из профилей
книг на LiveLib. Обложки открываются после двойного клика по миниатюре:
Решение:
Задание 6
Напишите программу, которая составляет рейтинг топ-100
лучших триллеров на основе этого
списка.
Пример результата:
Решение:
Задание 7
Напишите программу, которая составляет топ-20 языков
программирования на основе рейтинга популярности TIOBE.
Пример результата:
Решение:
Задание 8
Напишите программу для получения рейтинга 250 лучших фильмов
по версии IMDb. Названия должны
быть на русском языке.
Пример результата:
Решение:
Задание 9
Напишите программу, которая сохраняет в текстовый файл
данные о фэнтези фильмах с 10 первых страниц
соответствующего раздела IMDb.
Если у фильма/сериала еще нет рейтинга, следует указать N/A.
Ожидаемый результат в файле fantasy.txt– 500 записей:
Решение:
Задание 10
Напишите программу для получения главных новостей (на
русском) с портала Habr. Каждый
заголовок должен сопровождаться ссылкой на полный текст новости.
Пример вывода:
Решение:
Заключение
Мы рассмотрели основные приемы работы с главными Python-инструментами для скрапинга и парсинга. Способы извлечения и обработки данных варьируются от
сайта к сайту – в некоторых случаях эффективнее использование XPath, в других – разбор с BeautifulSoup, а иногда может
потребоваться применение регулярных выражений.
В следующей главе приступим к изучению основ ООП (объектно-ориентированного программирования).
Комментарии