Вконтакте html delphi. Пишем простейший спамер для ВКонтакте на Delphi

Вконтакте html delphi. Пишем простейший спамер для ВКонтакте на Delphi

17.03.2019

На создание данной статьи я был вдохновлен публикацией . Моя статья написана новичком и отражает опыт решения одной задачи. Основная цель написания этой статьи для меня - собрать мнения, отзывы и критику примененного подхода от более опытных коллег. Кроме того, надеюсь, что кому-то приведенная здесь информация будет полезна.

Не так давно в одном из тестовых задания на вакансию младшего php-программиста мне попалась простая, но интересная для меня задача.

«Сделайте скрипт на php, который возвращает список id пользователей «ВКонтакте», разделенный символами перевода строки, которые являются мужчинами старше 25 лет и состоят в группе vk.com/habr ».

Доступ к информации из базы «ВКонтакте» осуществляется с использованием VK API. Начинать знакомство с VK API лучше с официальной документации . Для того чтобы вызвать метод API ВКонтакте, необходимо осуществить POST или GET запрос по протоколу HTTPS на URL следующего вида:

Получаем JSON-структуру с общим количеством членов сообщества vk.com/habr и тысячей первых id в списке по умолчанию отсортированном по возрастанию.

По условию задачи нам нужно вывести id пользователей определенного пола и возраста. Очевидный способ - выбирать запросами VK API пользователей группы вместе с их данными о поле и возрасте, а потом в PHP-коде анализировать их и выводить только нужные. Другой возможный способ - метод execute - позволяет в одном запросе передать скрипт на специальном языке VKScript для манипуляции с данными на сервере и вернуть уже обработанные данные. Сразу скажу, что мне не удалось, решить задачу с помощью метода execute. Может быть в комментариях кто-то укажет такое решение.

Пойдем по первому пути. Метод groups.getMembers с помощью значения sex параметра fields может выдавать пол пользователя, но он не выдает возраст. Вместо этого параметр fields имеет поле bdate - дата рождения. Кроме того, в запросах мы выбираем по тысяче пользователей, значит каждый следующий запрос должен выдать следующую тысячу. Для этого есть параметр offset, который показывает с какой позиции начинать выборку. Укажем в запросе еще и версию API.

В итоге запрос будет иметь примерно такой вид: https://api.vk.com/method/groups.getMembers?group_id=habr&offset=0&fields=sex,bdate&version=5.27

Чтобы забирать файл по ссылке, в PHP есть функция file_get_contents() . Она получает контент по ссылке и возвращает его в виде строки. Нужно учесть, что для того, чтобы file_get_contents() понимала протокол HTTPS нужна поддержка openssl в веб-сервере.

Потом полученный JSON-контент можно преобразовать в массив функцией json_decode() . Массив будет содержать и id, и пол. Дата рождения может быть вообще не указана.
Если дата рождения всё же указана, осталось из даты рождения получить возраст.

Даты рождения в bdate хранятся в строках формата ДД.ММ.ГГГГ, если указан год рождения, или ДД.ММ, если год рождения не указан. Чтобы узнать в каком формате строка фактически, я использовал первое, что пришло в голову: count(explode(".", $user_array["bdate"])) равно 2 или 3. Этот способ работает и не думаю, что это самое узкое место скрипта.

Для вычисления возраста по дате рождения нашел формулу hashcode.ru/questions/137939#137940 . Функция strtotime() понимает формат поля bdate.

Проверяем пол и возраст. Если они удовлетворяют условию, выводим id.

Весь код на PHP

