Привет всем,
На Хабре было множество статей про Парсинг сайтов, или правильнее было бы сказать Краулинг (для придир — Краулинг + Парсинг).
Тема эта волнительна для любой e-Commerce площадки: велик соблазн взять уже готовый контент у конкурентов, сэкономив время и средства. Но пройдя путь наполнения значительных по размеру каталогов, каждый осознает доступность информации, и захочет обзавестись защитой. Ведь средства в ведение каталогов вкладываются значительные.
Есть и полезные краулеры — пауки поисковых систем, агрегаторы новостей, системы мониторинга и т.п. Защита не должна каким-либо образом повлиять на работу этих очень даже ожидаемых и уважаемых программ.
Учитывая открытость WWW — очевидно, 100%-ной защиты не получится. Сайты должны быть легко доступны для людей (и для полезных роботов тоже), а поведение скрипта может быть настолько хитроумным, что отличить от человека его будет непросто. Однако защита по крайне мере способна 1) создать трудности, 2) значительно — в сотни раз — снизить производительность краулеров. Учитывая, что задачи краулинга/парсинга поручают обычно не самым опытным разработчикам — есть вероятность, что они не разгадают все хитрости защиты и найдут какой-то другой источник, который станет для них более легкой добычей, отстанут таким образом от вашего сайта.
Не брезгуем Watermark-ами
В основном краулеры создаются с целью скопировать каталоги товаров. В этом случае установка «водяных знаков» на полноразмерные изображения продуктов — уже серьезная защита. На Хабре, впрочем, были уже статьи на тему снятия водяных знаков. По крайне мере, убрать простой текстовый watermark в пакетном режиме — не проблема.
Используйте watermark на основе полупрозрачной картинки, желательно с тонким полностью непрозрачным контуром.
Программная защита
Не нужно защищать все подряд разделы, нужно сосредоточиться на защите наиболее важного контента (непосредственно, каталога товаров).
Ведь хорошая защита потребует логики, а соответственно — жертв в виде сколько-то миллисекунд на отдачу страницы сервером. К тому же есть риски спутать реального человека с краулером — такая ситуация должна быть разрешена по возможности максимально деликатно (задать какой-то вопрос, запросить ввод captcha).
Сразу отбросим простые механизмы — даже пакетные краулеры умеют сейчас логиниться через формы, маскироваться под браузер, сохранять и передавать куки. Тем более, если краулер создается программистом адресно под сайт с использованием библиотеки CURL.
Особое внимание следует уделить краулерам поисковых систем — аккуратно в коде защиты прописать все известные данные о поисковых ботах, индексация которых важна для продвижения сайта в Сети. Обычно такие боты имеют определенную сигнатуру user-agent в http-заголовке — например Googlebot.
Чтобы не рисковать индексацией сайта, скорей всего придется дать максимально широкую дорогу всем запросам с определенными сигнатурами, ну и заодно оставить широчайших размеров дыру для остальных краулеров. Краулеру останется только правильно представиться.
Впрочем, можно еще в отдельных ветках кода попытаться проверить поведение бота — обычно нормальные поисковые системы достаточно аккуратны с запросами индексирования, стремясь не создавать чрезмерную нагрузку на сайт.
Также по причине необходимости холить и лелеять эти уважаемые поисковые боты мы вынуждены отказаться от нескольких элегантных методов защиты, особенно «PHP-код в картинке» (см
An image to download).
IP-адрес клиента — единственная объективная информация, которая доступна о клиенте на сервере. Возможности анализа по IP также очень ограничены — никогда не знаем, какая внутренняя сеть может скрываться за IP — может быть один домашний компьютер, а может быть офис компании со штатом 1000 человек. Блокировка IP также опасна — IP может быть динамически выделенным, и в последующем назначен другому случайному пользователю.
Важно определиться, что мы делаем в случае обнаружения нежелательного краулера по определенному IP-адресу. Мы якобы блокируем IP — это значит что при следующем обращении к защищенным ресурсам (страницам каталога) пользователь с таким IP должен будет пройти проверку — ввести captcha. Если пользователь вводит captcha (можно еще и ограничение по времени поставить) — IP-адрес «разблокируется», то есть
update ips set locked = false, verified = now() where ip = (ip);
Пр этом сохраняется момент времени проверки в поле verified, и последующие 3 часа система не будет анализировать данный IP, и соответственно — не будет блокировать.
Тут мы оставляем еще одну зияющую дыру — зная это логику, запустил краулер, дождался запроса проверки, прошел верификацию вручную — и имеешь 3 часа полной свободы. Расчет может быть только на то, что нервы на той стороне сдадут раньше — ведь у краулера много других проблем для отладки — например вариации структуры html от страницы к странице… а тут еще надо серверную логику угадать.
В БД системы потребуется простая таблица:
create table ips (
ip int unsigned,
created timestamp default now(),
updated timestamp, --заполняется в триггере BEFORE UPDATE, NEW.updated = now();
locked boolean, --IP "заблокирован"
verified timestamp, -- IP последний раз проверен заданный в момент времени
primary key(ip)
);
Раз в сутки таблицу можно очищать от левых записей: delete from ips where updated < yesterday() and locked = false;
Цель метода — выявление признаков поведения краулера путем анализа активности.
Краулер постарается каким-либо способом составить список интересующих его ресурсов, затем по очереди загружать страницу каждого ресурса(товара).
Для фиксации доступа к интересующим ресурсам создадим еще одну таблицу:
create table ipstats (
ipstats_id bigserial, -- PK
ip int unsigned,
created timestamp default now(), -- время доступа
delta integer, -- интервал в миллисекундах между текущим и предыдущим доступом - надо вычислить в триггере при заполнении
primary key(ipstats_id)
);
Вооружившись агрегатными функциями, будем проводить анализ после накопления минимальной статистики (в нашем случае это 100 записей в ipstats).
Скорей всего краулер
Основной и в нашем случае единственный критерий — это временная равномерность запросов:
( select count(*) from ipstats where ipstats.ip = (ip) and abs(dt - (select avg(ipstats2.delta) from ipstats as ipstats2 where ipstats2.ip = (ip))) < 10000 ) >= 0.8 * (select count(*) from ipstats where ip = (ip));
Проще говоря — если отклонение от среднего значения дельты у 80% запросов меньше 10 секунд (может быть другая константа).
Если так — «блокируем IP»:
update ips set locked = true where ip = (ip);
табличку ipstats для ip чистим и до «разболкировки» IP статистику по нему не ведем:
delete from ipstats where ip = (ip);
Есть ли риск, что попадут под раздачу реальные пользователи? Безусловно, есть — но ничего страшного, введут капчу и будут дальше работать.
Точно не краулер
1.
( select count(*) from ipstats where ip = (ip) and delta > 180000 ) > 0.1 * ( select count(*) from ipstats where ip = (ip) );
другими словами, если количество запросов с дельтой > 180 сек составляет более 10% от общего числа запросов.
2.
(select avg(delta) from ipstats where ip = (ip)) > 60000
если средняя дельта между запросами более 60 сек. Даже если это и краулер, то очень совсем не торопится, а значит не стремится вас обогнать и вреда от него никакого.
Если одно из этих условий сработало — чистим ipstats по ip:
delete from ipstats where ip = (ip)
Для того, кому логика покажется банальной, можно мучить табличку ipstats любым способом, опробовать любые другие критерии. Не забудьте только создать для нее индексы, и следите в вебмастерах Google и Яндекс за индексацией.
комментарии (38)