Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] cURL pobieranie dużej ilości danych i wsadzanie ich do bazy
Forum PHP.pl > Forum > Przedszkole
piotrex41
Witam,

Co prawda z PHP mam kontakt od 3 lat, to tematyka cURL jest mi kompletnie obca, a niestety muszę go użyć. Przechodzę do sedna:

Na praktykach dostałem do napisania serwis z ogłoszeniami dla osób poszukujących pracę. Pracodawcy dodają oferty itp. Całość napisana obiektowo, ale jest jedna rzecz na której się zaciąłem. Mianowicie właśnie cURL. Chodzi o automatyczne pobiernie ofert pracy z http://www.pup.gliwice.pl/klient/oferty_pracy.html Niestety nie ma tam RSSa więc trzeba to jakoś wyciągnąć sposobem, którym właśnie jest cURL.

Problem polega na tym, że na tej stronie są jedynie "zajawki" ofert a pełny opis (który muszę pobrać) znajduje się w linku, otwieranym w nowym oknie JS po kliknięciu.

Skrypt ma codziennie o godzinie 18 sprawdzać czy są nowe oferty i je dodawać do moderacji (moderacja jest już zrobiona, trzeba tylko wrzucać zapytaniem do bazy danych pobrane oferty).

Kompletnie nie wiem jak mam się za to zabrać. Dla mnie cURL to czarna magia. Wiem że pobrane źródło muszę filtrować regexp'ami, ale nic pozatym tongue.gif

Połączenie już zrobiłem, źródło mam, ale dalsze grzebanie to już masakra dla mnie.

Bardzo proszę o pomoc.
Octobus
Ale w czym dokladnie jest problem ? Wchodzisz curlem na strone, wyciagasz linki i robisz petle dla stron na ktore musisz wejsc zeby cale oferty sprawdzic. Adres pelnej oferty masz w href (zapomnij o js przy curl i ogolnie php). Ustaw naglowki i referery zeby cie zbyt szybko/w ogole nie zbanowali smile.gif To wcale nie jest duza ilosc danych tylko duzo zadan. Zrobi sobie crona. 1 wywolanie pobierze ze strony glownej linki do ofert, drugie przejdzie na strone druga a nastepne beda pobieraly dane. Ustaw co minute i hajda smile.gif Mozesz tez ustawic sobie petle zeby byla kontrola czasu to bedzie szybciej ale nie bede Ci motal. Tak bedzie dobrze 1 wywolanie na minute. Do konca dnia powinienes miec swierze oferty wink.gif
piotrex41
Tochę mnie nastraszyłes z tym banowaniem tongue.gif

Mój kod do cURL jest następujący:

  1. $curl = curl_init();
  2. //Inicujemy curl
  3.  
  4. curl_setopt($curl, CURLOPT_URL, 'http://www.pup.gliwice.pl/klient/oferty_pracy.html');
  5. //pobieramy dane z "http://www.lfsworld.net/?win=stats&racer=rafal612b2"
  6.  
  7. curl_setopt($curl, CURLOPT_REFERER, "http://www.google.pl/");
  8. //ustawiamy refferer na www.google.pl (niektóre strony mają zabezpieczenia
  9.  
  10. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  11. //wyniku nie wyświetlamy a zapisujemy do zmiennej co ułatwia prace nad nim
  12.  
  13. curl_setopt($curl, CURLOPT_USERAGENT, 'Googlebot/2.1 (+http://www.googlebot.com/bot.html)');
  14. //ustawiamy useragent (niektóre strony mają zabezpieczenia)
  15.  
  16. curl_setopt($curl, CURLOPT_TIMEOUT, 30);
  17. //Maxymalny czas połączenia ze stroną
  18.  
  19. curl_setopt($curl, CURLOPT_HEADER, 0);
  20. //nie chcemy dołączać nagłówka
  21.  
  22. $strona = curl_exec($curl);
  23. //uruchamiamy skonfigurowanego curla
  24.  
  25. curl_close($curl);
  26. //zamykamy