// Номер пакета запроса $packet = 0; // Размер пакета запроса $limit = 1000; do { // Каждый запрос начинаем там, где остановились в предыдущем запросе. $offset = $ packet * $limit; // Выполнение запроса. // Результат - JSON-файл с общим количеством и данными пользователей. // Чтобы file_get_contents() работал с https на веб-сервере apache // должен быть активен модуль openssl. $contents = file_get_contents("https://api.vk.com/method/groups.getMembers?group_id=habr&offset=$offset&fields=sex,bdate&version=5.27") // Преобразуем JSON в массив $members = json_decode($contents, true); // Данные пользователей хранятся в подмассиве users. // Каждый элемент users - ассоциированный массив с данными. foreach ($members["response"]["users"] as $user_array) { // Если пользователь указал дату рождения и пользователь - мужчина... if ((isset($user_array["bdate"])) && ($user_array["sex"] == 2)) { // ... и если в дате рождения три компонента (ДД.ММ.ГГГГ)... if (count(explode(".", $user_array["bdate"])) == 3) { // то вычисляем возраст (формулу нашел в интернете) $age = floor((time()-strtotime($user_array["bdate"]))/(60*60*24*365.25)); // Если возраст нам подходит, выводим id пользователя с переводом строки if ($age >
"; } } } } // Переходим на следующий пакет. $packet++; } while ($members["response"]["count"] > $offset + $limit);


Этот вариант прекрасно работает на относительно небольших группах, но на группах более 100 тысяч подписчиков скрипт отрабатывает не до конца - в какой-то момент почему-то вываливается ошибка «file_get_contents(...): failed to open stream: Connection timed out in … on line ...». Пробовал увеличивать время выполнения скрипта и таймаут веб-сервера - не помогло. Так и не смог найти закономерность.

Тогда нашелся другой вариант - для загрузки ответа запроса использовать cURL . Чтобы применить такой метод, необходимо установить в ОС библиотеку libcurl, например, в Ubuntu - sudo apt-get install libcurl3 и включить в PHP поддержку cURL, например, в Ubuntu - sudo apt-get install php5-curl Теперь можно открыть в PHP-скрипте сеанс curl функцией curl_init() , установить параметры соединения (в том числе URL) функцией curl_setopt() и скачивать контент JSON-файлов в строку функцией curl_exec() . Потом следует закрыть сеанс - curl_close() . Остальной код остается без изменений:

Весь код с cURL на PHP

// Номер пакета запроса $packet = 0; // Размер пакета запроса $limit = 1000; // Инициализируем cURL. // Для работы с cURL должна быть установлена библиотека libcurl // и включена поддержка cURL в PHP. $ch = curl_init(); do { // Каждый запрос начинаем там, где остановились в предыдущем запросе. $offset = $ packet * $limit; // Параметры запроса curl_setopt($ch, CURLOPT_URL, "https://api.vk.com/method/groups.getMembers?group_id=habr&offset=$offset&fields=sex,bdate&version=5.27"); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // Выполнение запроса. // Результат - JSON-файл с общим количеством и данными пользователей. $content = curl_exec ($ch); $members = json_decode($contents, true); // Данные пользователей хранятся в подмассиве users. // Каждый элемент users - ассоциированный массив с данными. foreach ($members["response"]["users"] as $user_array) { // Если пользователь указал дату рождения и пользователь - мужчина... if ((isset($user_array["bdate"])) && ($user_array["sex"] == 2)) { // ... и если в дате рождения три компонента (ДД.ММ.ГГГГ)... if (count(explode(".", $user_array["bdate"])) == 3) { // то вычисляем возраст (формулу нашел в интернете) $age = floor((time()-strtotime($user_array["bdate"]))/(60*60*24*365.25)); // Если возраст нам подходит, выводим id пользователя с переводом строки if ($age > 25) { echo $user_array["uid"] . "
"; } } } } // Переходим на следующий пакет. $packet++; } while ($members["response"]["count"] > $offset + $limit); // Закрываем cURL curl_close ($ch);


Как я уже говорил, думаю, возможен подход с методом execute, но мне пока не удалось получить в этом направлении удовлетворительный результат.

P. S. Прошу не думать, что я хочу получить от аудитории «Хабра» решение тестового задания. Вышеприведенные варианты я уже давно отправил и получил ответ. Просто немало времени потратил на эту задачу и хотел бы узнать, в правильном направлении ли я двигался и какие еще подходы можно было бы использовать.

