Тройное комбо в области парсинга данных, или как мы сделали кроулер сайтов на основе ИИ, двух тысяч прокси и Chrome API

в 14:27, , рубрики: Google Chrome, php, python, машинное обучение

Задача стояла следующая: собрать данные с израильской доски объявлений, которая блокирует на входе все страны кроме Израиля и некоторых европейских (исключая Россию). Далее блокирует всех, кто ведёт себя хотя бы сколько-нибудь подозрительно. Например, при запросе страницы сайта чаще 1 раза в 3 секунды уже есть возможность попасть в бан-лист. Далее, чтобы узнать номер телефона автора объявления (без которого все остальные бесполезны) нужно пройти капчу на иврите (местный язык). Т.е. доступную только евреям. Иными словами, создатели сайта явно против того, чтобы их парсили. Но мы решили попробовать.

Сначала сделали полуавтоматический режим. Написали расширение для Google Chrome, которое парсило страничку объявления после прохождения капчи человеком. По ходу дела пришлось подучить иврит. Посадили человека собирать данные. Через пару часов выясняется, что сайт заблокировал нашего человека. Как в итоге выяснилось, по IP, из-за слишком частого перехода по страницам. Поставили ему VPN с примерно 20-ю странами. Хватило на пару дней — сайт располагает удивительно мощным алгоритмом вычисления парсеров. Добавили в расширение Chrome очистку куков и кеша при каждом посещении. Сработало, но снова только на неделю. В отчаянии хотели было звонить заказчику и плакаться о том, что ничего не получится. Но решили попробовать кое-что ещё. И вот тут начинается самое интересное.

Ещё за полгода до этого меня заинтересовала тема ИИ и нейросетей. Написал даже простенький парсер изображений, который определял наличие человеческой физиономии на фотографии. И тут в голову пришла мысль — почему бы не использовать машинное зрение для прохождения капчи. На сайте, с которым мы боролись, капча не сложная. Больше узконаправленная на евреев, чем сложная. Было решено попробовать написать парсер для неё, однако перед этим нужно было решить вопрос блокировки по IP. VPN не подходит, как уже стало известно. Следующее, что пришло в голову — прокси. Долго мучились с с тем, чтобы найти список годных проксей. Бесплатные все не подходят — они фактически не работают. Стали пробовать платные. Картина не намного лучше, но всё же. Нашли в итоге русский сайт с более-менее рабочими серверами. Прикрутили их к cURL через API и написали сборщик данных на PHP. Поставили его на cron. Скрипт просто брал из 800 прокси случайный и пробовал собрать через него данные. Если без результата — брал следующий и по кругу. Таким образом удавалось собирать все данные кроме номера телефона, который под капчей. Неделю парсер проработал без блокировок, что можно считать успехом. Дальше встал вопрос капчи.

При написании парсера изображений я пользовался гугловской библиотекой TensorFlow. На её основе была построена и обучена нейросеть на питоне, которая определяла цифры на картинке, изображенные рукописным шрифтом на иврите. Заняла разработка сей вещи столько времени, денег и нервов, что заказчик до сих пор вспоминает это со слезами. Однако в итоге парсер верно читал капчу примерно в 7 случаях из 10, чего вполне достаточно для прохождения. Дальше встал новый вопрос: как брать изображение капчи у сайта через cURL, если капча асинхронная, а cURL не умеет выполнять скрипты?

Здесь мы вспомнили про созданное ранее расширение для Google Chrome. С его помощью был выработан примерно следующий алгоритм: cURL собирает все данные кроме номера телефона, далее передаёт управление в постоянно работающее браузерное расширение (да, костыль, но на тот момент было самым быстрым решением), там вычисляется изображение капчи, отдаётся на сервер в нейросеть, считывается и возвращается в расширение, где в итоге открывается и сохраняется номер телефона в базу. Всё.

Данный кроулер вот уже несколько месяцев успешно собирает данные, что с лихвой отбило сумму, отданную заказчиком за его разработку (конкуренты платят реальным людям за эту работу). А мы взялись за новый проект в области ИИ.

Автор: незнакомец

Источник

Поделиться

* - обязательные к заполнению поля