Парсинг результатов поиска Google (без проблем с блокировкой IP)
Table Of Content
Метод парсинга, устойчивый к блокировке IP
Отказ от ответственности: используйте предложенные здесь идеи на свой страх и риск.
Проблема блокировки IP
Если вы занимаетесь парсингом веб-сайтов, то, вероятно, знаете, что сайты не любят автоматические боты, которые посещают их только для сбора информации. Они настроили системы, которые могут определить, что ваша программа не является реальным человеком, и после нескольких запросов, поступающих из вашего скрипта, обычно появляется ужасное сообщение HTTP 429 Too Many Requests Error. Это означает, что ваш IP-адрес был заблокирован на определенное время. Ваш бот может идти домой и плакать.
Парсинг Святого Грааля
Поисковая система Google - очевидная цель для выполнения парсинга. Она предоставляет доступ к миллионам URL-адресов, ранжированных по релевантности вашему запросу. Но ребята из Google очень хороши в обнаружении ботов, поэтому это сайт особенно сложно спарсить. Однако я представляю здесь обходной путь, который может обойти барьеры Google.
Побеждайте свои битвы изнутри
Идея очень проста и может быть сформулирована несколькими ключевыми моментами:
- Если вы напрямую парсите Google Search, вас поймают через некоторое время и вы получите ошибку HTTP 429.
- Google App Engine позволяет развертывать сервисы в облаке. Вместо их запуска на конкретном хосте они динамически распределяются по машинам, называемым контейнерами.
- Каждый раз, когда вы повторно развертываете свой сервис, он находится в другом контейнере с другим IP-адресом.
- Мы можем создать парсер и запустить его из App Engine. Когда нас поймают, мы сохраняем состояние, повторно развертываем наш парсер и продолжаем парсить с нового контейнера.
Архитектура системы
Хорошо, как мы собираемся это делать? Мы будем использовать модель "мастер-слейв" для архитектуры. Слейв будет развернут в облаке и будет выполнять задачи парсинга по требованию. Мастер будет находиться на вашем локальном компьютере и будет оркестрировать слейва (или слейвов, хотя мы не пойдем так далеко), отправляя задачи.
Когда слейв в конечном итоге не справится с задачей из-за ошибки "Слишком много запросов", мастер уничтожит его и развернет нового слейва, который продолжит задачу. Поскольку у него будет новый IP-адрес, Google не узнает его как предыдущий парсер. (Я только что понял, что все это может показаться довольно непонятным для людей, не знакомых с жаргоном. Пожалуйста, не поймите меня неправильно и ознакомьтесь с моделью "мастер-слейв")
В общем, картинка стоит тысячи слов.
Реализация на практике
Сначала нам нужно настроить проект в Google Cloud. Только после этого мы сможем создать Мастер и Слейв.
Настройка Google Cloud
Я не буду вдаваться в подробности, но для начала вам нужно настроить Google Cloud и выполнить несколько действий:
- Войдите в консоль Google Cloud и создайте новый проект.
- Включите выставление счетов**… **(не волнуйтесь, вам не будет начисляться плата, пока вы не превысите щедрый бесплатный лимит Google).
- Создайте стандартное приложение App Engine
- Установите gcloud SDK** **для взаимодействия с вашим проектом из терминала.
- Создайте ключ служебного аккаунта и загрузите его в формате JSON для аутентификации в Google Cloud.
Создание Slave
Наш Slave будет использовать Flask в качестве основы для коммуникации и объект Scraper для выполнения основной работы. Оба (приложение Flask и Scraper) будут работать в отдельных процессах и обмениваться данными через Pipe. Приложение Flask будет использовать его для отправки запрошенных заданий Scraper'у, а Scraper будет отвечать со своим состоянием при изменении.
Класс Slave
Как вы можете видеть в методе scrape
, Slave просто использует объект Scraper()
, который получает задание (словарь с параметрами, которые нигде не определены) и возвращает DataFrame. Это дает много свободы для реализации Scraper()
по вашему усмотрению. Для Scraper'а, который я написал в качестве примера (здесь), задание определяется следующим образом:
job = {"query": "Футбол", "start": "2020-01-01", "end": "2020-03-29"}
Когда мой Scraper получает это задание, он будет получать URL-адреса топ-10 результатов для "футбола", фильтруя каждую дату между "start" и "end". То есть топ-10 для "2020-01-01", топ-10 для "2020-01-02"... Я использую пакет "googlesearch", который очень удобен.
Flask-приложение
Для сервера определены три маршрута:
/start
: вызывается мастером в самом начале. Он создает дочерний процесс Scraper, который работает в фоновом режиме./job
: передает задания от мастера к слейву с параметрами, закодированными в URL./state
: сообщает мастеру текущее состояние слейва (“простаивает”, “занят” или “обнаружено парсинг”).
Создание Мастера
Основным методом в классе Master (нет никакой игры слов) является orchestrate()
, который периодически проверяет состояние слейва с помощью check_slave_state
и отправляет задание, если он свободен.
Если состояние равно обнаружен парсинг
, то вызывается restart_machine()
и приложение развертывается. Мастер отслеживает задание, которое вызвало сбой, и повторно отправляет его слейву, как только он снова работает.
Если слейв перестает отвечать (нет ответа
), это означает, что он находится в процессе развертывания.
Хорошо, но покажите мне код
Хорошо, вы можете взглянуть на мой репозиторий на GitHub. Чтобы протестировать его локально, вам просто нужно выполнить следующие шаги:
pip install -r requirements.txt
для установки всех необходимых зависимостейpython master.py
для запуска мастераgunicorn -b :8080 slave:app --timeout 360000 --preload
для запуска слейва (команда, используемая для запуска сервера в Google Cloud)
Не забудьте запустить мастер и слейв из разных сеансов терминала. Пример выполнения мастера выглядит следующим образом:
Развертывание slave на Google Cloud
После того, как вы все протестировали локально, последний шаг - развернуть slave на App Engine из вашего терминала. Сначала вам нужно войти в Google Cloud через командную строку gcloud (выполните gcloud init
и выберите свой проект). Затем волшебная команда для развертывания slave...
gcloud app deploy
Она берет конфигурацию из app.yaml
и использует ее для создания вашего экземпляра. Проверьте файл и измените его, чтобы он соответствовал вашему проекту.
Надеюсь, вы найдете это полезным, и не стесняйтесь задавать мне вопросы в разделе комментариев или по электронной почте.