СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

| сохранено

H Как я здравый смысл на Vk.Api променял в черновиках

C#, API, .NET
Добрый день.
У меня осталось 15 минут до конца обеденного перерыва (это важно), завтра выходной, а потому прошу мой пост приравнивать к пятничному.
В своем недавнем посте товарищ ParadoxFilm исследовал связи между участниками одной из групп «ВКонтакте», саму группу оставив анонимной. Поскольку в статье фигурировали реальные люди — участники группы, анонимизация по названию меня удивила. Процесс «деанонимизации» — под катом.



Итак, есть три человека юзера: id97723 — Валерий Окунев, id206186029 Глеб Коломиец, id105522823 Ингруп Стс. Все они участники одной группы почти на 16000 человек, группа университетская. Задача: отыскать группу.

Первым делом я открыл контакты юзеров — если уж истина где-то рядом, почему бы ей не быть там? Один товарищ упоминает КВН с выступающей командой ВШЭ, другой там учился (третий состоит в группе dotNet разработчиков, привет, коллега). Окей, ищем группы по названию «ВШЭ». Результатов десятки, но поиск контакта удобно сортирует их по числу участников. Группы с 16 000 юзеров нет. Шерлок Холмс знал бы самые часто используемые синонимы, но мое имя даже на Ш не начинается.

Так что я расчехлил свою привычную VS2015 с Dark Theme, и скачал VkNet библиотеку — она первая попалась в гугле. Обновил все необходимые NuGet пакеты, сориентировал проект на .net framework 4, накидал код
        private static readonly int[] UserIds = { 97723, 206186029, 105522823 }; 
        private static readonly VkApi Api = new VkApi();

        static void Main(string[] args)
        {
            var zeroUserGroups = GetUserGroups(UserIds[0]);
            Thread.Sleep(1000);
            Console.WriteLine($"Groups for id {UserIds[0]}: {zeroUserGroups.Count}");


            var firstUserGroups = GetUserGroups(UserIds[1]);
            Thread.Sleep(1000);
            Console.WriteLine($"Groups for id {UserIds[1]}: {firstUserGroups.Count}");


            var secondUserGroups = GetUserGroups(UserIds[2]);
            Thread.Sleep(1000);
            Console.WriteLine($"Groups for id {UserIds[2]}: {secondUserGroups.Count}");

            // Тут мы ищем группы, встречающиеся в наборах всех юзеров.
            // Эх, надо было сразу вместо групп идентификаторы выделять
            var groupsIntersection = zeroUserGroups
                .Where(group => firstUserGroups.Any(insGroup => insGroup.Id == group.Id))
                .Where(group => secondUserGroups.Any(insGroup => insGroup.Id == group.Id))
                .ToList();            
        }

        private static ReadOnlyCollection<Group> GetUserGroups(long userId)
        {
            GroupsGetParams getUserGroupParams = new GroupsGetParams() {UserId = userId};
            return Api.Groups.Get(getUserGroupParams);
        }


и словил баттхерт исключение. Неавторизованный доступ, все дела. Пришлось регистрироваться в контакте, создавать приложение, копипастить applicationId, mail моей странички и мой же пароль в код (не повторяйте это в продакшне).

В итоге в самом начале метода Main появился код
            ApiAuthParams authParams = new ApiAuthParams
            {
                ApplicationId = myAppId,
                Login = "my@mail.com",
                Password = "myPagePassword",
                Settings = Settings.All
            };
            Api.Authorize(authParams);


В итоге все заработало, я получил лист из двух групп: 25205856, 66036248. Вторая группа называется «The Вышка», в ней сейчас 15968 человек. Среди них, кстати, и автор первоначальной статьи.
Удачи тебе в IT, бро.
P.S. Процесс поиска занял 45 минут, «за 15 минут я еще и бутерброд доесть успею».

комментарии (15)