Вполне сгодится для работы с любой социальной сетью или онлайн сервисом, которые предоставляют нам в распоряжение API. Но “ВКонтакте”, всё же из всех мне известных социальных сетей (за исключением, наверное, Twitter) является самой популярной в России, поэтому с ней и попробуем поработать, используя в работе Delphi XE6 . Ну, а чтобы было ещё более занимательно, попробуем написать небольшое приложение для Android . Кому потребуется приложение для Windows и VCL, думаю легко разберется в том, какие модули следует подключить в uses, а какие наоборот - убрать.

1. Создаем свое приложение “ВКонтакте” и пробуем авторизовать пользователя.

Для начала работы с API “ВКонтакте” необходимо создать новое приложение и получить необходимые данные для авторизации пользователей. Для этого заходим на страницу разработчиков и жмем вверху страницы кнопку “Создать приложение “:

Жмем кнопку “Подключить приложение” после чего вам предложат подтвердить свое действие, выслав на мобильный телефон проверочный код. После подтверждения Вам станет доступно изменение настроек приложения:

Переходим на вкладку “Настройки” и запоминаем ID приложения и Защищенный ключ :

Теперь можно переходить к Delphi XE6 и попробовать реализовать авторизацию пользователя.

Запускаем Delphi XE6, создаем новый проект для мобильных устройств и на главную форму бросаем компоненты, покзанные на рисунке ниже:

Сейчас нам нужны будут следующие компоненты: TButton , TRESTClient , TRESTRequest , TRESTResponse и TOAuth2Authenticator . Клик по кнопке TButton будет вызывать процесс авторизации пользователя. Для начала, напишем процедуру авторизации пользователя.

Теперь необходимо вызвать форму для авторизации пользователя “ВКонтакте” и получить Access Token. Как это делать я достаточно подробно рассказывал в самоё первой статье по . Подключаем в uses модуль REST.Authenticator.OAuth.WebForm.FMX и определяем следующую переменную:

type TForm1 = class (TForm) [ ... ] private WebForm: Tfrm_OAuthWebForm; public { Public declarations } end ;

Напомню, что Tfrm_OAuthWebForm - это форма, на которой расположен компонент TWebBrowser с помощью которого пользователь заходит на сайт, чтобы ввести свои логин/пароль и получить доступ для приложения к каким-либо данным своего аккаунта. Соответственно нам, как разработчикам, эта форма необходима, как минимум, для того, чтобы “отловить” редирект на специальный URL, который будет содержать необходимый нам Access Token. Для управления редиректами у Tfrm_OAuthWebForm определено сразу два события:

type TOAuth2WebFormRedirectEvent = procedure (const AURL: string ; var DoCloseWebView : boolean ) of object ; property OnBeforeRedirect: TOAuth2WebFormRedirectEvent read FOnBeforeRedirect write FOnBeforeRedirect; property OnAfterRedirect: TOAuth2WebFormRedirectEvent read FOnAfterRedirect write FOnAfterRedirect;

Нам необходим обработчик события OnAfterRedirect. Напишем его:

type TForm1 = class (TForm) [ ... ] private WebForm: Tfrm_OAuthWebForm; procedure AfterRedirect(const AURL: string ; var DoCloseWebView : boolean ) ; [ ... ] public { Public declarations } end ; procedure TForm1. AfterRedirect (const AURL: string ; var DoCloseWebView: boolean ) ; var i: integer ; Str: string ; Params: TStringList; begin i: = pos ("#access_token=" , AURL) ; if (i> 0 ) and (OAuth2Authenticator1. AccessToken = EmptyStr) then begin Str: = AURL; Delete (Str, 1 , i) ; Params: = TStringList. Create ; try Params. Delimiter : = "&" ; Params. DelimitedText : = Str; OAuth2Authenticator1. AccessToken : = Params. Values [ "access_token" ] ; OAuth2Authenticator1. AccessTokenExpiry : = IncSecond(Now, StrToInt (Params. Values [ "expires_in" ] ) ) ; finally Params. Free ; end ; WebForm. Close ; end ; end ;

Таким образом, после редиректа мы проверяем есть ли в URL подстрока #access_token= и, если такая строка имеется, то вытаскиваем из URL данные по Access Token и время его жизни - значение параметра expires_in.

