image Привет, Хаброжители! Если программирование напоминает волшебство, то веб-скрапинг — это очень сильное колдунство. Написав простую автоматизированную программу, можно отправлять запросы на веб-серверы, запрашивать с них данные, а затем анализировать их и извлекать необходимую информацию. Новое расширенное издание книги знакомит не только с веб-скрапингом, но и поможет собрать любого вида данные в современном Интернете. В части I основное внимание уделено механике веб-скрапинга: как с помощью Python запрашивать информацию с веб-сервера, производить базовую обработку серверного отклика и организовать автоматизированное взаимодействие с сайтами. В части II исследованы более специфичные инструменты и приложения, которые пригодятся при любом сценарии веб-скрапинга. — Разбирайте сложные HTML-страницы. — Разрабатывайте поисковые роботы с помощью фреймворка Scrapy. — Изучайте методы хранения данных, полученных с помощью скрапинга. — Считывайте и извлекайте данные из документов. — Очищайте и нормализуйте плохо отформатированные данные. — Читайте и пишите информацию на естественных языках. — Освойте поиск по формам и логинам. — Изучите скрапинг JavaScript и работу с API. — Используйте и пишите программы для преобразования изображений в текст. — Учитесь обходить скрапинговые ловушки и блокаторы ботов. — Протестируйте собственный сайт с помощью скрапинга.

Веб-краулинг с помощью API


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

По мере распространения методов генерации и загрузки контента с помощью JavaScript и Ajax описанная выше ситуация становится все менее привычной. В главе 11 мы рассмотрели один из способов решения указанной проблемы: использование Selenium для автоматизации браузера и извлечения данных. Это легко сделать. Это работает почти всегда.

Проблема в том, что, когда у вас в руках есть столь мощный и эффективный «молоток», как Selenium, каждая задача веб-скрапинга начинает походить на гвоздь.

В текущей главе вы узнаете о том, как, минуя весь этот JavaScript (не выполняя и даже не загружая его!), получить прямой доступ к источнику данных — к интерфейсам API, которые генерируют эти данные.

Краткое введение в API

Существует бесчисленное количество книг, докладов и руководств о нюансах API REST, GraphQL21, JSON и XML, однако все они основаны на одной простой концепции. API определяет стандартизованный синтаксис, который позволяет одной программе взаимодействовать с другой, даже если они написаны на разных языках или имеют разную структуру.

Данный раздел посвящен веб-API (в особенности позволяющим веб-серверу взаимодействовать с браузером), и здесь мы будем понимать под API именно этот тип интерфейсов. Но вы можете учесть, что в других контекстах API также является обобщенным термином, который может обозначать, например, интерфейс, позволяющий программе на Java взаимодействовать с программой на Python, работающей на том же компьютере. API не всегда означает «интерфейс через Интернет» и не обязательно должен включать в себя какие-либо веб-технологии.

