Индексация AJAX-сайтов

в 22:51, , рубрики: ajax, crawling, javascript, joosy, open source, ruby on rails, Блог компании Round Lake, метки: , , ,

Индексация AJAX сайтов

Вместе с разработкой Joosy, AJAX внезапно – но ожидаемо, – заполонил все проекты, за которые мы беремся. Парадигма оказалась крайне удачной во всех аспектах, кроме одного. Того самого классического: «AJAX? Индексация? Пфф...». Пока мы делаем интернет-банки, это нас вполне устраивает. Но как не отказывать себе в этом изысканном удовольствии для открытых Web-ресурсов?

А вот как: Google AJAX Crawling – это стандарт Google, который позволяет при формировании AJAX-адресов специальным образом (#!) заставить Google магически запрашивать вместо него другой магический адрес. С которого Google будет ждать HTML-дамп этой страницы, который он весело прожует. Добрые люди уже написали статью про то как это работает. Ну а нам остается научиться эффективно этот дамп формировать. Да так, чтоб без вмешательства в код самого приложения.


Hashbang – это маленький прокси-сервер на Ruby, работающий по протоколу Rack. Последнее означает, что для того чтобы его поднять сгодится любой web-сервер, работающий с Ruby и/или Rails. А для тех, кто использует собственно Rails, мы приготовили парочку особенных плюшек. Но обо всем по порядку.

Общее устройство

При инициализации, Hashbang создает в своих недрах инстанс WebKit-браузера. После того как запрос с указанием нужного URL запущен, он открывает нужный адрес, ждет специального Javascript-события и возвращает HTML код на момент, когда это событие произошло.

Это означает, что все, что вам потребуется изменить в текущем приложении – это вызывать

Suncsraper.finish()

когда страницу, подготавливаемую Javascript'ом можно считать готовой.

В боевом режиме это будет выглядеть так:

Индексация AJAX сайтов

Про внутренний браузер и производительность

Мы много экспериментировали с возможными реализациями «безголового» браузера. Пробовали Watir и разные существующие биндинги Qt. Ничего хорошего не вышло. Отчаявшись, мы просто написали свой биндинг к Qt-WebKit, который и только и умеет, что возвращать HTML, отслеживая событие: Sunscraper. Написано это чудо на смеси C/C++ и подключается к Ruby посредством FFI. Это значит, что Sunscraper должен работать не только на MRI, но и на JRuby/Rubinius. К сожалению, с Rubinius он все-таки не работает из-за багов в реализации того самого FFI.

Так как все, что мы запускаем – это сам движок WebKit, производительность близка к максимальной для решения этой задачи. Реальные данные с живых серверов в процессе сбора.

Перед установкой

Sunscraper использует Qt. Поэтому он обязательно вам понадобится для установки gem'а Hashbang. Если вы используете Mac, мы рекомендуем Homebrew: brew install qt. В Linux можно ставить любой, посвежее, из пакетов.

Development-режим для тех, кто на рельсах

Если вы не разрабатываете на Rails, смело переходите к следующему параграфу, который расскажет о внедрении Hashbang в бой.

Для установки Hashbang в Rails-проект, необходимо выполнить следующую последовательность действий:

  1. Добавить gem hashbang в Gemfile
  2. Сгенерировать базовое приложение с помощью rails g hashbang

Теперь внутри вашего Rails-приложения, в папке hashbang, лежит мини-приложение самого Hashbang'а. А это значит, что вам нужно пропустить первый абзац в части «настройки и запуска».

В development-среде, Hashbang вставляет в загрузку Rails свой middleware, который перехватывает все запросы, содержащие магический фрагмент _escaped_fragment_ и автоматически обрабатывает их. Проблема лишь одна: Webrick работает в один поток. А так как Hashbang запрашивает «сам себя», это приводит к дедлоку. Поэтому чтобы потестировать текущее приложение локально, запустите его с помощью rake hashbang:rails. Эта команда запустит ваше приложение под сервером Unicorn в два поток. После запуска – localhost:3000/?_escaped_fragment_ – и проверяйте HTML. Только не забудьте, что в самом AJAX-приложении надо вызывать Sunscraper.finish().

Чтобы сэмулировать запуск Hashbang в боевом режиме, где он работает через /?url=http://..., используйте команду rake hashbang:standalone.

Настройка и запуск

Если вы не используете Rails, базовое приложение можно взять из специального репозитория. Все, что вам надо будет сделать – разместить его где-нибудь, убедиться что у вас установлен gem bundler и сделать в корне приложения bundle install.

Внутри сгенерированного/скопированного Hashbang-приложения лежит файл config.rb, который обязательно надо отредактировать для эффективной работы. В нем всего две директивы:

  • url: регулярное выражение, которому должен соответствовать запрашиваемый URL
  • timeout: таймаут в милисекундах, который hashbang будет дожидаться события Sunscraper.finish()

Предположим, что для запуска сервиса мы используем модуль Passenger, который реализует работу с Rack на базе Nginx. В этом случае для корректной работы нам нужно добиться следующего:

  • На специальном внутреннем адресе у нас должно работать приложение Hasbang
  • Все запросы, содержащие _escaped_fragment_ должны пробрасываться на это приложение, причем пробрасываться uri-escaped абсолютным урлом в параметр url=....
  • Нам нужно ограничить количество параллельных ресурсов к этому приложению, потому что врядли нас будут индексировать в сто потоков, а ресурсы WebKit любит.

Вот какой конфигурационный файл можно использовать: https://gist.github.com/2127685. Это пример использования Hashbang в Ralis-приложении.

О грустном

К сожалению, в наши родные пенаты, Яндекс, этот стандарт так и не дошел. Его поддерживает Google, его поддерживает Bing (а значит и Yahoo). Даже crawler Facebook и тот его поддерживает. А Яндекс – нет. Это значит, что Hashbang никак не поможет вашей индексации в отечественном сегменте интернета. По крайней мере пока. Мы направляем яростные лучики добра в сторону команды Яндекса и желаем им поскорее обратить свой взор на столь активно развивающийся технологический сегмент Web'а :).

В заключение

Несмотря на то, что мы уже используем Hashbang в бою, мы еще не обкатали его на всех возможных конфигурациях. Если у вас возникнут какие-то проблемы при его сборке или настройке, мы всегда рады новым Issues на гитхабе.

Спасибо :).

Автор: inossidabile

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


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js