На данный момент на хабре около 350 хабов. Функционал сайта позволяет сортировать их по имени и по индексу. А по другим параметрам — например по количеству постов — нет, а хотелось бы.
Меня вдохновила статья рейтинг постов хаба, и я решил сделать похожую, но составить уже рейтинг самих хабов.
В первой половине статьи я представлю вам рейтинги хабов и компаний, а также небольшой их анализ. А во второй — подробно распишу, как я на Java с помощью библиотеки JSoup парсил HTML страницы хабры, с какими интересными явлениями и проблемами столкнулся. И в конце статьи выложу полный исходный код программы.

Все 4 рейтинга (полные) в виде веб-страницы
Когда я отсортировал хабы, обнаружились интересные вещи. Например я не знал, что существуют хабы с нулевым количеством постов. А их оказалось целых 4 штуки! Причём на каждый из них подписано более 500 человек.
Тройка хабов — Чулан, Я пиарюсь и Веб-разработка — лидируют как по количеству постов, так и по количеству читателей. Чулан на 1 месте потому, что туда администрация удаляет статьи. Далее идёт Информационная безопасность, которая пользуется на хабре бешеной популярностью.
К сожалению, я так и не понял, почему хаб Хабрахабр — оффтопик. По количеству постов он будет на 13 месте, да и подписчиков у него >80К. Получается, что писать на сайте об этом же сайте — отход от темы?
Огорчило, что хаб Java находится не так высоко, как хотелось бы.
Компаний очень много — 1343. Поэтому я выложу только ТОП-30 и последние 10 компаний. Вот ведь интересный момент — хабра почему-то показывает Все (1331), хотя моя программа насчитала их 1343 — и, собственно, это правильно. Если вручную их сосчитать — умножить количество страниц 67 на 20 компаний да ещё 3 — получается 1343.
Для начала меня удивил тот факт, что есть 2 вида отсутствия компании — «компания деактивирована» и «страница не найдена». Хотя повторюсь — все компании были взяты из списка. Первый вид я помечал количеством постов -2. Таких компаний довольно много. И три компании, название которых состоит из цифр — ведут на «страница не найдена». Их я пометил -3. Такие вот дела. Также полно компаний с нулевым количеством постов — например Apple. Интересно, зачем создавать аккаунт для компании и вообще не писать с него?
Собственно, если из тех 1343, зарегистрированных на хабре, вычеркнуть несуществующие и компании без постов, то останется всего 321. Такие вот дела.
Когда речь идёт о проектах «для себя», я выбираю любимую Джаву. Она и на этот раз меня не подвела — библиотека JSoup позволила в несколько строчек получить необходимые данные с HTML страницы. Но давайте сперва обсудим, как устроены хабы.
Страницы с хабами расположены по адресам habrahabr.ru/hubs/pageN/, где N — номер от 1 и далее. Посему, если мы хотим получить полный список из всех хабов — нам нужно загружать и анализировать эти страницы, пока они не закончатся. На каждой странице присутствует список из хабов. Формат элемента списка довольно простой и легко анализируется. Выглядит он так:
Давайте напишем метод, который возвращает нам список из всех хабов на сайте:
Мы крутим бесконечный цикл while, формируя с каждой итерацией новый URL. Затем, с помощью Jsoup.connect(urlHubs).get() получаем непосредственно HTML-документ со списком хабов и их параметрами. Как несложно заметить — div с информацией о хабе имеет класс hub — и, вызвав doc.select(".hub"), мы получаем список из этих элементов. Если его размер равен нулю — значит мы прошли последнюю страницу и уже проанализировали все хабы — тогда мы выходим из цикла.
Далее — проходим по всем хабам-элементам и для каждого создаём объект типа Hub, передав в конструктор наш org.jsoup.nodes.Element. В нём располагается HTML-код такого же формата, как указан выше. Теперь давайте абстрагируемся от всего. Для этого и существует ООП. Перед нами есть только тот кусочек HTML, представленный выше, и класс, в который его нужно запихнуть. Напишем каркас для нашего класса:
Напишем конструктор. Для начала сделаем самое простое — получим данные из заголовочного тега. Для этого мы сначала извлекаем сам div вида
Парсим через
Далее, мы хотим пропарсить количество подписчиков и постов — собственно те параметры, по которым мы и будем сортировать. Но сразу же сталкиваемся с первой проблемой — тег содержит строку «91741 подписчик», которую мы не можем просто так взять и преобразовать в Integer — она содержит буквы! Тут нам на помощь приходят регулярные выражения. Быстренько пишем ловкий метод, который получает строку и вырезает из неё всё, кроме цифр, да ещё и преобразует результат в int. \D — это НЕ цифра, а + — «встречается 1 или более раз». Т.е. мы в данном случае заменяем буквы на пустоту.
Вот теперь мы уже можем со спокойной душой получить наши значения:
В принципе, на этом можно было остановится, но я решил ради интереса извлечь всю возможную информацию о хабе. Тут возникла весьма интересная вторая проблема, которая будет изюминкой статьи. Как пропарсить хабраиндекс?
Для начала, следует заменить запятую на точку и убрать лишние пробелы. Но этого не достаточно! Парсер всё равно выдаёт ошибку, если скопировать и вставить хабраиндекс в код — Double.valueOf("–1.11"). А если ввести вручную то же самое число — всё окей. Причём визуально в моей IDEA они абсолютно идентично выглядят!
Оказывается, дизайнеры хабры просто использовали dash вместо minus — c иным кодом символа, и парсер его, понятное дело, не ест. Возьмите на заметку. Суть проблемы в следующем:
Когда-то в своей статье Хитрые задачи по Java я рассмотрел подвох, когда L маленькую можно не отличить от 1. Собственно, сейчас я напоролся на аналогичную проблему.
Посему, код для извлечения хабраиндекса будет чуть сложнее:
Далее, пишем компаратор по постам как вложенный статический класс для Hub
И сортируем по нему где-нибудь в main
Всё, задача выполнена! С количеством подписчиков аналогично. Далее я написал код, который выводит в консоль два списка в таком виде, чтобы их сразу можно было вставить в статью — и сделал это вначале.
На получение всех хабов уходит примерно 10 секунд. Исходный код можно скачать здесь. Собираем и запускаем вот так, не забыв установить Jsoup и заменить путь на ваш:
Кроме того, я переделал эти же классы для сбора статистики по компаниям. Там, казалось бы, всё аналогично — однако чтобы узнать количество постов в блоге компании, пришлось подгружать страничку для каждой по отдельности — а это заняло уже около 5 минут. Я сделал многопоточную загрузку для ускорения. Обнаружил, что хабра не позволяет грузить больше чем 5-7 страниц одновременно. Собственно, сериализовал ArrayList<CompanyBlog> и записал. Этот файлик на 100 килобайт лежит вместе с вторыми исходниками — можете поработать с ним.
Если вас интересует полный рейтинг и в более компактном виде — я выложил его в виде веб-страницы.
Меня вдохновила статья рейтинг постов хаба, и я решил сделать похожую, но составить уже рейтинг самих хабов.
В первой половине статьи я представлю вам рейтинги хабов и компаний, а также небольшой их анализ. А во второй — подробно распишу, как я на Java с помощью библиотеки JSoup парсил HTML страницы хабры, с какими интересными явлениями и проблемами столкнулся. И в конце статьи выложу полный исходный код программы.

