Funkcja pobierająca stronę www

02 lutego 2008

Właśnie coś sobie tworzę i zaszła potrzeba pobierania i obrabiania treści z pewnej strony www (nie chodzi o fotka.pl :P ). Problem w tym, że serwer na którym ta strona stoi jest bardzo kapryśny :/ Często bez powodu wywala błędy 4xx a jeszcze częściej 5xx. Niby obsługuje kompresję gzip ale zdarza się, że zwróci stronę nieskompresowaną :/

Potrzebowałem funkcji, która poradzi sobie z tym wszystkim. Oto ona:

PHP:
  1. <?php
  2. function otworz_adres($adres, $post=false, $blad=3)
  3. {
  4. $header[]='Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5';
  5. $header[]='Accept-Language: pl,en-us;q=0.7,en;q=0.3';
  6. $header[]='Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7';
  7. $header[]='Keep-Alive: 300';
  8. $header[]='Connection: keep-alive';
  9.  
  10. $ch=curl_init();
  11. curl_setopt($ch, CURLOPT_URL, $adres);
  12. curl_setopt($ch, CURLOPT_HEADER, 0);
  13. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  14. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  15. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  16. curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
  17. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.0; pl; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11');
  18. curl_setopt($ch, CURLOPT_TIMEOUT, 60);
  19. curl_setopt($ch, CURLOPT_AUTOREFERER, true);
  20. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  21. curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
  22. curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
  23. if($post!==false)
  24. {
  25. curl_setopt($ch, CURLOPT_POST, true);
  26. curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
  27. }
  28. $zwroc=curl_exec($ch);
  29.  
  30. if($blad>0)
  31. {
  32. $naglowek=substr(curl_getinfo($ch, CURLINFO_HTTP_CODE), 0, 1);
  33. if($zwroc=='' OR curl_error($ch)!='' OR $naglowek=='4' OR $naglowek=='5')
  34. {
  35. curl_close($ch);
  36. sleep(1);
  37. return otworz_adres($adres, $post, --$blad);
  38. }
  39. }
  40. else
  41. return false;
  42.  
  43. curl_close($ch);
  44. return gzdecode($zwroc);
  45. }
  46.  
  47. function gzdecode($tresc)
  48. {
  49. if(strlen($tresc)<18 OR strcmp(substr($tresc,0,2),"\x1f\x8b"))
  50. return $tresc;
  51. return gzinflate(substr($tresc, 10));
  52. }
  53. ?>

Wywołujemy ją w bardzo prosty sposób:

PHP:
  1. <?php
  2. $tresc=otworz_adres('http://onet.pl/');
  3. ?>

Można również wysłać coś metodą POST. Wygląda to tak:

PHP:
  1. <?php
  2. $tresc=otworz_adres('http://onet.pl', 'login=abc&haslo=123');
  3. ?>

Funkcja radzi sobie z napotykanymi błędami. Gdy coś pójdzie nie tak to 3 razy (można to zmienić, odpowiada za to parametr $blad w wywołaniu funkcji) próbuje pobrać dany adres. Dopiero po trzech niepowodzeniach zwracamy false czyli nie dało się otworzyć adresu.

Funkcja obsługuje kompresję gzip przy czym rozpoznaje czy serwer zwrócił normalne dane czy skompresowane. Pomyślałem, że warto coś takiego dodać bo jak serwer obsługuje gzip to aplikacja zadziała nam szybciej i zjemy mniej transferu. Wszystko dzieje się automatycznie i nie musimy sobie zawracać tym głowy.

Jak ktoś ma jakieś specyficzne wymagania to polecam poczytać o możliwościach curl_setopt. Wspomnę jeszcze, że dodałem obsługę cookies, trzeba tylko pamiętać o stworzeniu pliku cookies.txt :) Jak ktoś jest ciekaw jak to wszystko działa to zapraszam do manuala do części o CURL :) Możliwości jest sporo, każdy może sobie łatwo przystosować tą funkcję do własnych potrzeb.

UWAGA
Oczywiście aby funkcja działała wymagana jest włączona obsługa CURL na serwerze. Na szczęście jest to już praktycznie standard.

EDIT 2008.10.08
Do funkcji dodałem jedną linijkę: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
Powoduje ona, że możemy pobierać strony https:// i nie powoduje to żadnych błędów.

Dodaj komentarz

2 odpowiedzi dla tego wpisu

  1. macem napisał:

    Hehe jakie kombinacje, problem będzie kiedy zmienią stronę i strukturę html, lepiej ciągnać takie rzeczy przed rss w postaci xml jeśli oczywiście serwis to obsługuje (lepiej szukać takich własnie serwisów).

  2. MariuszT napisał:

    Zależy od Twoich potrzeb. Jak piszesz jakiś automat, który ma chodzić po stronie i coś robić to nie ma innego wyjścia jak tylko grzebać w html (no chyba, że jest jakieś API ale wiadomo, że to rzadkość). Albo np. czasami chcę coś ściągnąć to piszę skrypt, włączam go i chodzi godzinę, dwie, dzień albo tydzień aż się dociągnie. Oczywistym jest, że gdy jest taka możliwość to trzeba korzystać z narzędzi udostępnionych przez twórców strony (rss, api itd.).

Odpowiedz



Podobne wpisy: