Skip to content

Немного о спайдерах и расчёте числа Шухарта

04/02/2011

Хочу здесь поподробнее рассказать как именно работает спайдер, собирая данные с Хабрахабра. В основе — обычный поиск в ширину. Действует там всё довольно просто:

У паука есть очередь пользователей. В ней хранятся объекты с тремя свойствами: уровень пользователя (относительно Шухарта), имя (в том виде в котором оно входит в личный поддомен на Хабре) и путь от Шуха до пользователя. Вначале в очереди есть только Шухарт:

var shoohurt = {
    'username' : 'shoohurt',
    'level' : 0,
    'path' : ''
}

Кроме этого есть redis-хранилище, где хранятся, во первых, уже известные пауку пользователи (в виде set‘а) и, во вторых, персональные данные для каждого пользователя в виде двух ключей: users:%username%:level и users:%username%:path. Эти пары ключей спайдер только записывает, но никогда к ним не обращается (эти данные берутся из объекта очереди). Путь хранится в виде строки с именами пользователей, разделённых пробелами. Изначально там только Шух, его уровень равен 0, путь — пустая строка.

Потом спайдер действует по одному и тому же шаблону:

  • Достаёт пользователя из очереди
  • Получает его страницу на Хабре и достаёт оттуда список друзей
  • Для каждого друга в списке:
    • Проверяет, есть ли он в Redis в списке уже известных пользователей. Если да, ничего не происходит. Если нет:
    • Добавляет его в список известных пользователей
    • Добавляет запись о его уровне = уровень того у кого был найден пользователь + 1
    • Добавляет запись о пути до него = путь до того у кого был найден пользователь плюс имя того у кого мы его нашли
  • После этого паук ждёт заданное время (в первом варианте было 4 секунды) и переходит в режим готовности, повторяя этот алгоритм

Пример: мы обходим друзей пользователя shoohurt и находим Boomburum’а. Такого пользователя в известных нет, поэтому мы его добавляем. Уровень Шухарта = 0, путь к Шухарту — пустая строка. Тогда уровень Бумбурума будет 0 + 1 = 1 и путь к нему будет равен '' + ' shoohurt' = ' shoohurt'.

Пример 2: мы обходим друзей пользователя brainfucker и находим там хабраюзера nats. Такого пользователя в известных нет, поэтому мы его добавляем. Уровень brainfucker’а — 3, путь к нему — » shoohurt absolvo Alik-Kirillovich». Тогда для nats уровень будет 3 + 1 = 4, а путь — " shoohurt absolvo Alik-Kirillovich" + " brainfucker" = " shoohurt absolvo Alik-Kirillovich brainfucker".

Такой способ обхода выбран для того чтобы все пользователи кроме первого обрабатывались одинаково, вне зависимости от того на каком уровне они находятся. Правда тут есть одна проблема: так как на Хабре друзья располагаются в алфавитном порядке (и соответственно спайдер их обнаруживает так же) при нескольких возможных путях до одного и того же пользователя в базе окажется тот где промежуточные хабралюди ближе к началу алфавита.

Для показа на сайте мы проверяем есть ли такой пользователь в базе (с помощью SISMEMBER, если нет, показываем печальную страничку. Если пользователь есть, получаем его длину пути и сам путь. Путь разбивается на отдельных пользователей с помощью path.split(' ') и темизируется в виде отдельных ссылок. Последним в новый путь добавляется тот кого мы ищем (уже без последующего символа >).

Вообще изначально я задумывал это как тест графовой базы данных вроде VertexDB или FlockDB (граф-ориентированная база от создателей Twitter), но потом мне в голову пришёл этот алгоритм как упрощённый вариант изначального. Его я и реализовал.

P.S. К сожалению, как оказалось впоследствии, на Хабре топики с упоминанием Шухарта негласно запрещены независимо от их темы. Топик довольно резво набрал ~40 голосов, вышел на главную и был запилен администрацией ресурса. Есть над чем задуматься.

Реклама

From → Uncategorized

One Comment
  1. Интересно интересно =)

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: