Карта сайта для поисковиков (Sitemap) в Zend Framework приложении
По работе занимаюсь созданием довольно большого портала. Не люблю я это слово, но оно наиболее полно отражает суть веб-сервиса. На этой неделе встала задача генерации sitemap файла для поисковиков. Всё бы ничего но по примерным подсчётам на сайте никак не меньше 3 000 000 страниц, которые надо скормить роботу. Ввиду такого количества поисковик просто не индексирует их все, упираясь в свой лимит. Собственно поэтому и нужен sitemap.
Задача
Создать карту сайта(sitemap.xml/sitemap.txt) для большого сайта на Zend Farmework.
Решение
Необходимо создать список публично доступных-страниц сайта, т.е. ссылок на них. Ссылки в нормальном ZF-приложении генерятся через Url Helper:
1 |
url($urlOptions, $name, $reset): Creates a URL string based on a named route. $urlOptions should be an associative array of key/value pairs used by the particular route. |
А значит у нас есть единая точка генерации ссылок. Это позволит нам составить список ссылок для карты сайта.
Нашей первой идеей было пробежаться по всем маршрутам (по которым url хелпер строит ссылки) и сгенерить ссылкы на основе маршрутов и данных из БД. Это оказалось плохой затеей, т.к. данных в базе было много, ссылок тоже и время генерации карты сайта выходило за все разумные пределы.
Второй идеей было перехватывать вызовы url-хелпера и журналировать их в БД, а потом уже на основе журнала генерировать sitemap. Т.е. сделать БД буфером между запросами хелпера и файлом sitemap. У этой идеи был свои недостатки. На каждую ссылку на странице делалось два запроса к БД: один на чтение из таблицы sitemap (а была ли уже такая ссылка) и второй на запись (создание новой записи или обновленеи времени доступа существующей). Если на странице 80 ссылок, то имеем + 160 запросов к БД. Не вариант.
Тогда на ум пришла третья идея. А что если буферизировать вызовы хелпера в приложении. Т.е. по ходу генерации страницы собираем в массив все ссылки, а потом… нет, не пишем в БД, ведь тогда надо опять же проверять существование ссылок… отправляем задачу на сервер очередей.
Солюшен
- Журналируем вызовы url-хелпера и складываем их в массив в локальной переменной.
- Перед отдачей результатов рендеринга страницы пользователю отправляем задание с этим массивом в очередь.
- Отдаем страницу.
- Демон очереди получает задачу и в фоновом режиме (может даже на отдельном сервере) и осуществляет чтение/запись в БД.
- Где-нибудь ночью запускается cron-скрипт, который на основе подготовленных демоном данных в БД генерирует карту сайта.ъ
- PROFIT! 🙂
Преимущества
- Нет оверхеда при генерации страницы, только быстрая отправка задания в очередь.
- Актуальность карты сайта = период запуска крон скрипта.
- Потенциально неограниченный размер карты сайта, за счёт разделения работы между подсистемами и фоновой генерацией карты.
Недостатки
- Нужен сервер очередей 🙂
- Все ссылки на сайте должны генерироваться через URL хелпер.
На самом деле в нормальном проекте всё так и есть. Если нет, это повод задуматься. Думаю эта заметка будет полезной для ZF разработчиков.
А если кто-то будет соваться на несуществующие страницы? Например робот (спамер, ищейка уязвимостей… ) или просто страница удалена, а люди все равно на нее прут
Выдавать 404 код, чтобы страница исчезла из индекса поисковика. Ищейки пусть прут, будут часто заходить, можно начать их банить.
Сейчас решаю подобную задачу.
Возникает вопрос – а как быть с ссылками, которые роботу не надо видеть?
Типа /post/edit или /admin, ну и ссылки, которые доступны только авторизованным пользователям (личная почта) ?
Ну тут два варианта, либо сравнивать с массивом из черного списка, либо запретить в robots.txt
Сделал по другому 🙂
Ставить в очередь герману только тогда, когда ссылки генерируются для неавторизованного пользователя.
Другими словами, если по сайту бродит кто-то неавторизованный – то ссылки добавляем серверу очередей для обработки.
Кстати, хорошая идея.