+1
riot26 ,  
А зачем в коде логин/пароль? Можно ведь было обойтись более безопасным auth token`ом с правами только на нужные штуки.
0
Oxoron ,  
Несомненно, oauth безопаснее. Другое дело, что мою одноразовую страницу не жалко, а авторизация логин-пароль-applicationId делается быстрее.
+5
LoadRunner ,  
А вот и здравый смысл:
1. Открываем все три профиля.
2. Делаем те же выводы про ВШЭ.
3. Открываем «Интересные страницы» третьего профиля и смотрим на список.
4. The Вышка у меня оказалась в самом верху и только у неё около 16к подписчиков.
5. За минуту проверяем в первых двух профилях её наличие в аналогичном разделе.
0
Oxoron ,  
Шампанского этому господину!
Не знал, что «Интересные страницы» в контакте приравнены к группам.
0
+1 –1
LoadRunner ,  
Мне просто повезло :)
Интересная страница — это что-то между личной страницей и группой.
Давно заметил, что у тех, кто подписан на меня вконтакте (добавили в друзья) я попадаю в этот блок. Подозреваю, связано с общим числом друзей — когда оно переваливает за определённое число, личная страница трансформируется и где-то в недрах базы получает некий статус «интересности». Но это лишь моя теория.
И при создании группы можно сразу определить — она будет создана именно как группа или просто Публичной страницей. Во втором случае она так же попадает в блок «Интересные страницы».
Ну и у второго и третьего профиля даже блок групп не скрыт. А вот «интересные страницы» не скрываются вовсе (если это пункт «кого видно из моих друзей и подписок» в настройках приватности, то мало кто будет так заморачиваться для скрытия публичной группы). По третьему профилю вообще очень легко всё деанонимизируется.
0
sshk ,  
А The Вышка — это не группа, а паблик. Поэтому ее и можно увидеть в интересных страницах.
+1
impwx ,  
Скачать три списка групп через готовую библиотеку, найти пересечения, два полученных результата проверить руками… Как-то не тянет на сакральное знание, которым нужно было поделиться с сообществом.
–2
Oxoron ,  
Вы абсолютно правы, статья не самая серьезная. Я честно постарался это выразить катом, первым абзацем и тэгами.
0
ParadoxFilm ,   * (был изменён)
Привет! Как было указано в комментах к моей статьи, ссылки на группу не было по причине того, что это запрещено правилами хабра. Конечно, узнать коей она является — труда не составит (ибо цель скрыть её никто не преследовал).
По вашей статье: не понятно, зачем авторизация (методы получения списка групп пользователя доступны без этого). Также неясно, зачем использовать библиотеку (ведь есть API ВКонтакте).
P.S. Лестно, что статья написана относительно моей. Спасибо, это было интересно!
P.P.S. Группа, естественно, найдена верно.
0
Oxoron ,  
Насчет авторизации — сам удивился. Возможно azhidkov (автор библиотеки) не учел этого момента. Кстати, библиотека как раз с API работает.
+2
+4 –2
lizarge ,   * (был изменён)
Это хабрахабр или переписка студентов неудачников аналитиков тут? Если к первой статье можно было хоть что то разумное предьявить то тут уже нечего и сказать.
Вау у вконтакте есть API а VS2015 с Dark Theme это конечно показатель глубокого профессионализма, если поставите Dark Green Theme то все девчата с соседнего ПТУ ваши конечно. Группы еще какие то в ВК, детский сад.
+3
kstep ,  

Что это за детский сад на главной? О чём это всё?

0
+1 –1
drdoc ,  
А можно… Можно я тоже напишу как я скриптики на руби писал с вк апи??? Иль заминусуют меня за это. Хотя там и скриптики намного сложнее, чем «это». Но все же :)
0
aquamakc ,  
int[] UserIds — тип Int32 передаётся в GetUserGroups(long userId) — тип Int64,
Thread.Sleep(1000); — зачем?

Да и вообще для хабра как-то слабовато.
–1
Oxoron ,  
1. В моем случае массив состоит из констант. Константы в пределах Int32, Int32 конвертится в Int64, потери времени не критичны.
2. Thread.Sleep(1000); — у API есть ограничение по запросам в секунду. Точного значения не помнил, поэтому взял с запасом. Опять-таки, потеря 3 секунд — не проблема.