Попытка написать парсер =)

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by ImLucky, 26 Aug 2011.

  1. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Всем привет. Понадобилось с одного форума спарсить ники с мемберлиста.

    В браузере можно авторизироваться через сайт, и попасть на форум уже залогиненым.

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

    Прошу подсказать как можно исправить ситуацию. А то вручную копипастить 265к логинов как-то обломно )

    Code:
    procedure TForm1.btn1Click(Sender: TObject);
    var
    Http  : TidHttp;
    CM    : TidCookieManager;
    Data  : TStringList;  StrPage, UserID,  UserName  :  String;
    i : integer;
    s: string;
    
    begin
    try
    Http := TIdHTTP.Create(Self);
    Data := TStringList.Create;
    CM := TidCookieManager.Create(Http);
    Http.AllowCookies := true;
    Http.CookieManager := CM;
    Http.HandleRedirects := true;
    Http.Request.Host:='www.gamescampus.com';
    Http.Request.UserAgent:='Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; MRSPUTNIK 2, 4, 0, 270; MRA 5.8 (build 4133); SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)';
    Http.Request.Accept:='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
    Http.Request.AcceptLanguage:='ru-RU';
    Http.Request.AcceptCharSet:='windows-1251,utf-8;q=0.7,*;q=0.7';
    Http.Request.Referer:='http://scarletlegacy.gamescampus.com/';
    Data.Add('uid=deleted');
    Data.Add('pwd=deleted');
    Data.Add('x=37');
    Data.Add('y=17');
    StrPage := Http.Post('http://www.gamescampus.com/account/login_exec.asp?rtnurl=http://scarletlegacy.gamescampus.com/', Data);
    s:= idhtp1.get ('http://forum.gamescampus.com/memberlist.php') ;
    mmo2.Lines.Text:= s
    
    finally
    Data.Free;
    CM.Free;
    Http.Free;
    end;
    
    if Pos('Hello, <a href="http://www.gamescampus.com/account/modify_view.asp?gamescampus=scarletlegacy" target="_top">'+Edt1.Text,StrPage) <> 0
    then
    ShowMessage('Зашли')
    else
    ShowMessage('Это fail =(');
    Mmo1.Lines.Text := StrPage;
    end;
    
    

    Можно конечно напрямую через форум логиниться, но у меня там не получается авторизация из-за сесии (sid). Просто в браузере проблем не возникает при переходе с сайта на форум, а в проге возникает...почему ?
     
    #1 ImLucky, 26 Aug 2011
    Last edited: 26 Aug 2011
  2. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    s:= idhtp1.get ('http://forum.gamescampus.com/memberlist.php') ;

    Ты выполняешь эту строчку, а потом определяешь(как я понял) удачность авторизации.
    Если не разберешься, завтра утром помогу.

    EDIT: у тебя могут быть траблы с CookieManager'ом, если это Delphi 7.
     
    #2 Jingo Bo, 26 Aug 2011
    Last edited: 26 Aug 2011
  3. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Я уже по всякому пробовал, и на другой батон вешал, и после проверки делал, и так и сяк.. уже всё перепробовал. Разобраться так и не смог.

    Делфи да, семерка.

    На семерке я раньше уже писал подобные вещи, всё было без проблем. Правда это было давно, и сборка была другая.
     
    #3 ImLucky, 26 Aug 2011
    Last edited: 26 Aug 2011
  4. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    indy Обнови indy.fulgan.com/zip
     
  5. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Есть какие-то мануалы по апдейту инди ? А то почти все ссылки мертвые, многие ссылались на квенди, но сайт мертвый.

    upd.

    Вроде нашел.
     
    #5 ImLucky, 26 Aug 2011
    Last edited: 26 Aug 2011
  6. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Актуальная версия Indy находится только в SVN репозитории разработчиков, значит нам понадобится клиент SVN под Windows.
    Наиболее популярным клиентом является tortoisesvn, который можно скачать на сайте разработчика. Затем устанавливаем его. Для простоты можем в настройках (после установки) указать язык интерфейса русский.
    Перегружаемся.
    Теперь выберем место, где у нас будет располагаться папка с нашими актуальными компонентами, щелкаем правой клавишей мыши на свободном месте в проводнике и выбираем пункт TortoiseSVN->Экспорт…
    В появившемся окне в поле URL Хранилища впишите адрес репозитория Indy «https://svn.atozed.com:444/svn/Indy10/» в поле «Папка экспорта» выберите папку куда экспортировать компоненты. Затем нажмите ОК, у вас спросят логин с паролем в поле имя пользователя впишите «Indy-Public-RO», пароль указывать не нужно.
    Теперь дождитесь окончания операции.
    Запустите Delphi , выберите в меню «Component»->»Install Packages». В появившемся списке снимите галки с всех пакетов Indy. И затем удалите все пакеты Indy в этом же списке, воспользовавшись кнопкой remove. Затем откройте окно настроек среды: меню «tools->options->Library Win32″ и удалите из строки Library path пути к исходным кодам Indy. Затем добавьте в Library path 3 пути:
    1. «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\System«
    2. «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\Core«
    3. «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\Protocols«

    Закройте Delphi. Далее найдите в папке, где у вас установлена Delphi исходные коды Indy. Обычно они располагаются в папке «<папка с Delphi>/sources/Indy» и удалите эту папку. Далее в папке Lib, которая располагается по адресу «<папка установки Delphi>/lib» удалите все файлы Indy (поиск по вхождению «Indy» вам в этом поможет).Теперь запустите Delphi, и откройте пакет «IndySystemX0.dpk» (где X – это ваша версия Delphi), который располагается по следующему адресу: «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\System» и скомпилируйте его. Далее откройте пакет «IndyCoreX0.dpk» (где X- это ваша версия Delphi) из папки «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\Core» и скомпилируйте его. Теперь откройте и скомпилируйте пакет «IndyProtocolsX0.dpk» (где X – это ваша версия Delphi) , который располагается в папке «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\Protocols«.Далее откройте пакет «dclIndyCoreX0.dpk», который располагается в папке «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\Core» и установите его, также установите пакет «dclIndyProtocolsX0.dpk» из папки «<папка, куда вы экспортировали репозиторий Indy>\branches\Tiburon\Lib\Protocols». Вот и все, поздравляю, теперь у вас установлена актуальная версия Indy.
     
  7. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Мануал видимо устаревший, ибо нужных папок или ещё чего-то нету, или находятся в другом месте. Так и не смог обновиться. Скачал сборку делфи уже с 10-ым инди, установил и переустановил раз 20, при попытке юзать в ней инди и закомпилить проект, ругает на разные версии indy.

    Хотя все старые компоненты я чистил согласно инструкция.. беда какая-то.

    Впорос такой, а точно дело в инди ? Может я зря уже 4-ый час мучаюсь ? Может всё таки в коде что-то ?
     
  8. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    из этого мануала слово Branches\Tributron выкинуть из путей нужно и все ок.
    внимательно поищи и удали в папке windows\system файлы по маске *indy*.* их старичок закидывает туда.
     
  9. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Я всё это проделывал уже. Я полносью удалял делфи, и все файлы с разрешением dcp, dcu и ещё каким-то разрешением. То есть полностью чистил комп от всего что может бытьс вязано с делфи. Ставил сборку с 10 инди, и в итоге он ругался на версии.

    System32 тоже чистил... итог один. Пойду уже хз в какой раз заного пробовать.

    Блин бесит уже -_-

    [Fatal Error] Unit1.pas(8): Unit IdHTTP was compiled with a different version of IdException.EIdException
    [Fatal Error] Unit1.pas(7): Unit IdCookieManager was compiled with a different version of IdBaseComponent.TIdBaseComponent


    Как пофиксить ? Удалял уже всё что только можно было удалить, развее что реестр не чистил.

    Может всё же пропустил что-то ?

    Чистил system32 , сносил целиком делфи со всеми папками, что ещё можно сделать ?

    Ыыы, ребут компа не поможет ?) А то был как-то случай..
     
    #9 ImLucky, 26 Aug 2011
    Last edited: 26 Aug 2011
  10. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    не знаю, никогда такой ошибки не видел...
    а ты запускал файлик fullD7.bat?
    удалил старую папку D7?
    пути все указаны?
     
  11. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Если я установлю делфи без инди, и потом буду по мануалу устанавливать, нормально всё встанет, или чего-то не хватать будет ?
     
  12. Apathy

    Apathy New Member

    Joined:
    25 Aug 2011
    Messages:
    41
    Likes Received:
    0
    Reputations:
    0
    попробуй по мануалу отсюда http://avtuh.ru/
     
  13. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Фуууухх с 10 утра обновлял этот инди... Раньше бы этот гайдик... Спасибо

    И то только с 3 попытки всё встало ровно.

    Но собственно с обновлением Indy проблема описанная в первом посте так и не решилась. Есть у кого какие соображения ?

    Логинится на сайт нормально, но при переходе на форум логин теряется.
     
  14. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Вот код, авторизация работает. Но, из за глючности TIdCookieManager со старого Indy(Лень щас обновлять) не получается зайти именно на форум, с новой версии в теории должно работать, даже если где то косяки(ведь сам парсинг не отладил) - думаю не сложно исправить.
    Code:
    Var Users : Record
          Names : array of String;
          Count : Cardinal;
        end;
    type
      TStringArray = array of String;
    function Parse(Login, Pass : String) : Boolean;
    Const
        ForumUrl = 'http://forum.gamescampus.com/forum.php';
        RealignCount = 1000;
      function PosEx(Const Start : Cardinal; Const V : String; Const Text : PString) : Cardinal;
      Var i : Cardinal;
          j : Integer;
      Begin
          j := 1;
          for i := Start to Length(Text^) do
            if V[j] = Text^[i] then
            Begin
                if j >= Length(V) then
                Begin
                    Result := i - j + 1;
                    Exit;
                end;
                Inc(j);
            end else
            Begin
                j := 1;
                if V[j] = Text^[i] then
                  Inc(j);
            end;
          Result := 0;
      end;
      function ParseString(Const Start : Cardinal; Const S, E : String; Const Text : PString) : String;
      Var i, j : Cardinal;
      Begin
          Result := '';
          i := PosEx(Start, S, Text);
          if i = 0 then
            Exit;
          j := PosEx(i + Length(S), E, Text);
          if j = 0 then
            Exit;
          Result := Copy(Text^, i+Length(S), j - Length(S) + 1);
      end;
      procedure MultiParseString(Const S, E : String; Const Text : PString; Var sa : TStringArray);
      Var i, j : Cardinal;
      Begin
          i := 1;
          SetLength(sa, 0);
          while i <= Length(Text^) do
          Begin
              i := PosEx(i, S, Text);
              if i = 0 then
                Exit;
              j := PosEx(i + Length(S), E, Text);
              if j = 0 then
                Exit;
              SetLength(sa, High(sa)+2);
              sa[High(sa)] := Copy(Text^, i+Length(S), j - (Length(S) + 1));
              i := j + Length(E);
          end;
      end;
      procedure SafeAddMember(Value : String);
      Begin
          if Users.Count > High(Users.Names) then
            SetLength(Users.Names, Users.Count + RealignCount);
          Users.Names[Users.Count] := Value;
          Inc(Users.Count);
      end;
    Var i, Page : Integer;
        done : Boolean;
        sa : TStringArray;
        http : TIdHTTP;
        post : TStringList;
        html, forumHash : String;
        Cookies : TIdCookieManager;
    Begin
        Randomize;
        Result := false;
        post := TStringList.Create;
        http := TIdHTTP.Create(nil);
        Cookies := TIdCookieManager.Create(http);
        http.CookieManager := Cookies;
        try
          {Set Headers}
          with http.Request do
          Begin
              UserAgent := 'Mozilla/5.0 (Windows NT 5.1; rv:6.0) Gecko/20100101 Firefox/6.0';
              Accept := '*/*';
              AcceptLanguage := 'ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3';
              AcceptCharset := 'windows-1251,utf-8;q=0.7,*;q=0.7';
              Connection := 'close';
              Referer := '';
          end;
          {Auth request}
          with post do
          Begin
              Clear;
              Add('rtnurl=' + ForumUrl);
              Add('saveid=Y');
              Add('uid=' + Login); Add('pwd=' + Pass);
              Add('Sign+In.x=' + IntToStr(Random(84)));
              Add('Sign+In.y=' + IntToStr(Random(27)));
          end;
          try
            http.Post('http://www.gamescampus.com/account/meta/user_signin.asp', Post);
          except
            on e1 : EIdProtocolReplyError do
              Result := (http.Response.ResponseCode = 302) and (http.Response.Location = ForumUrl);
            on e2 : Exception do
              Exit;
          end;
          if not Result then {Åñëè íå àâòîðèçîâàëèñü}
            Exit;
          {Get forum page }
          html := '';
          try
            html := http.Get(ForumUrl);
          except
            Exit;
          end;
          forumHash := '';
          with Cookies.CookieCollection do
           for i := 0 to Count - 1 do
             if Items[i].CookieName = 'phpbb3_ddsge_sid' then
             Begin
                 forumHash := Items[i].Value;
                 Break;
             end;
          if Length(forumHash) = 0 then
            Exit;
          {Parse memberlist page}
            {Pre init}
          Page := 0;
          Users.Count := 0;
          SetLength(Users.Names, 0);
          repeat
            try
              html := http.Get('http://forum.gamescampus.com/memberlist.php?sid=' + forumHash + '&start=' + IntToStr(Page));
            except end;
            MultiParseString('<td class="genmed row" align="left"><a href="', '</td>', @html, sa);
            done := true;
            for i := 0 to High(sa) do
            Begin
                html := ParseString(1, '">', '</a>', @sa[i]);
                if Length(html) <> 0 then
                Begin
                    SafeAddMember(html);
                    done := false;
                end;
            end;
            Inc(Page, 50);
          until done;
        finally
          http.Free;
          post.Free;
        end;
        SetLength(Users.Names, Users.Count);
        Result := true;
    end;
    Если все верно - вернет true и в массиве Users.Names будут все логины, иначе - какая то ошибка.
     
  15. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Jingo Bo Большое спасибо за труды, но у меня чего-то не получается весь этот шедевр прикрутить к себе, если не сложно, можешь исходник скинуть с компилящимся проектом ? Буду оч признателен.

    А то код на данном этапе для меня слишком сложен ))

    Code:
    Build
      [Warning] Unit1.pas(75): Variable 'Http' might not have been initialized
      [Warning] Unit1.pas(73): Variable 'Data' might not have been initialized
      [Warning] Unit1.pas(74): Variable 'CM' might not have been initialized
      [Hint] Unit1.pas(47): Variable 'UserID' is declared but never used in 'TForm1.btn1Click'
      [Hint] Unit1.pas(47): Variable 'UserName' is declared but never used in 'TForm1.btn1Click'
      [Hint] Unit1.pas(48): Variable 'i' is declared but never used in 'TForm1.btn1Click'
      [Warning] Unit1.pas(112): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(131): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(134): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(134): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(141): Comparing signed and unsigned types - widened both operands
      [Warning] Unit1.pas(146): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(150): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(150): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(151): Combining signed and unsigned types - widened both operands
      [Warning] Unit1.pas(156): Comparing signed and unsigned types - widened both operands
      [Error] Unit1.pas(199): Undeclared identifier: 'EIdProtocolReplyError'
      [Error] Unit1.pas(216): Undeclared identifier: 'CookieName'
      [Error] Unit1.pas(218): Undeclared identifier: 'Value'
      [Warning] Unit1.pas(232): Unsafe code '@ operator'
      [Warning] Unit1.pas(236): Unsafe code '@ operator'
      [Error] Unit1.pas(255): ';' expected but '.' found
      [Error] Unit1.pas(257): Declaration expected but end of file found
      [Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'
    
     
  16. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Седня пробовал в Delphi XE, так там другой баг с CookieManager'ом, видимо без правки модулей не выйдет, или же самому писать менеджер куков.
     
  17. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    В общем я пришел к выводу что лучше уже тогда сразу на форуме попытаться залогиниться. Будет несколько сложнее, ну зато может тогда всё заработает.

    З.Ы.

    Проектик в виде исходника всё равно бы с удовольсвтием посмотрел бы, тот что ты выше выклаывал )
     
  18. Kandi

    Kandi Member

    Joined:
    18 Nov 2009
    Messages:
    344
    Likes Received:
    17
    Reputations:
    0
    Первый совет: Установи себе RAD 2010 ++
    Второй совет: Выкинь CookieManager из проекта
    Третий совет: HTTP.Request.RawHeaders.Text \ HTTP.Response.RawHeaders.Text из response вытаскивай Set-Cookie: ....... и HTTP.Request.RawHeaders.AddString('Cookie: ' + вытащенные кукис из response);
    При этом всём если у тебя HTTP.AlloweCookie := True; То ставь её в False и все куки даваемые тебе сайтом забирай и вставляй так как я показал...Удачи :)
    P.S. Если, что-то пойдет не так, то организуй все заголовки HTTP.Request в точности как в твоём браузере!
     
    1 person likes this.
  19. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Вот архив с полным проектом, парсит, тут используется свой простой парсер куков. Проще было бы Indy поправить, но ставить ее обновленную сложно, так что такие извороты, менеджер куков не учитывает path'ы, но для данной задачи работает.

    http://zalil.ru/31616868
     
  20. ImLucky

    ImLucky New Member

    Joined:
    26 Sep 2010
    Messages:
    72
    Likes Received:
    3
    Reputations:
    0
    Блин, большое спасибо тебе за труды, даже зарегился на том сайте ))

    Сейчас буду пытаться разобраться с твоим кодом. А то проект скомпилировал, нажал заветную кнопочку, и уже 10 минут жду пока прога отвиснет. Я так понимаю в данный момент она в мемо грузит все ники. Надо бы какое-то ограничение ей сделать и по кускам выдергивать )))

    UPD.

    Не, вроде поправил для теста чтобы с 5280 страницы начинал (всего 5283) , жму загрузить и всё равно виснит на оч. долго так ничего и не собрав....

    Че то ну ни как мне не везет с этим парсером :D

    Буду разбираться что не так.

    Кстати, первый раз че то не придал значения этому -

    При открытии проекта вылетает еррор

    Может в этом дело ? оО Точнее даже не может, а видимо в этом и есть дело )
     
    #20 ImLucky, 28 Aug 2011
    Last edited: 28 Aug 2011