Web crawling что это
Как работает веб-краулер (поисковой паук)
Содержание
Как работает веб-краулер?
Функционирование поискового робота строится по тем же принципам, по которым работает браузер. Паук заходит на сайты, оценивает содержимое страниц, переносит их в базу поисковой системы, затем по ссылкам переходит на другой ресурс, повторяя вызубренный алгоритм действий. Результат этих путешествий — перебор веб-ресурсов в строгой последовательности, индексация новых страниц, включение неизвестных сайтов в базу. Попадая на ресурс, паук находит предназначенный для него файл robots.txt. Это необходимо, чтобы сократить время на попытки индексации закрытого контента. После изучения файла робот посещает главную страницу, а с нее переходит по ссылкам, продвигаясь в глубину. За одно посещение краулер редко обходит сайт целиком и никогда не добирается до глубоко размещенных страниц. Поэтому чем меньше переходов ведет к искомым страницам с главной, тем быстрее они будут проиндексированы.
Отметим, что веб-паук не делает анализа контента, он лишь передает его на серверы поисковых систем, где происходит дальнейшая оценка и обработка. Краулеры регулярно посещают сайты, оценивая их на предмет обновлений. Новостные ресурсы индексируются с интервалом в несколько минут, сайты с аналитическими статьями, обновляемые раз в 4 недели, — каждый месяц и т. п.
Как самостоятельно проиндексировать сайт?
Сайты, на которые не ведет достаточный объем внешних ссылок, паук не проиндексирует без вмешательства вебмастера. Чтобы ресурс попал в поисковую выдачу, потребуется добавить его в карту посещений краулера. Оперативная индексация сайта возможна при размещении систем веб-аналитики от поисковых сервисов: Google Analytics, Яндекс.Метрика, Рейтинг@Mail.ru.
Положительно влияют на индексацию сайта ссылки из социальных медиа, новостных порталов. Однако большой объём покупных ссылок грозит санкциями поисковых систем, к примеру, «Минусинска» от «Яндекса».
Зачем краулеров маскируют под реальных пользователей?
Владельцы ботов часто не готовы смириться с ограничениями, установленными на ресурсах. Представим ситуацию, когда паук создан для отбора и анализа сведений о 10 000 популярных картинах сайта http://kinopoisk.ru. Для отражения информации по каждому фильму потребуются, минимум, 10 запросов, в процессе необходимо:
1) открыть страницу картины для чтения описания; 2) посетить разделы «Премьеры», «Кадры», «Актеры», «Студии», «Награды»; 3) посетить имеющиеся подразделы.
С учетом ожиданий между запросами в 10 секунд на просмотр страниц уйдет 11 суток. К тому же 10 000 объектов — начальная ставка, если задача разработчиков провести обучение машины. По этой причине новых пауков маскируют под реальных пользователей. И тогда краулер в заголовке запроса представляется как браузер. Кроме скромных тружеников статистики, существуют спам-боты, которые извлекают с веб-страниц почтовые адреса для своих рассылок.
«Яндекс» обучил поискового робота анализировать JavaScript и CSS-код
«Яндекс» научил своего бота понимать коды JavaScript и CSS. Новый талант используется при анализе содержимого сайтов, при этом проверяется не только контент, но и его CSS и JavaScript коды. Новый тип индексации на начальном этапе применяется только к отдельным сайтам. Функция позволит пауку оценивать содержимое ресурса на более глубоком уровне и видеть его глазами пользователя. К перечню параметров, по которым оцениваются сайты, добавляется удобство пользовательского интерфейса.
Дополнительно краулер получит доступ к части контента, ранее закрытой для анализа. Полученные данные могут использоваться для сравнения с информацией, которая в текущий момент влияет на позицию ресурса в поисковой выдаче.
Пишем краулер на раз-два 1.0
Веб-краулер (или веб-паук) — это важная составная часть поисковых систем для обхода веб-страниц с целью занесения информации о них в базы данных, в основном, для их дальнейшей индексации. Такая штука есть у поисковиков (Google, Yandex, Bing), а также у SEO-продуктов (SEMrush, MOZ, ahrefs) и не только. И штука эта — довольно интересная: как в плане потенциала и вариантов использования, так и для технической реализации.
Этой статьей мы начнем итеративно создавать свой велосипед краулер, разбирая многие особенности и встречая подводные камни. От простой рекурсивной функции до масштабируемого и расширяемого сервиса. Должно быть интересно!
Интро
Итеративно — значит в конце каждого выпуска ожидается готовая к использованию версия «продукта» с условленными ограничениями, характеристиками и интерфейсом.
В качестве платформы и языка выбраны node.js и JavaScript, потому что это просто и асинхронно. Конечно, для промышленной разработки выбор технологической базы должен опираться на бизнес-требования, ожидания и ресурсы. В качестве же демонстрации и прототипа эта платформа — вполне ничего (имхо).
Это мой краулер. Таких краулеров много, но этот — мой.
Мой краулер — мой лучший друг.
Реализация краулера — довольно популярная задача и встречается даже на технических собеседованиях. Готовых (Apache Nutch) и самописных решений для разных условий и на множестве языков — действительно много. Поэтому, любые комментарии из личного опыта разработки или использования приветствуются и будут интересны.
Постановка задачи
Задание для первой (начальной) реализации нашего тяп-ляп краулера будет следующим:
Краулер на раз-два 1.0
Написать краулер-скрипт, который обходит внутренние ссылки некоторого небольшого (до 100 страниц) сайта. В качестве результата предоставить список URL’ов страниц с полученными кодами и карту их перелинковки. Правила robots.txt и атрибут ссылки rel=nofollow игнорировать.
Внимание! Игнорировать правила robots.txt — плохая идея по понятным причинам. Мы наверстаем это упущение в дальнейшем. А пока, добавим ограничивающий количество обходимых страниц параметр limit, чтобы останавливаться и не DoS’ить подопытный сайт (лучше и вовсе для экспериментов использовать какой-нибудь свой персональный «сайт-хомячок»).
Реализация
Для нетерпеливых вот исходники этого решения.
1. HTTP(S)-клиент
Первое, что нам нужно уметь делать — это, собственно, отправлять запросы и получать ответы по HTTP и HTTPS. В node.js для этого есть два соответствующих клиента. Конечно, можно взять готовый клиент request, но для нашей задачи он крайне избыточен: нам всего лишь надо отправить GET-запрос и получить response с телом и заголовками.
Необходимый нам API обоих клиентов идентичен, заведем мапу:
Объявим простую функцию fetch, единственным параметром которой будет абсолютный URL нужного веб-ресурса строкой. С помощью утильного модуля url будем парсить полученную строку в объект URL. В этом объекте имеется поле с протоколом (с двоеточием), по которому мы выберем подходящий клиент:
Далее используем выбранный клиент и обернем результат функции fetch в промис:
Теперь мы умеем асинхронно получать response, но пока ничего с ним не делаем.
2. Варианты ответа
Для обхода сайта достаточно обрабатывать 3 варианта ответа:
Реализация стратегии формирования результата в лучших традициях if-else:
Функция fetch готова к использованию: код функции целиком.
3. Экстрагирование ссылок
Теперь в зависимости от варианта полученного ответа нужно уметь экстрагировать из данных результата fetch ссылки для дальнейшего обхода. Для этого определим функцию extract, принимающую на вход объект результата и возвращающую массив новых ссылок.
Если тип результата — REDIRECT, то функция вернет массив с одной единственной ссылкой из поля location. Если NO_DATA, то пустой массив. Если же OK, то нам необходимо подключить парсер для представленного текстового content для поиска.
Для задачи поиска можно написать и регулярное выражение. Но это решение совершенно не масштабируется, так как в дальнейшем мы как минимум будем обращать внимание на прочие атрибуты (rel) ссылки, как максимум — подумаем про img, link, script, audio/video (source) и прочие ресурсы. Гораздо перспективнее и удобнее парсить текст документа и строить дерево его узлов для обхода привычными селекторами.
Воспользуемся популярной библиотекой JSDOM для работы с DOM в node.js:
Достаем из документа все A элементы, а затем все отфильтрованные значения атрибута href, как не пустые строки.
4. Подготовка и фильтрация ссылок
В результате работы экстрактора мы имеем набор ссылок (URL) и две проблемы: 1) URL может быть относительным и 2) URL может вести на внешний ресурс (нам нужны сейчас только внутренние).
С первой проблемой нам поможет справиться функция url.resolve, которая резолвит URL целевой страницы относительно URL страницы-источника.
Чтобы решить вторую проблему, напишем простую утильную функцию inScope, которая проверяет хост целевой страницы относительно хоста базового URL текущего краула:
Функция осуществляет поиск подстроки (baseHost) с проверкой предыдущего символа, если подстрока была найдена: так как wwwexample.com и example.com — разные домены. В результаты мы не покидаем заданный домен, но обходим его поддомены.
Доработаем функцию extract, добавив «абсолютизацию» и фильтрацию полученных ссылок:
Здесь fetched — полученный результат от функции fetch, src — URL страницы-источника, base — базовый URL краула. На выходе мы получаем список уже абсолютных внутренних ссылок (URL) для дальнейшей обработки. Код функции целиком можно увидеть здесь.
5. Нормализация URL
Повторно встретив какой-либо URL, не нужно отправлять еще запрос за ресурсом, так как данные уже были получены (или другое соединение еще открыто и ожидает ответа). Но не всегда достаточно сравнить строки двух URL, чтобы это понять. Нормализация — это процедура, необходимая для определения эквивалентности синтаксически различных URL-адресов.
Процесс нормализации — это целый набор преобразований, применяемых к исходному URL и его компонентам. Вот только некоторые из них:
Да, здесь нет сортировки query-параметров, игнорирования utm-меток, обработки _escaped_fragment_ и прочего, чего нам (пока) совершенно не нужно.
Далее заведем локальный кэш запрошенных в рамках краула нормализованных URL. Перед отправкой очередного запроса нормализуем полученный URL, и, если тот отсутствует в кэше, добавим и только тогда отправим новый запрос.
6. Алгоритм работы main-функции
Ключевые компоненты (примитивы) решения уже готовы, пришло время начать собирать все вместе. Для начала определимся с сигнатурой функции crawl: на входе — стартовый URL и ограничение по страницам. Функция возвращает промис, резолв которого предоставляет аккумулированный результат; запишем его в файл output:
Простейшая схема рекурсивной работы функции краула может быть описана шагами:
1. Инициализация кэша и объекта результата
2. ЕСЛИ URL целевой страницы (через normalize) отсутствует в кэше, ТО
— 2.1. ЕСЛИ достигнут limit, ТО КОНЕЦ (ждать результат)
— 2.2. Добавить URL в кэш
— 2.3. Сохранить ссылку между источником и целевой страницей в результат
— 2.4. Отправить асинхронный запрос за страницей (fetch)
— 2.5. ЕСЛИ запрос выполнился успешно, ТО
— — 2.5.1. Экстрагировать новые ссылки из результата (extract)
— — 2.5.2. Для каждой новой ссылки выполнить алгоритм 2-3
— 2.6. ИНАЧЕ пометить страницу состоянием ошибки
— 2.7. Сохранить данные о странице в результат
— 2.8. ЕСЛИ это была последняя страница, ТО ВЕРНУТЬ результат
3. ИНАЧЕ сохранить ссылку между источником и целевой страницей в результат
Да, этот алгоритм будет претерпевать серьезные изменения в дальнейшем. Сейчас же умышленно используется рекурсивное решение в лоб, чтобы позже лучше «прочувствовать» разницу в реализациях. Заготовка для имплементации функции выглядит так:
Достижение лимита страниц проверяется простым счетчиком запросов. Второй счетчик — количество активных запросов в момент времени — послужит проверкой готовности отдать результат (когда значение оборачивается в ноль). Если функции fetch не удалось получить очередную страницу, то для нее Status Code выставим как null.
С кодом имплементации можно (не обязательно) ознакомиться здесь, но перед этим стоит рассмотреть формат возвращаемого результата.
7. Возвращаемый результат
Введем уникальный идентификатор id с простым инкрементом для опрошенных страниц:
Для результата заведем массив pages, в который будем складывать объекты с данными по странице: id
Для информативности перед резолвом результата отсортируем список страниц по возрастанию id (ведь ответы будут приходить в каком-угодно порядке), дополним результат числом просканированных страниц count и флагом о достижении заданного лимита fin:
Пример использования
Готовый краулер-скрипт имеет следующий синопсис:
Дополнив логированием ключевых точек процесса, увидим такую картину при запуске:
А вот результат в формате JSON:
Что с этим уже можно делать? Как минимум, по списку страниц можно найти все битые страницы сайта. А имея информацию о внутренней перелинковке, можно обнаружить длинные цепочки (и замкнутые циклы) редиректов или найти наиболее важные страницы по ссылочной массе.
Анонс 2.0
У нас получился вариант простейшего консольного краулера, который обходит страницы одного сайта. Исходный код лежит здесь. Там же есть еще пример и юнит-тесты для некоторых функций.
Web crawler с использованием Python и Chrome
Добрый день, дорогие друзья.
Недавно, сидя на диване, я задумался о том, что хочется мне сделать своего паука, который что-то бы смог качать с веб сайтов. Но качать он должен был бы не простой загрузкой, а как настоящий милый добрый браузер (т.е. JavaScript чтобы исполнялся).
В моей голове всплыли такие интересные штуки, как Selenium, PhantomJS, Splash и всякое подобное. Все эти штуки были мне немного втягость. Вот какие причины я выявил:
Пробежавшись по документации и готовому проекту, и убедившись что никто толком не реализовал клиент под Python, я решил сделать свой клиент.
Протокол у Chrome Remote Debug достаточно простой. Для начала нам надо запустить Chrome вот с такими параметрами:
Теперь у нас есть API, доступное, по адресу http://127.0.0.1:9222/json/, в котором я обнаружил такие методы как list, new, activate, version, которые используются для управления вкладками.
Также, если мы просто перейдем на http://127.0.0.1:9222/, то сможем перейти на прекрасный веб отладчик, который полностью имитирует стандартный. В нем очень удобно отслеживать как работают апишные методы хрома (окно отладки справа эмулируется внутри окна, а окно браузера — отрисовано на канвасе).
Собственно, перейдя на вкладку list, мы можем узнать, адрес вебсокета, с помощью которого мы сможем общаться с вкладкой.
Дальше мы подсоединяемся через вебсокет к желаемой вкладке, и общаемся с нею. Мы можем:
Тут мы используем систему колбеков. Самые интересные: start и any:
Однако, было одно но, из-за которого я все таки плачу. С помощью remote API нельзя производить перехват и модификацию запросов и ответов. Насколько я понял — это возможно через mojo, который позволяет использовать хром в качестве библиотеки.
Однако, я подумал, что компиляция нестабильного хрома и отсутствие Python прослойки для меня будет большим горем (сейчас есть C++ и JavaScript в процессе разработки).
Достаточно ли вы знаете о web-scale crawling
1 июня 2018 года прошла одна из самых масштабных конференций о продвижении на западных рынках Nazapad 9. Tim Soulo (Head of Marketing & Product Strategy at Ahrefs) затронул тему краулинга, рассказал что такое crawl budget, а также как индексируются ссылки. Эта тема достаточно сложная и объемная, так что заваривайте чай, садитесь поудобнее и будем разбираться вместе.
Как работает web-scale crawling
Все веб-краулеры собирают информацию примерно одинаково, но речь будет идти о краулере Ahrefs. Вот как это выглядит в геометрической прогрессии:
Предположим, что Краулер зашел на страницу, на которой находится 3 ссылки. Далее ему необходимо перейти на каждую из этих трёх ссылок, где в свою очередь находится еще 3 ссылки. То есть далее ему необходимо перейти на 9 страниц и тд. Но в реальной жизни на страницах практически никогда не бывает 3 ссылок, обычно это 50-60-100 и за пару шагов кол-во страниц, которые нужно прокраулить вырастает в сотни раз. Поэтому невозможно краулить новые страницы мгновенно. В связи с этим существует система “Краулер-Планировщик”.
Задача Краулера ходить по страницам, просматривать их контент и находить новые страницы. После чего отдавать эти страницы Планировщику, а он уже в свою очередь приоритезирует эту информацию и говорит Краулеру, что необходимо краулить в первую очередь. По этой причине существует некая задержка между тем, когда краулер найдет какой-то URL и тем когда он его прокраулит. Есть важные пункты, которые необходимо отменить:
На странице https://ahrefs.com/big-data мы можем увидеть сколько страниц прокраулил Ahrefsbot, не считая тех, что все еще висят в Планировщике.
Те ссылки, которые висели в планировщике более 90 дней Ahrefs отмечает как delayed.
Что такое crawl budget (краулинговый бюджет)
При краулинге нового домена, Ahrefsbot смотрит на следующие параметры:
Если рейтинг домена слишком маленький и он имеет слишком большое количество страниц, то качественные страницы этого домена могут вытеснить из индекса менее качественны. Такие страницы помечены как dropped.
Что представляет собой индекс ссылок
Чтобы в индексе оставались актуальные страницы необходимо придерживаться некоторых правил:
Ahrefs краулит 5000000 страниц в минуту, 80% из которых это ре-краул. Если страница очень крутая, на нее постоянно появляется куча ссылок, у нее хороший рейтинг или на ней что-то меняется, то её ре-краулят часто. Минимальный интервал ре-краула таких страниц — 1 час. Если у страницы плохой рейтинг и на неё нет новых ссылок, то такая страница будет ре-краулиться реже. Максимальный интервал — 6 месяцев.
Иногда при сравнении индекса Ahrefs и других сервисов, первый показывает меньше ссылок, хотя принято считать, что у Ahrefs индекс самый обширный. Дело в том, что ре-краулинг происходит слишком часто и Ahrefs быстрее видит, что ссылки пропали. Ввиду этого в Ahrefs создано 3 индекса:
Зачастую стоит обращать внимание на индекс Recent, так как большинство причин удаления ссылки из индекса обратимы:
Рассмотрим подробнее эти причины. Они разделены на 2 группы. Первая относится к странице, на которой вас линкуют. Вторая категория относится к самой ссылке. Страница:
Чем отличаются индексы разных провайдеров
То, как считаются ссылки, очень важно, потому что разные провайдеры считают ссылки по разному. Для примера, в посте “Why Counting Links Is Not So Easy” директор по маркетингу Majestic по состоянию на 2011 год в задаче по определению количества ссылок на страницу B из картинки ниже указал, что они определяют 4 ссылки на эту страницу. В Ahrefs будет учитываться 7-8 ссылок. Другие провайдеры могут считать совсем по другому.
Еще пример, в Majestic статья «Beginner’s Guide to SEO» имеет 126,201 ссылок с сайта coschedule.com:
На Ahrefs всего 17 ссылок на данную статью из этого сайта:
Оказалось, что Majestic учитывает страницы с UTM-метками несмотря на том, что на странице указан rel= «canonical»:
Ссылки в JavaScript — это еще один важный момент, который нужно учитывать. На скриншоте ниже указано какие поисковики кроулят js frameworks. Из линк-индексов только Ahrefs недавно начал это делать и включать такие ссылки в свой индекс. Поэтому в Ahrefs есть определенные ссылки, которых нет у других.
Что такое AR/DR/UR
AR = Ahrefs Rank. Рейтинг сайтов строится на основе их Backlinks.
DR = Domain Rating. По сути это все сайты из AR загнанные в шкалу от 1 до 100. DR это быстрый способ определить где определенный сайт находится по соотношению ко всем остальным сайтам.
UR = URL Rating. Не стоит путать в метрикой DR, она относится ко всему домену. UR относится к каждой странице сайта отдельно.
Вот и всё. Надеемся каждый, кто уделил свое время прочтению статьи, почерпнул из нее что-то новое для себя.
CRAWL динамических страниц для Google и Яндекс поисковиков (snapshots, _escaped_fragment_, ajax, fragment)
1. Что такое CRAWL
2. Динамический CRAWL
3. Задачи, инструменты, решение
4. Почитать
5. Выводы
1. Что такое CRAWL
Это сканирование страниц сайта поисковыми системами с целью получить необходимую информацию. Результат выполнения данного сканирования является html представление в конечной точке (у каждой поисковой системы свои настройки, а именно грузить или нет js (с запуском или без), css, img и т.д.) или как это ещё называют «снимок» сайта.
2. Динамический CRAWL
Это прописано в настройках роутера angular:
3. Задачи, инструменты, решение
Задачи:
1. Отдавать динамический контент страницы такой, какой он становится после окончания рендеринга и инициализации приложения
2. Формируем, Оптимизируем и Сжимаем html снимок страницы
3. Отдаём поисковой системе html снимок
Инструменты:
1. Установленная NPM (npm — это пакетный менеджер node.js. С его помощью можно управлять модулями и зависимостями.)
2. Установленный модуль html-snapshots с помощью команды:
3. Правильная конфигурация
Решение:
Для быстродействия рекомендую выполнять «кравлинг» на localhost (локальном веб-сервере)
Для начала нужно добавить в главный index.php в meta tag в head:
Снимки вашего сайта подготовлены, осталось отдать их поисковому боту при заходе:
1. html5 push state
If you use html5 push state (recommended):
Just add this meta tag to the head of your pages
2. hashbang
If you use the hashbang (#!):
If your URLs look like this:
www.example.com/#!/user/1
Дополнительно, для тех у кого есть снимки, но нет оптимизации:
4. Почитать
5. Выводы
Теперь смело можно писать любые SPA приложения не беспокоясь за их «кравлинг» поисковым ботом, также вы можете подобрать под свой набор инструментов нужную конфигурацию как для «сервера», так и для «клиента»!