Пример парсера для web сайтов.

Часто возникает задача периодически парсить какой-нибудь сайт на наличие новой информации. Например, если ты пишешь агрегатор контента с новостного сайта или форума, в котором нет поддержки RSS. Проще всего написать скрепер на Питоне и разобрать полученный HTML через beautifulsoup или регулярками. Однако есть более элегантный способ — самому сделать недостающие API для сайта и получать ответы в привычном JSON, как будто бы у сайта есть нативный API.

Пример парсера для web сайтов.

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

ПОСТАНОВКА ЗАДАЧИ

Итак, наша задача: сделать API вида GET /posts, который бы отдавал десять последних статей  в JSON. Также нам нужно иметь возможность задавать сдвиг, то есть раз за разом получать следующие десять постов.

GET /posts

Ответ должен быть таким:

Пример парсера для web сайтов.

Также нужно иметь возможность получать следующие десять постов — со второй страницы, третьей и так далее. Это делается через GET-параметр вида GET /posts?page=2. Если page в запросе не указан, считаем его равным 1 и отдаем посты с первой страницы «Хакера». В общем, задача ясна, переходим к решению.

ФРЕЙМВОРК ДЛЯ ПАРСЕРА WEB САЙТОВ

WrapAPI — это довольно новый (пара месяцев от роду) сервис для построения мощных кастомных парсеров веба и предоставления к ним доступа по API. Не пугайся, если ничего не понял, сейчас поясню на пальцах. Работает так:

  1. Указываешь WrapAPI страницу, которую нужно парсить (в нашем случае главную «Хакера» — https://xakep.ru/).
  2. Говоришь, с какими параметрами обращаться к серверу, каким HTTP-методом (GET или POST), какие query-параметры передавать, какие POST-параметры в body, куки, хедеры. Короче, все, что нужно, чтобы сервер вернул тебе нормальную страничку и ничего не заподозрил.
  3. Указываешь WrapAPI, где на полученной странице ценный контент, который надо вытащить, в каком виде его представлять.
  4. Получаешь готовый URL для API вида GET /posts, который вернет тебе все выдранные с главной «Хакера» посты в удобном JSON!

Немного о приватности запросов

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

1. Каждый API-репозиторий (а соответственно, и все API-запросы в нем) можно сделать приватным. Они не будут показываться в общем списке уже созданных API на платформе WrapAPI. Просто выбери достаточно сложное имя репозитория, и шанс, что на него кто-то забредет случайно, сведется к минимуму.

2. Любой запрос к WrapAPI требует специального токена, который нужно получить в своей учетке WrapAPI. То есть просто так узнать URL к твоему репозиторию и таскать через

ПРИГОТОВЛЕНИЯ

Несколько простых шагов перед началом.
1. Идем на сайт WrapAPI, создаем новую учетку и логинимся в нее.
2. Устанавливаем расширение для Chrome (подойдет любой Chromium-based браузер), открываем консоль разработчика и видим новую вкладку WrapAPI. 3. Переходим на нее и логинимся.

Это расширение нам понадобится для того, чтобы перехватывать запросы, которые мы собираемся эмулировать, и быстро направлять их в WrapAPI для дальнейшей работы. По логике работы это расширение очень похоже на связку Burp Proxy + Burp Intruder.

Пример парсера для web сайтов.

ОТЛАВЛИВАЕМ ЗАПРОСЫ

Теперь нужно указать WrapAPI, какой HTTP-запрос мы будем использовать для построения нашего API. Идем на сайт «Хакера» и открываем консоль разработчика, переключившись на вкладку WrapAPI.

Для получения постов я предлагаю использовать запрос пагинации, он доступен без авторизации и может отдавать по десять постов для любой страницы «Хакера», возвращая HTML в объекте JSON (см. ниже).

Чтобы WrapAPI начал перехватывать запросы, нажми Start capturing requests и после этого выполни целевой запрос (на пагинацию). Плагин поймает POST-запрос к странице https://xakep.ru/wp-admin/admin-ajax.php с кучей form/urlencoded-параметров в теле, в том числе и номером страницы. Ответом на запрос будет JSON-объект с параметром content, содержащий закешированный HTML-код с новыми постами. Собственно, этот блок и нужно парсить WrapAPI.

КОНФИГУРИРУЕМ WRAPAPI

После того как ты выбрал нужное имя для твоего репозитория (я взял test001 и endpoint posts) и сохранил его на сервер WrapAPI через расширение для Chrome, иди на сайт WrapAPI и открывай репозиторий. Самое время настраивать наш API.

Переходи на вкладку Inputs and request. Здесь нам понадобится указать, с какими параметрами WrapAPI должен парсить запрашиваемую страницу, чтобы сервер отдал ему валидный ответ.

Аккуратно перебей все параметры из пойманной WrapAPI полезной нагрузки (POST body payload) в поле слева. Для всех параметров, кроме paginated, выставь тип Constant. Это означает, что в запросы к серверу будут поставляться предопределенные значения, управлять которыми мы не сможем (нам это и не нужно). А вот для paginated выставляй Variable API, указав имя page. Это позволит нам потом обращаться к нашему API по URL вида GET / posts?page=5 (с query-параметром page), а на сервер уже будет уходить полноценный POST со всеми перечисленными параметрами.

[ad name=»Responbl»]

Заголовки запроса ниже можно не трогать, я использовал стандартные из Chromium. Если парсишь не «Хакер», а данные с какого-нибудь закрытого сервера, можешь подставить туда нужные куки, хедеры, basic-auth и все, что нужно. Одним словом, ты сможешь настроить свой запрос так, чтобы сервер безо всяких подозрений отдал тебе контент.

УЧИМ WRAPAPI НЕДОСТАЮЩИМ ФИЧАМ

Теперь нужно указать WrapAPI, как обрабатывать полученный результат и в каком виде его представлять. Переходи на следующую вкладку — Outputs and response.

Небольшой глоссарий, прежде чем идти дальше:

  • Output — фильтр-постпроцессор контента, который принимает на входесырой ответ сервера, а возвращает уже модифицированный по заданным правилам. Они бывают нескольких типов. Самые часто используемые:
    • JSON выбирает содержимое указанного атрибута, который подан на вход JSON-объекта, и возвращает его значение как строку;
    • CSS выбирает элементы DOM по указанному CSS-селектору (например, ID или классу) и возвращает их значение, атрибут или весь HTML-тег целиком. Может вернуть как одну строку, так и массив найденных вхождений;
    • Regular expression выбирает вхождения по регулярному выражению, в остальном то же, что и предыдущий output;
    • HTTP Header выбирает значение HTTP-заголовка ответа сервера и возвращает его строкой;
    • Cookie выбирает значение Cookie, полученной в ответе от сервера, и возвращает его строкой.
  • Output Scenario — набор аутпутов, которые объединены в одну или несколько параллельных цепочек. По сути — почти весь набор препроцессоров, которые превращают серверный ответ в нужный нам формат.
  • Test case — сохраненный ответ сервера, на котором тестируются обработчики и подбирается нужная цепочка аутпутов.
    Создай новый test case, сохрани его под именем page1. Теперь посмотри, что вернул сервер. Это должен быть объект JSON, одно из полей которого содержит кусок HTTP-разметки с перечислением запрошенных постов.

Продолжение следует..

Click to rate this post!
[Total: 8 Average: 3.1]

Специалист в области кибер-безопасности. Работал в ведущих компаниях занимающихся защитой и аналитикой компьютерных угроз. Цель данного блога - простым языком рассказать о сложных моментах защиты IT инфраструктур и сетей.

1 comments On Пример парсера для web сайтов.

Leave a reply:

Your email address will not be published.