Обратите внимание, что данные для доступа к API мы записываем сразу в компонент TOAuth2Authenticator1

Теперь нам необходимо создать форму, определить обработчик OnAfterRedirect и в нужный момент показать эту форму пользователю.
Что касается создания/уничтожения объекта формы, то это можно сделать где вам удобно. Для примера, я создаю форму авторизации в OnCreate главной формы, а уничтожаю, соответственно, в OnDestroy:

procedure TForm1. FormCreate (Sender: TObject ) ; begin WebForm: = Tfrm_OAuthWebForm. Create (nil ) ; WebForm. OnAfterRedirect : = AfterRedirect; end ; procedure TForm1. FormDestroy (Sender: TObject ) ; begin WebForm. Free ; end ;

type TForm1 = class (TForm) [ ... ] private WebForm: Tfrm_OAuthWebForm; procedure AfterRedirect(const AURL: string ; var DoCloseWebView : boolean ) ; procedure Auth; public { Public declarations } end ; procedure TForm1. Auth ; begin OAuth2Authenticator1. AccessToken : = EmptyStr; OAuth2Authenticator1. ClientID : = cAppID; OAuth2Authenticator1. ClientSecret : = cAppKey; OAuth2Authenticator1. ResponseType : = TOAuth2ResponseType. rtTOKEN ; OAuth2Authenticator1. AuthorizationEndpoint : = cEndPoint; WebForm. ShowWithURL (OAuth2Authenticator1. AuthorizationRequestURI ) ; end ;

Здесь мы, опять же, используем компонент TOAuth2Authenticator - записываем в него данные нашего приложения (ID и секретный ключ), а также получаем URL, по которому необходимо перейти пользователю для авторизации.