Веб-API чаще всего используются разработчиками для взаимодействия с широко разрекламированными и хорошо документированными открытыми сервисами. Например, американский кабельный спортивный телевизионный канал ESPN предоставляет API (http://www.espn.com/apis/devcenter/docs/) для получения информации о спорт­сменах, счетах в играх и др. У Google в разделе для разработчиков (https://console.developers.google.com) есть десятки API для языковых переводов, аналитики и геолокации.

В документации всех этих API обычно описываются маршруты или конечные точки в виде URL, которые можно запрашивать, с изменяемыми параметрами, либо входящими в состав этих URL, либо выступающими в роли GET-параметров.

Например, в следующем URL pathparam является параметром пути:

example.com/the-api-route/pathparam

А здесь pathparam является значением параметра param1:

example.com/the-api-route?param1=pathparam

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

Ответ на API-запрос обычно возвращается в формате JSON или XML. В настоящее время JSON гораздо популярнее, чем XML, но последний иногда тоже встречается. Многие API позволяют выбирать тип ответа, обычно с помощью еще одного параметра, определяющего, какой тип ответа вы хотите получить.

Вот пример ответа на API-запрос в формате JSON:

{"user":{"id": 123, "name": "Ryan Mitchell", "city": "Boston"}}


А вот ответ на API-запрос в формате XML:

<user><id>123</id><name>Ryan Mitchell</name><city>Boston</city></user>


Сайт ip-api.com (http://ip-api.com/) имеет понятный и удобный API, который преобразует IP-адреса в реальные физические адреса. Вы можете попробовать выполнить простой запрос API, введя в браузере следующее

ip-api.com/json/50.78.253.58

В результате вы получите примерно такой ответ:

{"ip":"50.78.253.58","country_code":"US","country_name":"United States",
"region_code":"MA","region_name":"Massachusetts","city":"Boston",
"zip_code":"02116","time_zone":"America/New_York","latitude":42.3496,
"longitude":-71.0746,"metro_code":506}

Обратите внимание: в запросе есть параметр пути json. Чтобы получить ответ в формате XML или CSV, нужно заменить его на соответствующий формат:

ip-api.com/xml/50.78.253.58
ip-api.com/csv/50.78.253.58


API и HTTP-методы

В предыдущем разделе мы рассмотрели API, отправляющие на сервер GET-запрос для получения информации. Существует четыре основных способа (или метода) запроса информации с веб-сервера через HTTP:

— GET;
— POST;
— PUT;
— DELETE.

Технически типов запросов больше четырех (например, еще есть HEAD, OPTIONS и CONNECT), но они редко используются в API и маловероятно, что когда-либо встретятся вам. Подавляющее большинство API ограничиваются этими четырьмя методами, а иногда даже какой-то их частью. Постоянно встречаются API, которые используют только GET или только GET и POST.

GET — тот запрос, который вы используете, когда посещаете сайт, введя его адрес в адресной строке браузера. Обращаясь по адресу ip-api.com/json/50.78.253.58, вы применяете именно метод GET. Такой запрос можно представить как команду: «Эй, веб-сервер, будь добр, выдай мне эту информацию».

Запрос GET по определению не вносит изменений в содержимое базы данных сервера. Ничего не сохраняется и ничего не изменяется. Информация только считывается.

POST — запрос, который используется при заполнении формы или отправке информации, предположительно предназначенной для обработки серверным скриптом. Каждый раз, авторизуясь на сайте, вы делаете POST-запрос, передавая имя пользователя и (как мы надеемся) зашифрованный пароль. Делая POST-запрос через API, вы говорите серверу: «Будь любезен, сохрани эту информацию в базе данных».

Запрос PUT при взаимодействии с сайтами используется реже, но время от времени встречается в API. Этот запрос применяется для изменения объекта или информации. Например, в API можно задействовать запрос POST для создания пользователя и запрос PUT для изменения его адреса электронной почты.

Запросы DELETE, как нетрудно догадаться, служит для удаления объекта. Например, если отправить запрос DELETE по адресу myapi.com/user/23, то будет удален пользователь с идентификатором 23. Методы DELETE нечасто встречаются в открытых API, поскольку те в основном создаются для распространения информации или чтобы позволить пользователям создавать или публиковать информацию, но не удалять ее из баз данных.

В отличие от GET запросы POST, PUT и DELETE позволяют передавать информацию в теле запроса, в дополнение к URL или маршруту, с которого запрашиваются данные.
Как и ответ, получаемый от веб-сервера, эти данные в теле запроса обычно представляются в формате JSON или реже в формате XML. Конкретный формат данных определяется синтаксисом API. Например, при использовании API, который добавляет комментарии к сообщениям в блоге, можно создать следующий PUT-запрос:

example.com/comments?post=123

с таким телом запроса:

{"title": "Great post about APIs!", "body": "Very informative. Really helped me out with a tricky technical challenge I was facing. Thanks for taking the time to write such a detailed blog post about PUT requests!", "author": {"name": "Ryan Mitchell", "website": "http://pythonscraping.com", "company": "O'Reilly Media"}}


Обратите внимание: идентификатор сообщения в блоге (123) передается в качестве параметра в URL, а контент создаваемого нами комментария — в теле запроса. Параметры и данные могут передаваться и в параметре, и в теле запроса. Какие параметры обязательны и где передаются — опять-таки определяется синтаксисом API.

Подробнее об ответах на API-запросы

Как мы видели в примере с сайтом ip-api.com в начале данной главы, важной особенностью API является то, что эти интерфейсы возвращают хорошо отформатированные ответы. Наиболее распространенные форматы ответов —XML (eXtensible Markup Language — расширяемый язык разметки) и JSON (JavaScript Object Notation — нотация объектов JavaScript).

В последние годы JSON стал намного популярнее, чем XML, по нескольким основным причинам. Во-первых, файлы JSON обычно меньше, чем хорошо проработанные файлы XML. Сравните, например, следующие данные в формате XML, занимающие 98 символов:

<user><firstname>Ryan</firstname><lastname>Mitchell</
lastname><username>Kludgist</username></user>

А теперь посмотрите на те же данные в формате JSON:

{"user":{"firstname":"Ryan","lastname":"Mitchell","username":"Kludgist"}}


Это всего 73 символа, на целых 36 % меньше, чем те же данные в формате XML.
Конечно, вероятен аргумент, что XML можно отформатировать так:

<user firstname="ryan" lastname="mitchell" username="Kludgist"></user>


Но это не рекомендуется, поскольку такое представление не поддерживает глубокое вложение данных. И все равно запись занимает 71 символ — примерно столько же, сколько эквивалентный JSON.

Другая причина, по которой JSON так быстро становится более популярным, чем XML, связана с изменением веб-технологий. Раньше получателями API были по большей части серверные скрипты на PHP или .NET. Сейчас вполне может оказаться, что получать и отправлять вызовы API будет фреймворк наподобие Angular или Backbone. Серверным технологиям до определенной степени безразлично, в какой форме к ним поступают данные. Однако библиотекам JavaScript, таким как Backbone, проще обрабатывать JSON.

Принято считать, что API возвращают ответ либо в формате XML, либо в формате JSON, однако возможен любой другой вариант. Тип ответа API ограничен только воображением программиста, создавшего этот интерфейс. Еще один типичный формат ответа — CSV (как видно из примера с ip-api.com). Отдельные API даже позволяют создавать файлы. Можно отправить на сервер запрос, по которому будет сгенерировано изображение с наложенным на него заданным текстом, или же запросить определенный файл XLSX или PDF.

Некоторые API вообще не возвращают ответа. Например, если отправить на сервер запрос для создания комментария к записи в блоге, то он может вернуть только HTTP-код ответа 200, что означает: «Я опубликовал комментарий; все в порядке!» Другие запросы могут возвращать минимальный ответ наподобие такого:

{"success": true}


В случае ошибки вы можете получить такой ответ:

{"error": {"message": "Something super bad happened"}}


Или же, если API не очень хорошо сконфигурирован, вы можете получить не поддающуюся анализу трассировку стека или некий текст на английском. Отправляя запрос к API, как правило, имеет смысл сначала убедиться, что получаемый ответ действительно имеет формат JSON (или XML, или CSV, или любой другой формат, который вы ожидаете получить).

Об авторе

Райан Митчелл (Ryan Mitchell) — старший инженер-программист в бостонской компании HedgeServ, в которой она разрабатывает API и инструменты для анализа данных. Райан окончила Инженерно-технический колледж им. Франклина В. Олина, имеет степень магистра в области разработки программного обеспечения и сертификат по анализу и обработке данных, полученный на курсах повышения квалификации при Гарвардском университете. До прихода в HedgeServ Райан трудилась в компании Abine, где разрабатывала веб-скраперы и средства автоматизации на Python. Регулярно выступает консультантом проектов по веб-скрапингу для розничной торговли, сферы финансов и фармацевтики. По совместительству работает консультантом и внештатным преподавателем в Северо-Восточном университете и Инженерно-техническом колледже им. Франклина В. Олина.

Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок

Для Хаброжителей скидка 25% по купону — Python

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.