Coś trzeba zmienić?

I teraz powiedz czy dobrze zrozumiałem biggrin.gif
1. Pobieram cURL całą zawartość strony
2. Filtruję sobie z tego linki
3. Każdy link znów traktuje cURL (w pętli) i pobieram całą zawartość, następnie wybieram co potrzebne i do bazy wrzucam poprzez zapytanie?

No i jak zrobić żeby zawsze o 18 sprawdzał? Bo zdaje mi się że zwykły IF sprawdzający godzinę przez date('H'); to było by chyba za proste smile.gif
Octobus
Ja dostalem kiedys bana na wordpress.com tongue.gif przeze mnie musieli zrobic ograniczenie zapyan hehe ale na pup watpie zeby to robili. Moze nawet nie zauwaza smile.gif zrob sobie liste naglowkow przegladarek i je losuj i referer moze byc nawet na sztywno jako strona glowna pup. Zawsze to bedzie lepiej wygladalo (naturalniej). Ale jak bedziesz sie laczyl co minute to nie powinni niczego zrobic. Ja na ww serwis dawalem po 10 000 zapytan dziennie tongue.gif hehe ale nie curlem tylko takim narzedziem. Mozesz tez udawac ze jestes googlebotem tak jak powyzej co powinno byc bezpieczniejsze bo beda mysleli ze to g wink.gif i mysle ze to lepsze rozwiazanie

1. wchodzisz na strone glowna, pobierasz linki i np zapisujesz do bazy status ze 1 etap juz wykonany
2. wchodzisz na wszystkie strony ofert (albo nie wszystkie tylko np 3 pierwsze, nie przygladalem sie serwisowi), wyciagasz linki i zapisujesz do bazy status ze wykonuje 2 etap i jest na x stronie, albo ze wykonal juz 2 etap
3. wchodzisz na wszystkie oferty, parsujesz je i zapisujesz do bazy. W bazie ja bym trzymal url'e ofert na tabeli unique zeby nie wchodzic pare razy na te same i trzymalbym tam flage zeby wiedziec czy ma to parsowac czy jeszcze nie parsowal.

Zalezy jak bardzo chcesz zeby to bylo dokladne ale mysle ze tak jest ok i starczy. Ewentualnie mozesz sprawdzac czy kod odpowiedzi http ==200 jesli nie to jest cos nie tak (np strona nie istnieje albo wystapil timeout) ale dalbym sobie spokoj z tym. Jednak na przyszlosc jakbys chcial to masz kod do tego:

  1. if (curl_getinfo($handle, CURLINFO_HTTP_CODE) != "200") {
  2. exit('Nieprawidlowa odpowiedz, serwer zwrocil naglowek http: '.curl_getinfo($handle, CURLINFO_HTTP_CODE));
  3. }


Sory za straszaka z banem, o to trzeba sie w sumie postarac szczerze mowiac smile.gif ja od paru miesiecy parsuje anglojezyczny serwis raz na jakis czas co minute pobieram z niego dane i nigdy nie mialem problemu smile.gif ale zawsze jest znikome ryzyko.

Jesli chodzi o sprawdzanie po 18stej to ustaw sobie ten plik na zadaniu cron zeby wykonywal sie od 18 do powiedzmy 24. Sparsowanie tego serwisu moze troche trwac ale napewno sie wyrobi.
piotrex41
No dobra, mam całe źródło, i teraz tak. Każda oferta jest linkiem do kolejnej, więc musze te linki wyciagnąć. Oto kawałek kodu HTML jednej oferty:

  1. <table class="ogolna1 oferta_mater" style="width:330px; " >
  2. <tr>
  3. <th colspan="2" style="text-align:center"><a onclick="showPopupWindow(this.href,712,560);return false;" href = "http://www.pup.gliwice.pl/klient/oferta/1285.html">Tapicer</a></th>
  4. </tr>
  5. <tr>
  6. <td class="lewa_s">Nr oferty:</td>
  7. <td class="prawa_s">StPr/12/1448</td>
  8. </tr>
  9. <tr>
  10. <td class="lewa_s">Miejsce pracy:</td>
  11. <td class="prawa_s">44-100 Gliwice, ul. -Niemcy</td>
  12. </tr>
  13. <tr>
  14. <td class="lewa_s">Ważna od:</td>
  15. <td class="prawa_s">2012-05-24</td>
  16. </tr>
  17. </tbody>