В этом уроке я покажу вам достаточно простой и эффективный способ авторизации в небезызвестной социальной сети ВКонтакте, например, для получения какой-либо информации.
Всем известно, что в социальных сетях в настоящее время зарегистрировано огромное количество пользователей, в частности в соц. сети ВКонтакте. Поэтому синхронизация, привязка различных данных из аккаунтов соц. сетей к различным приложениям и играм является достаточно актуальной темой. Для того чтобы получать эту информацию в Delphi, можно провести авторизацию посредством библиотеки Indy, принять все cookies и получить необходимую информацию. В интернете можно найти огромное множество различных способов авторизации ВКонтакте посредством Indy, однако будьте уверены, что 99% этих способов не работают, или перестали работать уже очень давно. Это обуславливается тем, что ВКонтакте постоянно изменяется, в него вносится постоянно множество изменений. Способ, который предлагаю я, на сегодняшний день (12 марта 2012) работает достаточно неплохо. Итак, привожу код самой авторизации с подробными комментариями:
var
s: string;
http: TIdHTTPEx;
begin
http:= TIdHTTPEx.Create;
// Создаем экземпляр класса TIdHTTPEx
http.Request.UserAgent:=
‘Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.7.62 Version/11.01’;
// Маскируемся под оперу 🙂
try
s:= http.GetEx(‘http://vk.com/login.php?m=1&email=’ + email +
‘&pass=’ + pass);
// пробуем залогиниться
// для этого выполняем обычный GET запрос, в котором прямо в адресе передаем
// значения email и pass
except
// при авторизации происходит редирект,
// который обязательно необходимо обработать,
// иначе корректно залогиниться нам не удастся
if http.ResponseCode = 302 then
s:= http.GetEx(‘http://vk.com’ + http.Response.Location);
end;

Обратите внимание на то, что в качестве email`а нужно указывать email, который привязан к аккаунту! Если вы укажете вместо email свой номер телефона, по которому вы регистрировались, или логин, то авторизация скорее всего будет неуспешной. В настоящее время привязка аккаунта ВКонтакте к email не обязательна и при регистрации не требуется. Привязать ваш email к аккаунту можно в настройках аккаунта.

Как вы уже заметили, для проведения самой авторизации я использую не стандартный класс TIdHTTP, а TIdHTTPEx, который отличается тем, что более корректно принимает и отправляет печенья. TIdHTTPEx основан естественно на базе стандартного TIdHTTP. Для работы с TIdHTTPEx вам потребуется скачать модуль по этой ссылке , кинуть его в папку с будущим проектом, а затем объявить его в разделе uses.

Итак, если логин и пароль были введены правильно, то авторизация должна пройти без проблем. Чтобы проверить авторизировались ли мы, давайте пропарсим полученный исходный код страницы ВКонтакте, который я поместил в строковую переменную s. Определить успешность авторизации достаточно просто: для этого мы всего лишь поищем в той самой строке s слово ‘logout’, которое появляется в исходном коде в ссылке ‘Выйти’ (для выхода из аккаунта). Если это слово в строке s обнаружено, значит мы успешно авторизировались:
if Pos(‘logout’, s) <> 0 then
ShowMessage(‘Авторизация успешна’)
else
ShowMessage(‘Авторизация неудачна’);
Поместим этот код сразу же после кода с авторизацией.
Теперь, когда мы прошли авторизацию, мы можем получать различную информацию из аккаунта. Делается это достаточно простым парсингом строки s. Можно также зайти на другую страницу ВКонтакте, мы все равно будем авторизованны. Кстати парсить строки очень удобно при помощи библиотеки RegExpr.

Доброго времени суток уважаемые читатели! Сегодня мы с вами поговорим про API ВКонтакте, точней об использовании API в Delphi. Я буду использовать в этой статье Delphi 2010, в принципе вам ее использовать не обязательно, данный материал будет применим к любой версии Delphi. И так, сегодня мы с вами рассмотрим метод авторизации в VK.COM с помощью indy, настройку компонентов indy для работы с API VK. На самом деле все очень-очень просто и 100 раз находится в гуглояндексе и других поисковиках. Но большинство из них написаны еще под vkontakte.ru, API тогда естественно было другое. Ну да ладно, давайте начинать. Для начала нам понадобятся компоненты:

  • IdHTTP
  • IdSSLIOHandlerSocketOpenSSL
  • IdCookieManager

Ну и стандартно:

  • TLabel
  • TEdit
  • TButton

Настраиваем компоненты

ВАЖНО! В папку с исполнительным файлом программы копируем эти DLL

Они есть в архиве к этому материалу.
И так, настройка компонентов для авторизации вконтакте завершена, необходимые DLL библиотеки скопированы, теперь напишем немного кода.

Procedure TForm1.Button1Click(Sender: TObject); var TmpStr: string ; json: TJSONObject ; client_id ,client_secret: string ; Token, IdUser: string ; begin client_id:= Ваш ID полученный на сайте Вконтакте; client_secret:= Секрет от туда же; try TmpStr:= IdHTTP.Get("https://oauth.vk.com/token?grant_type=password&client_id="+client_id+"&client_secret="+client_secret+"&username="+EdtEmail.Text+"&password="+EdtPass.Text); except on E: Exception do begin MessageBox(Application.Handle, PChar(Format("Ошибка: %s",)), "Error", MB_ICONHAND); exit ; end; end; json:= TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TmpStr),0) as TJSONObject; Token:= json.Get(0).JsonValue.ToString; Token:= StringReplace(Token, """, "", ); IdUser:= json.Get(2).JsonValue.ToString; end;

я осознанно опускаю ту часть в которой обычно рассказывают про то как получить ID и секрет от вконтакте, это вы уже читали в предыдущих постах. У нас же будет только самое необходимое, не какого левого материала).
Объясню код:
Первое что вы наверное не видели в других уроках это json: TJSONObject, да да, я правильно разбираю ответы от сервера, так как того просит религия;). Другими словами это правильная переменная для хранения ответа от сервера на наш GET запрос. Инициализируется она просто: json:= TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TmpStr),0) as TJSONObject; поля вытащить из нее тоже не составляет большого труда: Token:= json.Get(0).JsonValue.ToString;
Токен и айди пользователя нужны для дальнейшего выполнения API функций, о которых мы поговорим с вами в следующих статьях.
Ну собственно и все на этом по коду. Проверку авторизации не делаю, оставляю это вам)))



© 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows