[DELPHI] Źródło Strony

0

Witam, mam z pozoru łatwy do rozwiązania problem - chodzi mianowicie o to że muszę pobrać sobie źródło strony (właściwie bez znaczenia czy w formie HTML czy tekstowej, choć obie były by przydatne).
Używałem najprostszej metody czyli WebBrowsera, jednak w tym wypadku to się nie sprawdza...

Mój mini programik ma za zadanie wczytać z listy pewną ilość linków do rapidshare, otworzyć je, odczytać ich źródło, przeanalizować to źródło, czy link jest poprawny (to znaczy czy użytkownik podał właściwy i czy zamieszczony plik ciągle znajduje się na serwerze). Nic specjalnego, ot taka mała rzecz. Problem jednak w tym że jeżeli plik został skasowany (bo łamał prawa autorskie, albo był zbyt stary) to WebBrowser wyrzuca komunikat o tym (starndardowy MessageBox od serwisu rapidshare). Niby nic, ale problem pojawia się wtedy gdy komunikat wyświetla się w pętli np. 100 razy...

Niestety WebBrowser nie ma (albo ja nie umiem go odszukać) zdarzenia które mozna by obsłużyć (np. OnGetStupidMessage ;P), więc chyba nie da się zablokować teych wiadomości.

W związku z tym zrezygnowałem z WebBrowsera i przerzuciłem się na idHttp z Indy. Nietstety to badziewie ma rozwaloną obługę błędów. Jeżeli wydam mu polecenie pobrania źródła z niewłaściwego linka (brak takowej strony - nie istnieje), albo nie będzie w tej chwiki połączenia z netem - to socet wywali błąd (dokładnie 11004). NIE DA się temu zapobieć, żadne try-except ani odczytywanie odpowiednich indexów błędu nie pomoże. Było to wałkowane już na tym forum i wniosek był jeden - Indy ssie, a ja potwierdzam.

Próbowałem takim małym, sytarym komponentem jak HttpGet - do prostego ściągania plików się nadaje, ale to też raczej słabizna (np. zupełnie dziwacznie reaguje na OnError, ma problemy z doczytywaniem źródeł - google, yahoo czy amazon go przerastają...).

Zwykły URLDownloadToFile z biblioteki URLMon nawet sobie radzi, tylko że to cholerstwo żadnych zdarzeń nie ma, więc nie wiem czy ściąganie już się skończyło, czy były problemy, czy jest połaczenie z netem itd...

Po tym wszystkim już nie wiem co robić, proszę uprzejmie o pomoc... Taka (niby) prosta pierdólka, a nie wiem jak ją rozpracować.

0

Popróbuj z Synapse, a to że zawiodłeś się na Indy wcale mnie nie dziwi. Już w ciągu ostatniej doby to trzeci temat gdzie
komyś polecam THttpSend z Synapse, więc zobacz moje inne posty i to co pisałem poprzednikom. I nie wiem czy może
wszystkie posty są dostępne. Całkiem możliwe, że ktoryś ,co zwykle bywa u nowych - poleciał do kosza za "temat" itp.
Synapse ma ok obsługę błędów, ma też możliwość obsługi niektórych zdarzeń. A i kod strony powinieneś uzyskać raczej
bez problemów. Z tego co się orientuje kiedyś autor USDownloadera też korzystał z Synapse, nieco chyba zmienionego.
Dodam tylko, że poniższy kod zwrocil mi źródlo strony z takim tekstem komunikatu wywolywanego przez JavaScript, że
pozwala to rozpoznać kiedy link został usunięty z powodu naruszenia praw autorskich. Ja sprawdzałem akurat coś co mi
przyszło na myśl czyli dostępną już na sieci wersję R5 filmu "Salt" w Divixie, bo wiadomo że dystrybutor walczy i linki, z
jednego popularnego portalu, "padają" po dłuższym lub krotszym czasie od pojawienia się ich w danym wątku. Poza tym
używanie WebBrowsera do pobrania kodu html strony bez jego wyświetlania to jak polowanie na michy z armatą. Dlatego
polecam Tobie Synapse. Musisz tylko zobaczyć - jaki kod html jest zapisywany przy innych plikach (i również wygasłych).
Później taki kod bez problemu załadujesz do TStringList albo nawet do zmiennej typu string i możesz sparsować wyniki.

var
  AUrl : string;
  SynHttp : THttpSend;
begin
  AUrl := 'http://rapidshare.com/files/film_salt_i_tak_dalej_partXX.rar';
  SynHttp := THttpSend.Create;
  SynHttp.HTTPMethod('GET', AUrl);
  SynHttp.Document.SaveToFile('D:\test.htm');
  SynHttp.Free;
end;
0

Crow bzdura! normalnie zwraca 404 jak się umie z niego korzystać pokaż kod to Ci powiem co robisz źle. Za pomocą WebBrowser też się da tylko trzeba umieć a nie chcieć ale faktycznie niepotrzebnie ale WebBrowser jest niezastąpiony tam gdzie trzeba JavaScript (szkoda że projrkt jego odpowiednika opartego na FF padł).

0

kAzek, zobacz sobie : http://www.progdigy.com/?p=116

0

Dzięki olesio, synapse to na pewno dobry trop. Prosił bym jednak abyś w swej dobroci (:D), napisał mi jak obsłużyć zdarzenia. Bo nic mi po śćiągnięciu kodu strony, jeżeli nie jestem w stanie sprawdzić czy już i czy w ogóle to nastąpiło...

A o resztę się nie martw, jak dostanę kod strony to już z resztą sobie poradzę - pisałem kiedyś betę tego programiku, więc wszystko mam względnie sprawdzone.

kAzek

"Crow bzdura! normalnie zwraca 404 jak się umie z niego korzystać"

Ale o co chodzi? O Indy? Jeżeli tak, to zobacz to:
http://4programmers.net/Forum/241446

Indy po prostu nie działa poprawnie...

"Za pomocą WebBrowser też się da tylko trzeba umieć a nie chcieć"

Mozna co? Odczytać kod strony? Ja wiem że można, ale mi chodzi o to by ZLIKWIDOWAĆ ten komunikat który wyskakuje z WebBrowsera...

0

Crow: a zajrzaleś chociaż do dokumentacji Synapse albo do innych moich postów jak radzilem?
Jak tak się bedziesz bronił przed samodzielnym pozyskaniem wiedzy, to nie wróżę sukcesów ;/
A THttpSend ma takie coś jak ResultCode. W przypadku rapidshare, nawet jak link już padł, to
i tak zwróci kod 200, a po wywołaniu HttpMethod, to co uzyska komponent masz w Document
zawsze, bo zdarzenia jakie oferuje THttpSend, słuzyć moga raczej tylko do pokazania postępu.

0

Szczerze powiedziawszy chciałem to po prostu szybko załatwić, bez specjalnego zagłębiania się w meandra synapsa (dlatego że już od 2 miesięcy piszę duży projekt, jeszcze mnóstwo pracy przede mną, a chodzi mi właściwie o małą pierdółkę - dlatego koniecznie chciałem jakieś konkrety ;D). Poczytalem sobie dokumentację synapsa, ale nigdy bym nie wpadł na coś takiego jak ResultCode (cały ten help jest dziwancznie napisany - po kilka procedur żadnych przykładów. Wiem, są dema ale też jakieś dziwne, w tym HttpSend w ogóle nie wiem co to demo robi ;]).

Teraz już wiem jak z tego używać, ale mam jeszcze jedno zapytanie - skąd można pobrać katalog błędów i odczytać co znaczą?

Wiem że gdy się uda to zwraca 200, gdy nie ma neta albo link jest nieprawidłowy to 500, ale próba pobrania np. google.com zwraca mi 302 (dlaczego nie 200?). Nie wiem dlaczego tak jest i przede wszystkim nie wiem co to oznacza.

Dzięki za wszystko i pozdrawiam, liczę jeszcze na tą jedną odpowiedź ;)

0
100 : status:=' Continue';
101 : status:=' Switching Protocols ';
200 : status:=' OK ';
201 : status:=' Created ';
202 : status:=' Accepted ';
203 : status:=' Non: status:='Authoritative Information ';
204 : status:=' No Content ';
205 : status:=' Reset Content'; 
206 : status:=' Partial Content'; 
300 : status:=' Multiple Choices ';
301 : status:=' Moved Permanently ';
302 : status:=' Found ';
303 : status:=' See Other ';
304 : status:=' Not Modified'; 
305 : status:=' Use Proxy ';
306 : status:=' No Longer Used ';
307 : status:=' Temporary Redirect ';
400 : status:=' Bad Request ';
401 : status:=' Not Authorised'; 
402 : status:=' Payment Required'; 
403 : status:=' Forbidden ';
404 : status:=' Not Found ';
405 : status:=' Method Not Allowed ';
406 : status:=' Not Acceptable ';
407 : status:=' Proxy Authentication Required ';
408 : status:=' Request Timeout ';
409 : status:=' Conflict  the state of the resource. ';
410 : status:=' Gone ';
411 : status:=' Length Required ';
412 : status:=' Precondition Failed ';
413 : status:=' Request Entity Too Large ';
414 : status:=' Request URI Too Long ';
415 : status:=' Unsupported Media Type ';
416 : status:=' Requested Range Not Satisfiable ';
417 : status:=' Expectation Failed ';
500 : status:=' Internal Server Error'; 
501 : status:=' Not Implemented ';
502 : status:=' Bad Gateway ';
503 : status:=' Service Unavailable ';
504 : status:=' Gateway Timeout ';
505 : status:=' HTTP Version Not Supported';
0

Dzięki wszystkim, napisałem działa szybko i bezproblemowo (przynajmniej na razie ;P)

PS. Faktycznie Synapse jest bardzo dobry, Indy może robi lepsze wrażenie (ma tyle specjalistycznych kontrolek), ale niestety wykłada się przy najprostszych kwestiach :/

Jakby coś jeszcze szwankowało to na pewno dam o sobie znać.

Pozdro.

0

Crow co to za odwołanie do tematu z 2005 roku!? Gwarantuję że to da się zrobić w indy bądź jezeli wymagane jest użycie JavaScript w WebBrowser. Pokaż kod co tam na modziłeś to napiszę co jest źle.

0

Dzięki już nie trzeba, napisałem w Synapsie i wszystko działa poprawnie ;]

Jest jednak coś w czym przydała by mi się pomoc. Kod programu i kilka wyjaśnień:

WIPWindow to specjalne okienko które nadzoruje dodawanie plików do listy, coś jak okno w Winrarze które odpala się gdy coś pakujemy lub rozpakowujemy.

Box to ListBox, wiem że gółbym zrobić sobie w locie jakiegoś StringLista ale tak mi wygodniej ;)

FoundErrorsWindow to okienko które wyłapuje wszystkie uszkodzone linki, a po zakończeniu dodawania wyświetla się.

LinkList to memo do którego użytkownik wrzuca linki (w formie listy).

Main list to ListView z linkami, które dostały doń dodane, jeżeli są poprawne.

{Check is ON} //została wybrana opcja by sprawdziło linki przed dodaniem do listy.
    begin

    {Preparation}
    WIPWindow.Checked.Caption:='0';
    WIPWindow.Proper.Caption:='0';
    WIPWindow.Broken.Caption:='0';
    FoundErrorsWindow.ErrorList.Clear;

    for I:=0 to LinkList.Lines.Count-1 do
      begin

      {Preparation}
      Box.Clear;
      Code:=0;
      WIPWindow.CheckBar.MaxValue:=LinkList.Lines.Count-1;

      {Canceled}
      if BRK=True then
        begin
        MainWindow.MainList.Clear;
        FoundErrorsWindow.ErrorList.Clear;
        Break;
        end;

//poniższy kod sprawdza czy wrzucony przez użytkownika link spełnia wymagania. Jeżeli tak to stara się "wymuskać" własciwy link. Dlaczego tak? Bo np. przed linkiem może znajdować się spacja, albo jakieś niepotrzebne rzeczy, wtedy zostaną obcięte
      if Pos('http://rapidshare.com', LinkList.Lines.Strings[I])>0 then
        begin
        P:=Pos('http://rapidshare.com', LinkList.Lines.Strings[I]);
        Link:=Copy(LinkList.Lines.Strings[I],P,Length(LinkList.Lines.Strings[I]));
        Checker:=THttpSend.Create;
        Checker.HTTPMethod('GET', Link);
        Checker.Document.SaveToFile(Dir+'\Data\Link.htm');
        Code:=Checker.ResultCode;
        Checker.Free;

//ta część odczytuje kod operacji i sprawdza co właśnie zaszło, w tym przypadku źródło zostało odczytane poprawnie.
          {Link Readed}
          if Code=200 then
            begin
            Box.Items.LoadFromFile(Dir+'\Data\Link.htm');

//a to mój prosty sposób na sprawdzenie czy plik został usuniety. Dobry plik zawiera w 134 linijce podany rozmiar w kilobajtach. Zły link, nawet nie ma tylu linijek... Przy okazji pobiram sobie rozmiar pliku.
            {File has been found}
            if Box.Items.Count>134 then
              begin
              Line:=Box.Items.Strings[134];
              Box.Clear;
              ExtractStrings(['|'],[],Pchar(Line),Box.Items);
              Line:=Box.Items.Strings[1];
              Box.Clear;
              ExtractStrings(['<'],[],Pchar(Line),Box.Items);
              Line:=Copy(Box.Items.Strings[0],2,Length(Box.Items.Strings[0])-4);
              Box.Clear;
              FSize:=StrToInt(Line);
              if FSize>=1048576 then FSize:=FSize div 1048576 else FSize:=FSize div 1024;
              ExtractStrings(['/'],[],Pchar(Link),Box.Items);
              FName:=Box.Items.Strings[Box.Items.Count-1];
              Ext:=ExtractFileExt(FName);

{to bardziej skomplikowane, każdy plik w ListView ma swoją ikonę odpowiadającą jego rozszerzeniu. Ikony są dodawane do ImageList w locie, więc zapisuję rozszerzenia które już mam, dzięki temu nie będe miał po kilka razy tych samych ikon).
              {Check extension list}
              if Pos(Ext,MainWindow.ExtList.Text)>0 then
                begin
                for N:=0 to MainWindow.ExtList.Lines.Count-1 do
                if MainWindow.ExtList.Lines.Strings[N]=Ext then IconIndex:=N;
                end else
                  begin
                  FIcon:=TIcon.Create;
                  BMP:=TBitmap.Create;
                  BMP.Width:=16;
                  BMP.Height:=16;
                  MainWindow.ExtList.Lines.Add(Ext);
                  IconIndex:=MainWindow.ExtList.Lines.Count-1;
                  Box.Items.SaveToFile(Dir+'Data\Icon'+Ext);
                    try
                    GetIconFromFile(Dir+'Data\Icon'+Ext,FIcon,SHIL_SYSSMALL);
                    BMP.Canvas.Draw(0,0,FIcon);
                    MainWindow.FileIcon.Add(BMP,nil);
                    finally
                    DeleteFile(Dir+'Data\Icon'+Ext);
                    FIcon.Free;
                    BMP.Free;
                    end;
                  end;

              {Add to list}
              Delete(FName,Length(FName)-Length(Ext)+1,Length(Ext));

              LI:=MainWindow.MainList.Items.Add;
              LI.Caption:=FName;
              LI.SubItems.Add(FloatToStrF(FSize, ffNumber, 32, 2)+' MB');
              LI.SubItems.Add('');

              {Gauge}
              Gauge:=TsGauge.Create(nil);
              Gauge.Parent:=MainWindow.MainList;
              LI.Data:=Gauge;
              Gauge.Left:=491;
              Gauge.Height:=14;
              Gauge.Top:=LI.Top+1;
              Gauge.Width:=52;
              Gauge.SkinData.SkinManager:=MainWindow.sSkinManager7;
              Gauge.Progress:=0;
              Gauge.Show;

              LI.SubItems.Add(' ');
              LI.SubItems.Add(' ');
              LI.SubItems.Add('In queue');
              LI.SubItems.Add(Copy(Ext,2,Length(Ext)));
              LI.SubItems.Add(IntToStr(0));
              LI.SubItems.Add(IntToStr(IconIndex));
              LI.SubItems.Add('YES');
              LI.SubItems.Add(Link);

              LI.StateIndex:=0;
              LI.ImageIndex:=IconIndex;

              {Progress} //ustawia parametry w WIPWidnow żeby użytkownik widział co sie dzieje.
              Application.ProcessMessages;
              WIPWindow.Checked.Caption:=IntToStr(I)+'/'+IntToStr(A);
              WIPWindow.Proper.Caption:=IntToStr(MainWindow.MainList.Items.Count-1);
              WIPWindow.CheckBar.Progress:=I;
              end else

                {File removed} //Źródło ma mniej niż 134 linijki, czyli adres jest poprawny, ale plik został skasowany.
                begin
                ELI:=FoundErrorsWindow.ErrorList.Items.Add;
                ELI.Caption:=Link;
                ELI.StateIndex:=4;

                {Progress}
                Application.ProcessMessages;
                WIPWindow.Broken.Caption:=IntToStr(FoundErrorsWindow.ErrorList.Items.Count);
                WIPWindow.CheckBar.Progress:=I;
                end;
            end;

            {Connection or link error} //500 oznacza że albo link jest zepsuty, albo nie ma połączenia z netem - trzeba to zbadać. W tym celu powtarzam operację, ale dla jakiegoś "niezniszczalnego" serwisu. Ja wybrałem www.yahoo.com
          if Code=500 then
            begin
            ErrorCode:=0;
            Checker:=THttpSend.Create;
            Checker.HTTPMethod('GET', 'http://www.yahoo.com/');
            ErrorCode:=Checker.ResultCode;
            Checker.Free;

              {No connection} //Yahoo zwraca 500, nie ma neta
              if ErrorCode=500 then
                begin
                ShowMessage('Chyba nie masz neta');
                FoundErrorsWindow.ErrorList.Clear;
                MainWindow.MainList.Clear;
                Break;
                end;

              {Link is broken} //Yahoo zrwca 200, link był zły
              if ErrorCode=200 then
                begin
                ELI:=FoundErrorsWindow.ErrorList.Items.Add;
                ELI.Caption:=Link;
                ELI.StateIndex:=4;

                {Progress}
                Application.ProcessMessages;
                WIPWindow.Broken.Caption:=IntToStr(FoundErrorsWindow.ErrorList.Items.Count);
                WIPWindow.CheckBar.Progress:=I;
                end;
            end;
        end;
        if FileExists(Dir+'\Data\Link.htm') then DeleteFile(Dir+'\Data\Link.htm');
        Application.ProcessMessages;
        WIPWindow.Checked.Caption:=IntToStr(I)+'/'+IntToStr(A);
      end;
    end;

Kod działa, ale problem jest taki że program czasem się zawiesza - nie wiem dlaczego. Wrzucam do sprawdzenia 100 linków to działa OK. Wrzucam 300 to przy 5 linku program przestaje odpowiadać... Jakieś pomysły?

0

Spróbuj to zrobić w wątku, bo Application.ProcessMessages niewiele pomoże.

0

Po co uzywac dodatkowych komponentow skoro delphi posiada w sobie webrowsera z ktorego bez problemu mozna wyciagac kod strony i dalej robic z nim co sie podoba

przegladarka = webrowser )

Edit1.Text:=przegladarka.LocationURL;
memo1.Clear;
if Assigned(przegladarka.Document) then
begin
iall := (przegladarka.Document AS IHTMLDocument2).body;
while iall.parentElement <> nil do
begin
iall := iall.parentElement;
end;
Memo1.Text := iall.outerHTML;//pobierz zawartosc przegladarki

na iall. mozliwosci wiecej i po kija komponenty dodatkowe skoro to dziala

1 użytkowników online, w tym zalogowanych: 0, gości: 1