понедельник, 26 ноября 2012 г.

Ба, знакомые всё лица...

6-дневный забег


Закадровый голос, которым озвучивают обычно страшилки о грядущем апокалипсисе и прочую плесень в стиле "ааа, мы все умрём", на фоне Оли с обычной улыбкой до ушей вызывает ээээ.... некоторый плюрализм в отдельно взятой голове :)

четверг, 8 ноября 2012 г.

Как разложить фрэндов по полочкам :)

Камрад _winnie навёл на актуальное нынче средство для визуализации графов - Gephi и поделился скриптом для преобразования списка фрэндов в формате ЖЖ в граф для Gephi.

Как большой любитель всяческих визуализаций решил тоже нарисовать себе подобных картинок.

Итак, для начала качаем список ЖЖ фрэндов (команды linux-овые, так что cygwin вам в руки):
wget "http://www.livejournal.com/misc/fdata.bml?user=malgarr" -O malgarr.txt
Если сидим за прокси, то соответственно так:
wget --proxy=on -e http_proxy=192.168.1.252:3128 --proxy-user=username --proxy-passwd=userpassw "http://www.livejournal.com/misc/fdata.bml?user=malgarr" -O malgarr.txt
Теперь в файле malgarr.txt лежит список моих фрэндов. Создаем рядом подкаталог out и файлик x.sh:
wget -q "http://www.livejournal.com/misc/fdata.bml?user=$1" -O out/$1.txt
Соответственно, если сидим за прокси, то команда в файлике x.sh должна быть такая:
wget --proxy=on -e http_proxy=192.168.1.252:3128 --proxy-user=username --proxy-passwd=userpassw -q "http://www.livejournal.com/misc/fdata.bml?user=$1" -O out/$1.txt
Также рядом создаем файл с питоновским скриптом merge_friends_to_dot.py:
import glob
from os.path import basename, splitext


ls = [l.strip() for l in open('malgarr.txt').read().splitlines() if l.strip()]
my_f = set(l[2:] for l in ls if l[0] != '#' and l[0] == '>')
my_f.remove('malgarr')


print 'digraph {'
dirs = set()
for f in glob.glob('out/*.txt'):
    x = splitext(basename(f))[0]
    for l in open(f).read().splitlines():
        l = l.strip()
        if not l:
            continue
        if l[0:1] == '#':
            continue
        y = l[2:]
        if x in my_f and y in my_f:
            if x != y:
                if l[0] == '>':
                    dirs.add((x, y))
                #elif l[0] == '<':
                #    dirs.add((y, x))
for x, y in sorted(dirs):
    print '"%s" -> "%s"' % (x, y)
print '}'
Запускаем команду, которая для каждого фрэнда из malgarr.txt вытащит список его фрэндов и сложит это все в out:
time cat malgarr.txt | grep -v '^#' | cut -c 3- | sort -u | xargs -P 4 -n 1 ./x.sh
Осталось преобразовать все это богатство в граф для Gephi:
python merge_friends_to_dot.py > foaf_i_read.dot
Открываем foaf_i_read.dot в Gephi, переходим на панель Обработка:


Жмем на запуск сбора статистики по параметру Модулярность:


Перед началом обработки вылетает окно с параметрами:

Если параметр Resolution уменьшить, то деление будет происходить на большее число кластеров.

Теперь это разделение надо визуализировать:


Размеры узлов сделаем пропорциональными популярности:


Сгруппировать кластеры по кучкам можно при помощи алгоритмов укладки:

Кстати, не все алгоритмы сами завершают свою работу, когда узлы перестают тасоваться надо просто давить кнопку Стоп. Прямо в процессе работы укладки можно вручную перекидывать узлы мышкой на картинке, они потом устаканятся в соответствии с новым положением.

Цвет узлов можно подстроить вручную:


В конце концов у меня получилось такое картинко:

Фрэнды поделились по большей части несколько надуманно :( Предпочитаемые тысячники практически перебили другие связи. Хотя например, Челябинский кластер повязан так, что никакие тысячники его разорвать не смогли :)

Можно выкинуть тысячников из malgarr.txt и повторить процесс, вроде как кучкование получается более адекватное:


Вообщем струмент порадовал возможностями и безглючной работой.