Teraz ja muszę wyciągnąć ten link (to co się znajduje w href) - http://www.pup.gliwice.pl/klient/oferta/1285.html
Ale co bym nie zrobił, to coś nie idzie tego wyciągnąć. Mój kod:
  1.  
  2. $dane = array();
  3. for($i = 0; $i <= 10; $i++)
  4. {
  5. preg_match('/<a onclick="showPopupWindow(this.href,712,560);return false;" href = "(.+?)">/', $this->_home, $dane[]);
  6. }
  7. print_r($dane);

Co pokazuje ciągle pustą tablicę.

Jakaś wskazówka? smile.gif
Octobus
  1. #<a onclick="showPopupWindow(.*?);return false;" href = "(.*?)">#i
wink.gif nie wiem co bylo nie tak ale teraz jest dobrze tongue.gif
polecam ta strone do testowania. Codziennie jestem na niej pare/parenascie razy smile.gif
piotrex41
No niby jest ok, ale wszędzie jest ten sam link tongue.gif Jakieś inne pomysły? smile.gif

//edit

Mój obecny kod:
  1. $this->_home = preg_replace('/\<head\>(.*?)\<\/head\>/is', '<head></head>', $strona); //pozbycie się obszernej sekcji head dla łatwiejszego czytania kodu
  2.  
  3. $dane = array();
  4. for($i = 0; $i <= 10; $i++)
  5. {
  6. preg_match('#<a onclick="showPopupWindow(.*?);return false;" href = "(.*?)">#i', $this->_home, $dane[]);
  7. }
  8. print_r($dane);


A przypomnę że potrzebuje tylko to co jest między href = " a " wink.gif
Octobus
Coś jest nie tak, nie moze byc wszedzie ten sam link. SPójrz w źródło czy href sie zmienia. Ja uzywam preg_match_all zawsze z przyzwyczajenia ale to raczej nie powod. Przesledz krok po kroku swoj kod co zostaje po wykonaniu kazdej funkcji i mysle ze to Cie naprowadzi.
piotrex41
Cóż, debugowanie kodu nie wiele dało, więc spróbowałem tego preg_match_all() i wyszło... No wyszło co wyszło tongue.gif Co prawda są wszystkie linki, ale tablica jest ogromna:

Jest tak gigantyczna, że nawet nie mogę tu jej wkleić biggrin.gif Oto link do jej źródła: http://pastebin.com/EaVMSLTN

Mój kod:
  1. $dane = array();
  2. for($i = 0; $i <= 10; $i++)
  3. {
  4. preg_match_all('#<a onclick="showPopupWindow(.*?);return false;" href = "(.*?)">#i', $this->_home, $dane[]);
  5. }
  6. print_r($dane);


@EDIT:

Ok udało mi sie pozbyć nadmiaru info, mam już tylko linki, ale niestety tylko ze strony głównej:
  1. $dane = array();
  2. preg_match_all('#<a onclick="showPopupWindow(.*?);return false;" href = "(.*?)">#i', $this->_home, $dane[]);
  3.  
  4. print_r($dane[0][2]);


I jak teraz zrobić żeby sprawdzał na wszystkich podstronach a nie tylko na 1szej? smile.gif
Czy za każdym razem muszę nowego curla inicjować w pętli dodającej numer strony a później łączyć tablice z linkami w 1?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.