HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 09.02.2013, 17:04
BlackIce
Участник форума
Регистрация: 10.01.2013
Сообщений: 100
Провел на форуме:
18665

Репутация: 27
По умолчанию

Интро


Сейчас актуально писать мелкий говнософт для разных социальных сетей. Обычно начинающие быдлокодеры пишут подобное с помощью процедурного подхода и если проект более-менее сложный начинают захлебываться в глобальных переменных и значениях процедур и функций. Я хочу продемонстрировать ООП подход и его приимущества. В статье будет ценен не код программы (скорее он то только для устрашения), а способ мышления при использовании ООП подхода.

Этап 1


ТЗ: Написать дампер сообщений социальной сети ВКонтакте с возможностью дампить переписку как по SID так и по логину/паролю.

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

Что нам понадобится?

1) Язык поддерживающий ООП (Я пишу на Дэльфи)

2) Сниффер сетевого трафика (работать будем в основном с http поэтому httpAnalyzer вполне устроит).

Этап 2


По ООП есть куча разной литературы. Я попробую максимально доступно объяснить всю суть на конкретном примере. Итак, исходя из ТЗ мне нужно создать класс объекта, который смог бы проделывать определенные операции на сайте. Для начала происнифаем сайт и разберемся в алгоритмах запросов. Об этом я вообще писать не буду. По окончании у нас будет алгоритм примерно такой:

1 - Авторизуемся

2 - парсим корешей

3 - парсим месаги

Создаем новый класс объекта . Коротко немного теории : каждый класс что-то знает и что-то умеет делать. То что класс знает называется полями класса (если угодно переменные), а то что он умеет - называется методами класса (если угодно процедуры и функции)... В самомо начале проэктируется внешний вид класса (что знает умеет), а потом реализация (как он умеет). Чтож, давайте попробуем определиться, что необходимо знать и уметь нашему классу...


Знать: авторизационные данные (логин пароль), SID пользователя, количество друзей пользователя, список ID друзей, и он должен взаимодействовать с сетью по протоколу http, поэтому будет разумно запихнуть в него объект типа TidHTTP. Можно продолжать, но в учебных целях притормозим

Уметь: Авторизоваться, Парсить ID друзей, Парсить сообщения.

Также, каждый объект класса будет инициализирован под средством метода конструктора Create () . В нем удобно создавать объекту все условия для комфортной работы (создавать файлы/ соединяться с БД/ задавать настройки по умолчанию других объектов.)

Код:
//---------------Class for work with Vk.com--------- 
type
    TVKDump = Class
                Login, Password : String; // Данные для авторизации
                Link : String;            // Нужная шняга
                SID : String;             // Значение remixsid в кукисах
                HTTP : TidHTTP;           // Для работы с нетом
                FriendList : TStringList; // Список ИДшников друзей
                FriendCount : Integer;    //Количество друзей
                function ParseMessage (FriendID : String) : Boolean;   //Вытаскиваем сообщения со скритов
                function Authorize () : Boolean;                      //Авторизация
                function ParseFriends () : Integer;                   //Парсим ИД корешей
                constructor Create ();                                // Чето создаем и настраиваем
              end;
//-------------------------------------------------
Этап 3


Вот собственно и все! Осталось всего ничего описать реализацию каждой функции . Здесь в подробности я вдаваться не буду, просто выложу свой быдлокод .... Там в основном парсинг и танци с бубном вокруг запросов к ВК.

Код:
//------------function parse messages with a script--------------------------
function TVKDump.ParseMessage (FriendID : String) : Boolean;
  var Data, MsgList : TStringList;
      Name, Mess, tmp : String;
      i, j : Integer;
  begin
    Result := True;
try
 try
    HTTP.AllowCookies := False;
    HTTP.Request.CustomHeaders.Clear;
    HTTP.Request.CustomHeaders.Add('Cookie:remixsid=' + SID);
    MsgList := TStringList.Create;
    Data := TStringList.Create;

      for j := 0 to 5 do
        begin
          Data.Clear;
          Data.Add('act=a_history');
          Data.Add('al=1');
          // offset - параметр смещения сообщений, можно пробовать подставлять
          Data.Add('offset=' + IntTostr(j*50));
          Data.Add('peer=' + FriendID);
          Data.Add('whole=0');

          tmp := HTTP.Post('http://vk.com/al_im.php', Data);
          HTTP.AllowCookies := True;
          Sleep(200);
            for i := 1 to 100 do
              begin
                Delete(tmp, 1, Pos('class="mem_link" target="_blank">', tmp) + 32);
                Name := Copy(tmp, 1, Pos('', tmp) - 1);
                Delete(tmp, 1, Pos('', tmp) + 5);
                Mess := Copy(tmp,1, Pos('', tmp) - 1);
                MsgList.Add(Name + ':' +Mess);
              end;
       end;
       MsgList.SaveToFile(FriendID + '_damp.txt');
 except
  Result := False;
 end;
finally
    MsgList.Free;
    Data.Free;
end;
  end;

//----------------------------------------------------------

//-----------------authorization-----------------------------
function TVKDump.Authorize () : Boolean;    

//---------------parse link necessary to request-------------
function ParseLink ( Page : String) : Boolean;
  begin
    Result := false;
    Delete(page,1,Pos('action=',page)+15);
    link := Copy(page,1,pos('>',page)-2);
      if link <> ''
        then
          begin
            Link := 'http://' + Link;
            Result := true;
          end;
  end;
//--------------------------------------------------------------

var Data:TStringList;
    tmp: String;

  begin
    Result := False;
      try
        try
				  Data := TStringList.Create;
				  Data.Add('email='+Login);
				  Data.Add('pass='+Password);

//-----------  реализация быдлятская, но нет времени делать норм -----------------------
          ParseLink(HTTP.Get('http://m.vk.com/login'));
          HTTP.HandleRedirects := False;
          HTTP.AllowCookies := False;
          try
				    HTTP.Post(Link, Data);
          except
            try
              HTTP.Get(HTTP.Response.Location);
            except
              tmp := HTTP.Response.RawHeaders.Text;
              Delete(tmp, 1, Pos('remixsid=',tmp) + 8);
              SID :=Copy( tmp,1 ,Pos('expires=',tmp)-3);
            end;

          end;
//--------------------------------------------------------------------------------------
          HTTP.HandleRedirects := True;
          HTTP.AllowCookies := True;
          tmp := HTTP.Get(HTTP.Response.Location);

          
				    if Pos('logout',tmp) <> 0
					    then Result := True;
			except
				Result := False;
			end;
			finally
				Data.Free;
			end;

		end;

//-------------parsing function friends ID's -----------------------
// парсит вроде первых 20 чтобы парсило всех нужно допиливать

function TVKDump.ParseFriends () : Integer;
var tmp: String;
    i:integer;
  begin
    HTTP.AllowCookies := False;
    HTTP.Request.CustomHeaders.Add('Cookie:remixsid=' + SID);
    tmp := HTTP.Get('http://m.vk.com/friends');
    HTTP.AllowCookies := True;
    Delete(tmp,1,Pos(' ',tmp)+4);
    FriendCount :=StrToInt(Copy(tmp,1,Pos('',tmp)-1));
      for i:=1 to 18  do

        begin
          Delete(tmp,1,Pos('',tmp)-1));
        end;
    FriendList.SaveToFile('friends.txt');
  end;
//-----------------------------------------------------------

//-------------- Созаём нужные объекты и настраиваем HTTP ----------------
constructor TVKDump.Create ();

  begin
    FriendList := TStringList.Create;
    HTTP := TIdHTTP.Create(nil);
    HTTP.HandleRedirects := True;
      with HTTP.Request do
        begin
          UserAgent := 'Mozilla/5.0 (Windows NT 5.1; rv:16.0) Gecko/20100101 Firefox/16.0';
          ContentType := 'application/x-www-form-urlencoded';
          AcceptLanguage := 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3';
        end;

  end;
Этап 4


На 4 этапе необходимо создать объект нашего класса. Для этого его нужно инициализировать методом Create (). Также описывается поведение объекта и взаимодействие с другими компонентами программы. Дабы немного поизвращаться я не стал делать GUI. Программа получает необходимые данные ввиде параметров командной строки, а результаты пишет в файлы.

Код:
Var
      VK : TVKDump;
      i : Integer;
begin
  VK := TVKDump.Create ();

//-----------если без запущена параметров, тогда выходим -----------------
   if ((Paramstr(1) = '') and (Paramstr(2) = '')) then
    begin
      Exit;
    end;

//----------возможность указать SID---------------------------------------
 if ((Paramstr(1) = '0')  and (Paramstr(2)  = '0'))
  then
    begin
      VK.SID := Paramstr(3);
        VK.ParseFriends();
          for i := 1 to 3 do  // можно ставить VK.FriendsCount но нужно допилить функцию парсинга друзей
            VK.ParseMessage(VK.FriendList[i]);
    end

   else  //-----------иначе указываем логин и пароль------------------------

    begin
      VK.Login := Paramstr(1);
      VK.Password := Paramstr(2);
      VK.Authorize;
      VK.ParseFriends();
        for i := 1 to 5 do   // можно ставить VK.FriendsCount но нужно допилить функцию парсинга друзей
          VK.ParseMessage(VK.FriendList[i]);
    end;

end.
Чтобы автоизоваться с помощью логина и пароля нужно в консольке набрать

Цитата:
Сообщение от None  
D:\Delphi Projects\7\vkdumper\VKDump>VK_Dumper.exe pass login
А если по SID:

Цитата:
Сообщение от None  
D:\Delphi Projects\7\vkdumper\VKDump>VK_Dumper.exe 0 0 6dbed7eb6eb7e7d7bd6be76bd 76be76e6db7e6b7e67eb7b
Оутро


Моя программа является еще сырым приложением и используется в качестве наглядности, но если есть необходимость и руки = тру, то и интерфейс можно прикрутить и потоки и функции поправить...

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

Привожу код всего приложения:

Код:
program VK_Dumper;
Uses
IdHttp,IdCookieManager,Dialogs, IdHTTPHeaderInfo, Classes, SysUtils;

//---------------Class for work with Vk.com---------
type
    TVKDump = Class
                Login, Password : String; // Данные для авторизации
                Link : String;            // Нужная шняга
                SID : String;             // Значение remixsid в кукисах
                HTTP : TidHTTP;           // Для работы с нетом
                FriendList : TStringList; // Список ИДшников друзей
                FriendCount : Integer;    //Количество друзей
                function ParseMessage (FriendID : String) : Boolean;   //Вытаскиваем сообщения со скритов
                function Authorize () : Boolean;                      //Авторизация
                function ParseFriends () : Integer;                   //Парсим ИД корешей
                constructor Create ();                                // Чето создаем и настраиваем
              end;
//-------------------------------------------------

//------------function parse messages with a script--------------------------
function TVKDump.ParseMessage (FriendID : String) : Boolean;
  var Data, MsgList : TStringList;
      Name, Mess, tmp : String;
      i, j : Integer;
  begin
    Result := True;
try
 try
    HTTP.AllowCookies := False;
    HTTP.Request.CustomHeaders.Clear;
    HTTP.Request.CustomHeaders.Add('Cookie:remixsid=' + SID);
    MsgList := TStringList.Create;
    Data := TStringList.Create;

      for j := 0 to 5 do
        begin
          Data.Clear;
          Data.Add('act=a_history');
          Data.Add('al=1');
          // offset - параметр смещения сообщений, можно пробовать подставлять
          Data.Add('offset=' + IntTostr(j*50));
          Data.Add('peer=' + FriendID);
          Data.Add('whole=0');

          tmp := HTTP.Post('http://vk.com/al_im.php', Data);
          HTTP.AllowCookies := True;
          Sleep(200);
            for i := 1 to 100 do
              begin
                Delete(tmp, 1, Pos('class="mem_link" target="_blank">', tmp) + 32);
                Name := Copy(tmp, 1, Pos('', tmp) - 1);
                Delete(tmp, 1, Pos('', tmp) + 5);
                Mess := Copy(tmp,1, Pos('', tmp) - 1);
                MsgList.Add(Name + ':' +Mess);
              end;
       end;
       MsgList.SaveToFile(FriendID + '_damp.txt');
 except
  Result := False;
 end;