Все 4 рейтинга (полные) в виде веб-страницы
Рейтинг хабов
По количеству постов
Чулан 35 971
Я пиарюсь 5 461
Веб-разработка 4 011
Информационная безопасность 3 385
Google 2 770
Железо 2 733
Гаджеты. Устройства для гиков 2 375
Программирование 2 293
Linux 2 235
Android 1 965
JavaScript 1 687
Apple 1 612
Хабрахабр 1 568
.NET 1 485
PHP 1 465
Системное администрирование 1 454
DIY или Сделай Сам 1 442
Разработка 1 331
Управление проектами 1 261
Интерфейсы 1 257
Microsoft 1 237
Game Development 1 218
Open source 1 110
Смартфоны и коммуникаторы 1 091
JAVA 1 020
Дизайн в IT 996
Алгоритмы 991
Копирайт 982
Социальные сети и сообщества 949
GTD 939
Windows 919
Учебный процесс в IT 916
Python 866
Робототехника 798
Разработка под Android 783
Разработка под iOS 777
Хостинг 749
C++ 711
Законодательство и IT-бизнес new 677
Медиа 664
(...)
Tumblr 3
Cubrid 3
Промышленное программирование new 3
Julia new 2
Microsoft Access 2
Growth Hacking new 2
Google Checkout 0
MySpace 0
Xcode new 0
SCADA new 0
Я пиарюсь 5 461
Веб-разработка 4 011
Информационная безопасность 3 385
Google 2 770
Железо 2 733
Гаджеты. Устройства для гиков 2 375
Программирование 2 293
Linux 2 235
Android 1 965
JavaScript 1 687
Apple 1 612
Хабрахабр 1 568
.NET 1 485
PHP 1 465
Системное администрирование 1 454
DIY или Сделай Сам 1 442
Разработка 1 331
Управление проектами 1 261
Интерфейсы 1 257
Microsoft 1 237
Game Development 1 218
Open source 1 110
Смартфоны и коммуникаторы 1 091
JAVA 1 020
Дизайн в IT 996
Алгоритмы 991
Копирайт 982
Социальные сети и сообщества 949
GTD 939
Windows 919
Учебный процесс в IT 916
Python 866
Робототехника 798
Разработка под Android 783
Разработка под iOS 777
Хостинг 749
C++ 711
Законодательство и IT-бизнес new 677
Медиа 664
(...)
Tumblr 3
Cubrid 3
Промышленное программирование new 3
Julia new 2
Microsoft Access 2
Growth Hacking new 2
Google Checkout 0
MySpace 0
Xcode new 0
SCADA new 0
По количеству подписчиков
Чулан 124 521
Я пиарюсь 101 864
Веб-разработка 96 117
Android 95 361
Гаджеты. Устройства для гиков 95 020
Смартфоны и коммуникаторы 94 376
Google 93 844
DIY или Сделай Сам 92 322
Железо 91 959
Информационная безопасность 91 729
Linux 91 103
Робототехника 89 721
Программирование 89 668
Планшеты 88 757
Google Chrome 88 197
Операционные системы 88 098
Интерфейсы 88 064
Windows 87 695
iPhone 87 609
Алгоритмы 87 372
Веб-дизайн 87 341
Электронные книги 86 582
Дизайн в IT 86 266
Совершенный код 85 525
Браузеры 85 443
iPad 85 290
Энергия и элементы питания 84 866
Научно-популярное 84 668
PHP 84 621
(...)
Резервное копирование new 3 503
Xcode new 2 823
Физика new 2 372
Raspberry Pi new 2 274
Промышленное программирование new 2 141
Разработка под e-commerce new 2 034
SCADA new 1 856
Laravel new 1 799
Growth Hacking new 1 063
Julia new 948
Я пиарюсь 101 864
Веб-разработка 96 117
Android 95 361
Гаджеты. Устройства для гиков 95 020
Смартфоны и коммуникаторы 94 376
Google 93 844
DIY или Сделай Сам 92 322
Железо 91 959
Информационная безопасность 91 729
Linux 91 103
Робототехника 89 721
Программирование 89 668
Планшеты 88 757
Google Chrome 88 197
Операционные системы 88 098
Интерфейсы 88 064
Windows 87 695
iPhone 87 609
Алгоритмы 87 372
Веб-дизайн 87 341
Электронные книги 86 582
Дизайн в IT 86 266
Совершенный код 85 525
Браузеры 85 443
iPad 85 290
Энергия и элементы питания 84 866
Научно-популярное 84 668
PHP 84 621
(...)
Резервное копирование new 3 503
Xcode new 2 823
Физика new 2 372
Raspberry Pi new 2 274
Промышленное программирование new 2 141
Разработка под e-commerce new 2 034
SCADA new 1 856
Laravel new 1 799
Growth Hacking new 1 063
Julia new 948
Когда я отсортировал хабы, обнаружились интересные вещи. Например я не знал, что существуют хабы с нулевым количеством постов. А их оказалось целых 4 штуки! Причём на каждый из них подписано более 500 человек.
Тройка хабов — Чулан, Я пиарюсь и Веб-разработка — лидируют как по количеству постов, так и по количеству читателей. Чулан на 1 месте потому, что туда администрация удаляет статьи. Далее идёт Информационная безопасность, которая пользуется на хабре бешеной популярностью.
К сожалению, я так и не понял, почему хаб Хабрахабр — оффтопик. По количеству постов он будет на 13 месте, да и подписчиков у него >80К. Получается, что писать на сайте об этом же сайте — отход от темы?
Огорчило, что хаб Java находится не так высоко, как хотелось бы.
Рейтинг компаний
Хотя изначально я планировал построить рейтинг только для хабов, в комментариях к статье выдвинули хорошую идею — сделать тоже самое и для компаний. Код при этом сильно менять не пришлось.Компаний очень много — 1343. Поэтому я выложу только ТОП-30 и последние 10 компаний. Вот ведь интересный момент — хабра почему-то показывает Все (1331), хотя моя программа насчитала их 1343 — и, собственно, это правильно. Если вручную их сосчитать — умножить количество страниц 67 на 20 компаний да ещё 3 — получается 1343.
По количеству подписчиков
Яндекс 11 056
Google 10 999
Microsoft 6 797
Intel 5 463
Apple 4 124
Opera Software ASA 3 873
Журнал Хакер 3 034
Zfort Group 2 969
JetBrains 2 946
Mail.Ru Group 2 921
ВымпелКом (Билайн) 2 730
IBM 2 655
Студия Артемия Лебедева 2 640
Nokia 2 542
ТМ 2 314
Простая Наука 2 222
Samsung 2 222
2ГИС 1 992
Adobe 1 878
ABBYY 1 847
Box Overview 1 844
ВКонтакте 1 841
HP 1 828
Мосигра 1 772
Skype 1 718
«Лаборатория Касперского» 1 667
ASUS Russia 1 615
Sony Mobile Communications 1 572
Apps4All 1 541
LinguaLeo 1 493
(...)
Angie 5
Photoplay 5
Флорист.ру 5
PlatOn 5
Polyvizor 5
Dulton Media LLC 5
bdl premium 4
GolovachCourses 4
timera inc. 4
Slon.ru 3
Google 10 999
Microsoft 6 797
Intel 5 463
Apple 4 124
Opera Software ASA 3 873
Журнал Хакер 3 034
Zfort Group 2 969
JetBrains 2 946
Mail.Ru Group 2 921
ВымпелКом (Билайн) 2 730
IBM 2 655
Студия Артемия Лебедева 2 640
Nokia 2 542
ТМ 2 314
Простая Наука 2 222
Samsung 2 222
2ГИС 1 992
Adobe 1 878
ABBYY 1 847
Box Overview 1 844
ВКонтакте 1 841
HP 1 828
Мосигра 1 772
Skype 1 718
«Лаборатория Касперского» 1 667
ASUS Russia 1 615
Sony Mobile Communications 1 572
Apps4All 1 541
LinguaLeo 1 493
(...)
Angie 5
Photoplay 5
Флорист.ру 5
PlatOn 5
Polyvizor 5
Dulton Media LLC 5
bdl premium 4
GolovachCourses 4
timera inc. 4
Slon.ru 3
По количеству постов
Яндекс 1 012
Microsoft 828
Intel 491
Google 422
Mail.Ru Group 317
Apps4All 292
Opera Software ASA 234
Samsung 215
ASUS Russia 209
ESET NOD32 200
ABBYY 197
IBM 190
HP 188
Evernote 186
Webnames.ru 169
МУК 154
Nokia 142
Zfort Group 134
Positive Technologies 131
Простая Наука 127
EPAM Systems 127
Sony Mobile Communications 116
КРОК 115
Turbomilk 103
Селектел 101
REG.RU 97
Box Overview 96
Ciklum 96
SmartGadget 94
JetBrains 87
(...)
HotSupport -2
Worksection -2
Далее -2
МФИ Софт -2
NVIDIA Corporation -2
DeepArtment -2
RuTube -2
Самый Нужный ТЕЛЕФОН -3
«Студия — 8812» -3
590.com.ua -3
Microsoft 828
Intel 491
Google 422
Mail.Ru Group 317
Apps4All 292
Opera Software ASA 234
Samsung 215
ASUS Russia 209
ESET NOD32 200
ABBYY 197
IBM 190
HP 188
Evernote 186
Webnames.ru 169
МУК 154
Nokia 142
Zfort Group 134
Positive Technologies 131
Простая Наука 127
EPAM Systems 127
Sony Mobile Communications 116
КРОК 115
Turbomilk 103
Селектел 101
REG.RU 97
Box Overview 96
Ciklum 96
SmartGadget 94
JetBrains 87
(...)
HotSupport -2
Worksection -2
Далее -2
МФИ Софт -2
NVIDIA Corporation -2
DeepArtment -2
RuTube -2
Самый Нужный ТЕЛЕФОН -3
«Студия — 8812» -3
590.com.ua -3
Для начала меня удивил тот факт, что есть 2 вида отсутствия компании — «компания деактивирована» и «страница не найдена». Хотя повторюсь — все компании были взяты из списка. Первый вид я помечал количеством постов -2. Таких компаний довольно много. И три компании, название которых состоит из цифр — ведут на «страница не найдена». Их я пометил -3. Такие вот дела. Также полно компаний с нулевым количеством постов — например Apple. Интересно, зачем создавать аккаунт для компании и вообще не писать с него?
Собственно, если из тех 1343, зарегистрированных на хабре, вычеркнуть несуществующие и компании без постов, то останется всего 321. Такие вот дела.
Разработка
Очень долго я пытался разобраться в Хабрахабр Api. Как выяснилось, он закрыт и пока что в процессе разработки. Однако в переписке с support@habrahabr.ru мне сказали, что они не имеют ничего против парсинга их страниц. Собственно, именно так и работают хабраклиенты для Android (на данный момент).Когда речь идёт о проектах «для себя», я выбираю любимую Джаву. Она и на этот раз меня не подвела — библиотека JSoup позволила в несколько строчек получить необходимые данные с HTML страницы. Но давайте сперва обсудим, как устроены хабы.
Страницы с хабами расположены по адресам habrahabr.ru/hubs/pageN/, где N — номер от 1 и далее. Посему, если мы хотим получить полный список из всех хабов — нам нужно загружать и анализировать эти страницы, пока они не закончатся. На каждой странице присутствует список из хабов. Формат элемента списка довольно простой и легко анализируется. Выглядит он так:
<div class="hub " id="hub_50">
<div class="habraindex">1 280,58</div>
<div class="info">
<div class="title">
<a href="http://habrahabr.ru/hub/infosecurity/">Информационная безопасность</a>
<span class="profiled_hub" title="Профильный хаб"></span>
</div>
<div class="buttons">
<input type="button" class="mini blue subscribeHub" value="Подписаться" data-id="50">
<input type="button" class="mini hidden unsubscribeHub" value="Подписан" data-id="50" "="">
</div>
<div class="clear"></div>
<div class="stat"><a href="http://habrahabr.ru/hub/infosecurity/subscribers/" class="members_count">91741 подписчик</a>, <a href="http://habrahabr.ru/hub/infosecurity/posts/">3385 постов</a><a></a></div><a>
</a></div><a>
</a></div>
Давайте напишем метод, который возвращает нам список из всех хабов на сайте:
static List<Hub> getAllHubs() {
ArrayList<Hub> fullHubsList = new ArrayList<>();
String urlHubsIncomplete = "http://habrahabr.ru/hubs/page";
int pageNum = 1;
do {
String urlHubs = urlHubsIncomplete + pageNum;
try {
Document doc = Jsoup.connect(urlHubs).get();
Elements hubs = doc.select(".hub");
if (hubs.size() == 0) {
break;
}
for (Element hubElem : hubs) {
Hub hub = new Hub(hubElem);
fullHubsList.add(hub);
}
pageNum++;
} catch (Exception e) {
e.printStackTrace();
break;
}
} while (true);
return fullHubsList;
}
Мы крутим бесконечный цикл while, формируя с каждой итерацией новый URL. Затем, с помощью Jsoup.connect(urlHubs).get() получаем непосредственно HTML-документ со списком хабов и их параметрами. Как несложно заметить — div с информацией о хабе имеет класс hub — и, вызвав doc.select(".hub"), мы получаем список из этих элементов. Если его размер равен нулю — значит мы прошли последнюю страницу и уже проанализировали все хабы — тогда мы выходим из цикла.
Далее — проходим по всем хабам-элементам и для каждого создаём объект типа Hub, передав в конструктор наш org.jsoup.nodes.Element. В нём располагается HTML-код такого же формата, как указан выше. Теперь давайте абстрагируемся от всего. Для этого и существует ООП. Перед нами есть только тот кусочек HTML, представленный выше, и класс, в который его нужно запихнуть. Напишем каркас для нашего класса:
import org.jsoup.nodes.Element;
public class Hub {
String title;
int posts;
boolean profiled;
int membersCount;
float habraindex;
String url;
public Hub(Element hubElem) {
}
}
Напишем конструктор. Для начала сделаем самое простое — получим данные из заголовочного тега. Для этого мы сначала извлекаем сам div вида
<div class="title">
<a href="http://habrahabr.ru/hub/infosecurity/">Информационная безопасность</a>
<span class="profiled_hub" title="Профильный хаб"></span>
</div>
Парсим через
Element titleDiv = hubElem.select(".title").get(0);
Element tagA = titleDiv.getElementsByTag("a").get(0);
title = tagA.text();
url = tagA.attr("href");
profiled = (hubElem.select(".profiled_hub").size() != 0);
Далее, мы хотим пропарсить количество подписчиков и постов — собственно те параметры, по которым мы и будем сортировать. Но сразу же сталкиваемся с первой проблемой — тег содержит строку «91741 подписчик», которую мы не можем просто так взять и преобразовать в Integer — она содержит буквы! Тут нам на помощь приходят регулярные выражения. Быстренько пишем ловкий метод, который получает строку и вырезает из неё всё, кроме цифр, да ещё и преобразует результат в int. \D — это НЕ цифра, а + — «встречается 1 или более раз». Т.е. мы в данном случае заменяем буквы на пустоту.
private int getNumbers(String str) {
String numbers = str.replaceAll("\\D+", "");
return Integer.valueOf(numbers);
}
Вот теперь мы уже можем со спокойной душой получить наши значения:
String membersCountFullStr = hubElem.select(".members_count").get(0).text();
membersCount = getNumbers(membersCountFullStr);
String statFullStr = hubElem.select(".stat").get(0).getAllElements().get(2).text();
posts = getNumbers(statFullStr);
В принципе, на этом можно было остановится, но я решил ради интереса извлечь всю возможную информацию о хабе. Тут возникла весьма интересная вторая проблема, которая будет изюминкой статьи. Как пропарсить хабраиндекс?
Для начала, следует заменить запятую на точку и убрать лишние пробелы. Но этого не достаточно! Парсер всё равно выдаёт ошибку, если скопировать и вставить хабраиндекс в код — Double.valueOf("–1.11"). А если ввести вручную то же самое число — всё окей. Причём визуально в моей IDEA они абсолютно идентично выглядят!
Оказывается, дизайнеры хабры просто использовали dash вместо minus — c иным кодом символа, и парсер его, понятное дело, не ест. Возьмите на заметку. Суть проблемы в следующем:
System.out.println((int)'-');//45
System.out.println((int)'–');//8211
Когда-то в своей статье Хитрые задачи по Java я рассмотрел подвох, когда L маленькую можно не отличить от 1. Собственно, сейчас я напоролся на аналогичную проблему.
Посему, код для извлечения хабраиндекса будет чуть сложнее:
String rawHabraIndex = hubElem.select(".habraindex").get(0).text();//1 265,92
char minus = 45;//'-'
char dash = 8211;//'–'
String niceHabraIndex = rawHabraIndex.replaceAll(" ", "").replace(",", ".").replace(dash,minus);//1266.72
habraindex = Float.valueOf(niceHabraIndex);
Далее, пишем компаратор по постам как вложенный статический класс для Hub
public static class ComparePosts implements Comparator<Hub> {
@Override
public int compare(Hub o1, Hub o2) {
return o2.posts - o1.posts;
}
}
И сортируем по нему где-нибудь в main
List<Hub> hubs = getAllHubs();
Collections.sort(hubs, new Hub.ComparePosts());
Всё, задача выполнена! С количеством подписчиков аналогично. Далее я написал код, который выводит в консоль два списка в таком виде, чтобы их сразу можно было вставить в статью — и сделал это вначале.
На получение всех хабов уходит примерно 10 секунд. Исходный код можно скачать здесь. Собираем и запускаем вот так, не забыв установить Jsoup и заменить путь на ваш:
javac -cp .;"C:\prog\lib\jsoup-1.7.3.jar" com/kciray/habrahubs/Main.java
java -cp .;"C:\prog\lib\jsoup-1.7.3.jar" com.kciray.habrahubs.Main
Кроме того, я переделал эти же классы для сбора статистики по компаниям. Там, казалось бы, всё аналогично — однако чтобы узнать количество постов в блоге компании, пришлось подгружать страничку для каждой по отдельности — а это заняло уже около 5 минут. Я сделал многопоточную загрузку для ускорения. Обнаружил, что хабра не позволяет грузить больше чем 5-7 страниц одновременно. Собственно, сериализовал ArrayList<CompanyBlog> и записал. Этот файлик на 100 килобайт лежит вместе с вторыми исходниками — можете поработать с ним.
Если вас интересует полный рейтинг и в более компактном виде — я выложил его в виде веб-страницы.