Обратился заказчик, с проблемой, что его сборщик не
можетсправитьсяс защитой "incapsula".
В двух словах, вместо кода страницы возвращается javascript код,
при выполнении которого, идет запрос на сервера инкапсулы,
проверяютсякакие-топараметры браузера и в случае если браузер
признан валидным, отдается страница и некоторые cookie.
Подробное описание есть на сайте разработчика
(www.imperva.com)
Добавление обработчика javascript, так же как и другие решения,
предлагаемые гуглом(например поднять свои сервера), показалось
слишком сложными\долгими. Selenium же, как оказалось, прекрасно
обходит, данную защиту, но так как данных много и собирать в один
поток, (или даже переключаясь между вкладками) не хотелось, а
запускать несколько браузеров не хватало ресурсов было решено
написать proxy сервер.
Так как нагрузка менялась, в зависимости от времени суток и других
условий, было решено сделать масштабируемую веб часть через
комбинацию Nginx + uwsgi + flask. Запускать на каждый,
воркер,версию Seleniumпоказалосьслишком затратным, поэтому вынести
Selenium было решено в отдельный сервис, со связью между блоками
через Redis. Чтобы максимальноупроститьреализацию, запросы
выполняются синхронно.
Структура проекта
uwsgi.ini файл с конфигурацией. Существует куча статей по
настройке, поэтому я опущу этот этап. На всякий случай в конце
статьи оставлю ссылку по настройке(
Микросервисselenium:
Файл gecko/Sel.py
Класс с sellenium модулем. Реализована инициализация, запуск
selenium безгуи, и авторизация на сайте (проект изначально писался
под конкретный сайт). Также в цикле обновляется главная страница
для получения обновленных cookie и в случае появления сообщения в
очереди Redis. Cookie выгружаются и хранятся в общем словаре, в
redis. Получение cookie отселениумавынесены в callback функции.
Микросервис API:
Файлы в папке src
Во фласке реализован только базовый функционал, слушающий 1
url:
@app.route('/', methods=['GET', 'POST'])
Сервер ожидает запрос, с параметром url с urlом, который необходимо получать, и с телом запроса в случае post запроса.
Например:
http://127.0.0.1:5000/?url=https://www.example.com/vehicledetails/34313441?RowNumber=0&
Запрос без изменений и модификаций передается дальше, что
впрочем, не мешает редактировать его, в случае необходимости.
В файле request.py реализована следующая логика.
Инициализацияпараметров для библиотеки requests,такие
какхедеры.
Инициализация подключения к Redis, а также Post, Get запросы c
помощью библиотеки reqests.
При получении сообщения, происходит обновление cookie, полученных
от Selenium сервиса.
Надопонимать, что это лишь заготовка. Такие вопросы как https,
настройка сервера, дополнительная обработка ошибок, авторизация и
т.д я намеренно оставил за пределами статьи. Дополнительная
кастомизация и доработка работы с ресурсом, также остается на
стороне пользователя.