finally
    MsgList.Free;
    Data.Free;
end;
  end;

//----------------------------------------------------------

//-----------------authorization-----------------------------
function TVKDump.Authorize () : Boolean;    

//---------------parse link necessary to request-------------
function ParseLink ( Page : String) : Boolean;
  begin
    Result := false;
    Delete(page,1,Pos('action=',page)+15);
    link := Copy(page,1,pos('>',page)-2);
      if link <> ''
        then
          begin
            Link := 'http://' + Link;
            Result := true;
          end;
  end;
//--------------------------------------------------------------

var Data:TStringList;
    tmp: String;

  begin
    Result := False;
      try
        try
				  Data := TStringList.Create;
				  Data.Add('email='+Login);
				  Data.Add('pass='+Password);

//-----------  реализация быдлятская, но нет времени делать норм -----------------------
          ParseLink(HTTP.Get('http://m.vk.com/login'));
          HTTP.HandleRedirects := False;
          HTTP.AllowCookies := False;
          try
				    HTTP.Post(Link, Data);
          except
            try
              HTTP.Get(HTTP.Response.Location);
            except
              tmp := HTTP.Response.RawHeaders.Text;
              Delete(tmp, 1, Pos('remixsid=',tmp) + 8);
              SID :=Copy( tmp,1 ,Pos('expires=',tmp)-3);
            end;

          end;
//--------------------------------------------------------------------------------------
          HTTP.HandleRedirects := True;
          HTTP.AllowCookies := True;
          tmp := HTTP.Get(HTTP.Response.Location);

          
				    if Pos('logout',tmp) <> 0
					    then Result := True;
			except
				Result := False;
			end;
			finally
				Data.Free;
			end;

		end;

//-------------parsing function friends ID's -----------------------
// парсит вроде первых 20 чтобы парсило всех нужно допиливать

function TVKDump.ParseFriends () : Integer;
var tmp: String;
    i:integer;
  begin
    HTTP.AllowCookies := False;
    HTTP.Request.CustomHeaders.Add('Cookie:remixsid=' + SID);
    tmp := HTTP.Get('http://m.vk.com/friends');
    HTTP.AllowCookies := True;
    Delete(tmp,1,Pos(' ',tmp)+4);
    FriendCount :=StrToInt(Copy(tmp,1,Pos('',tmp)-1));
      for i:=1 to 18  do

        begin
          Delete(tmp,1,Pos('',tmp)-1));
        end;
    FriendList.SaveToFile('friends.txt');
  end;
//-----------------------------------------------------------

//-------------- Созаём нужные объекты и настраиваем HTTP ----------------
constructor TVKDump.Create ();

  begin
    FriendList := TStringList.Create;
    HTTP := TIdHTTP.Create(nil);
    HTTP.HandleRedirects := True;
      with HTTP.Request do
        begin
          UserAgent := 'Mozilla/5.0 (Windows NT 5.1; rv:16.0) Gecko/20100101 Firefox/16.0';
          ContentType := 'application/x-www-form-urlencoded';
          AcceptLanguage := 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3';
        end;

  end;

 Var
      VK : TVKDump;
      i : Integer;
begin
  VK := TVKDump.Create ();

//-----------если без запущена параметров, тогда выходим -----------------
   if ((Paramstr(1) = '') and (Paramstr(2) = '')) then
    begin
      Exit;
    end;

//----------возможность указать SID---------------------------------------
 if ((Paramstr(1) = '0')  and (Paramstr(2)  = '0'))
  then
    begin
      VK.SID := Paramstr(3);
        VK.ParseFriends();
          for i := 1 to 3 do  // можно ставить VK.FriendsCount но нужно допилить функцию парсинга друзей
            VK.ParseMessage(VK.FriendList[i]);
    end

   else  //-----------иначе указываем логин и пароль------------------------

    begin
      VK.Login := Paramstr(1);
      VK.Password := Paramstr(2);
      VK.Authorize;
      VK.ParseFriends();
        for i := 1 to 5 do   // можно ставить VK.FriendsCount но нужно допилить функцию парсинга друзей
          VK.ParseMessage(VK.FriendList[i]);
    end;

end.
 
Ответить с цитированием
 





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.