Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][JS][XML]Pobieranie z "nietypowego" xml.
Forum PHP.pl > Forum > Przedszkole
BigBoyPL
Witam,
Mam pewien problem z wykonaniem skryptu (głównym problemem jest brak wiedzy na temat PHP oraz JS ;]).
Mianowicie potrzebuję zrobić skrypt do pobierania informacji z pewnej strony która w źródle ma wartości xml.
Idealne byłoby gdyby zrobić skrypt który sam sobie pobiera wartości z serwera, następnie porównując je (z plikiem lub z wartościami z bazy) dodaje tylko nowe wyniki (każdy wpis na stronie ma swoją datę). Po co taka kombinacja ? Strona ta oferuje testowe softy na telefony dla developerów LG. Żeby się coś wyświetliło trzeba podać pewne argumeny. Myślę że najłatwiej będzie to wytłumaczyć na przykładzie linku :
Kod
http://csmg.lgmobile.com:9002/csmg/b2c/client/optest_rndapps_websw_list.jsp?country=PL&region=E&buyer=POL&model=

Powyższy link jest do sprawdzenia informacji jakie softy wyszły dla kraj=Polska i sprzedawca=Polska OPEN
Natomiast ten poniżej pokazuje softy dla Niemcy, Vodafone.
Kod
http://csmg.lgmobile.com:9002/csmg/b2c/client/optest_rndapps_websw_list.jsp?country=DE&region=E&buyer=VD2&model=

Jak łatwo dostrzec zmieniamy tylko parametry country oraz region. W systemie jest 250 krajów i zakładając że każdy kraj ma średnio 4 operatorów to daje nam 1000 stron do odwiedzania. A trzeba odwiedzać codziennie albo nawet kilka razy dziennie i ręcznie sprawdzać czy coś się zmieniło.
Jeśli wejdziemy w ten link to pojawi się nam bliżej nie zrozumiały tekst ;]. Po wejściu w źródło sytuacja staje się bardziej oczywista.
pierwszy wpis
  1. <total_count>[LICZBA]</total_count>
daje nam informacje ile softów jest na stronie.
następnie już kolejno jest
  1. <model>[MODEL]</model>
- model telefonu
  1. <buyer>[ABC]</buyer>
oraz
  1. <buyer_name>[NAZWA]</buyer_name>
to 3 literowy skrót sprzedawcy oraz jego pełna nazwa (buyer bo dla producenta nasz sprzedawca jest kupującym ;])
  1. <swversion>V99X_00</swversion>
- wersja softu
  1. <live_date>2013-12-30 23:59:59.0</live_date>
- dokładna data kiedy plik został wrzucony na serwer
  1. <country>XX</country>
oraz
  1. <country_name>Poland</country_name>
- kraj dla jakiego jest soft (skrót i pełna nazwa)
  1. <chip_type>QCT</chip_type>
- typ procesora ( w tym przypadku Qualcomm)
  1. <sw_uri></sw_uri>
oraz
  1. <sw_locale_url></sw_locale_url>
linki do softu
  1. <cdma_sw_uri></cdma_sw_uri>
oraz
  1. <gsm_sw_uri></gsm_sw_uri>
linki do sterowników
Niektóre parametry pominąłem bo są nie ważne.
Następnie znów powtarza się ta sama procedura tylko z kolejnym modelem telefonu.


Jak wiadomo w internecie jest pełno gotowych skryptów zarówno w php jak i w js do robienia tabel, albumów i wszystkiego innego korzystając z pobierania danych z plików .xml
Tutaj znajduje się bardzo dobry przykład
Kod
http://www.w3schools.com/xml/tryit.asp?filename=tryxml_display_table

I tutaj powstają 2 problemy.
Po pierwsze w źródle ze stron których chciałbym użyć nie ma wzorowego xml, mianowicie nie występują znaczniki definiujące początek i koniec kolejnego wpisu.
W przykładzie z linku powyżej plik xml wygląda tak
Kod
http://www.w3schools.com/xml/cd_catalog.xml

i znacznikami oddzielającymi są
  1. <CD></CD>
a pomiędzy nimi dopiero są informacje. U mnie parametry lecą jakby ciągiem i zastosowanie nawet lekko zmodyfikowanego kodu da mi tylko pierwszy wpis bo nie ma tam definicji początku i końca.
Jakoś sobie z tym poradziłem pośrednio, modyfikując na ślepo ten skrypt z przykładu tak długo aż dał mi w miarę sensowny wynik:
  1. <!DOCTYPE html>
  2.  
  3. if (window.XMLHttpRequest)
  4. {// code for IE7+, Firefox, Chrome, Opera, Safari
  5. xmlhttp=new XMLHttpRequest();
  6. }
  7. else
  8. {// code for IE6, IE5
  9. xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  10. }
  11. xmlhttp.open("POST","file.xml",false);
  12. xmlhttp.send();
  13. xmlDoc=xmlhttp.responseXML;
  14. var x=xmlDoc.getElementsByTagName("*");
  15. document.write("<table border='1'>");
  16. document.write("<tr><th>MODEL</th><th>SUFFIX</th><th>DATE</th><th>SW_VER</th><th>DL LINK</th></tr>");
  17. for (i=0;i<x.length;i++)
  18. {
  19. document.write("<tr><td>");
  20. document.write(x[0].getElementsByTagName("model")[i].childNodes[0].nodeValue);
  21. document.write("</td><td>");
  22. document.write(x[0].getElementsByTagName("suffix")[i].childNodes[0].nodeValue);
  23. document.write("</td><td>");
  24. document.write(x[0].getElementsByTagName("approve_date")[i].childNodes[0].nodeValue);
  25. document.write("</td><td>");
  26. document.write(x[0].getElementsByTagName("sw_version")[i].childNodes[0].nodeValue);
  27. document.write("_");
  28. document.write(x[0].getElementsByTagName("cond_version")[i].childNodes[0].nodeValue);
  29. document.write("</td><td><a href=");
  30. document.write(x[0].getElementsByTagName("sw_url")[i].childNodes[0].nodeValue);
  31. document.write(">Download</a></td></tr>");
  32. }
  33. document.write("</table>");
  34.  
  35. </body>
  36. </html>

Skrypt działa prawie dobrze a mianowicie dalej nie jest zdefiniowany koniec ostatniego wpisu i w tabeli na końcu pod ostatnim wpisem tworzy się jeszcze jedna pusta komórka.
Kolejnym problemem jest to że jeśli ręcznie zapiszę sobie wartości z tej strony do pliku .xml na komputerze lub nawet gdzieś w sieci to wszystko się wczytuje, ale jak podam w miejsce pliku adres do strony to już niestety nic się nie wczyta.
Mogę tylko zgadywać że to może być dlatego że to nie jest plik .xml ale strona .jsp i ma tam jakieś dodatkowe konfiguracje w headerze.
Może to być spowodowane też tym że nie zaczyna się od <?xml version blablabla tylko przed tym znacznikiem jest jeszcze 0D 0A w hex powtórzone 13 razy. Tego niestety nie jestem w stanie nijak przeskorzyć z moją wiedzą.

Pisałem wcześniej na innym forum o grach w dziale rozwoju php ale tam nie było żadnego zainteresowania.
Po upływie pewnego czasu stwierdziłem że chyba można zrobić w php tak że pobieramy zawartość tej strony, następnie zamieniamy wszystkie znaczniki
  1. <model>
na powiedzmy
  1. <phone><model>
oraz wszystkie
  1. </gsm_sw_uri>
na
  1. </gsm_sw_uri></phone>

co dało by taką strukturę jaka jest w przykładzie i wtedy mógłbym spokojnie zastosować kod w js z przykładu albo jakiś prosty php.
Ostatnim problemem jest też to że właśnie pliki znikają co jakiś czas a ja chciałbym mieć bazę i trzeba by zrobić skrypt który porównuje wartości z serwera z tymi które są w pliku.xml czy w bazie mysql i dodaje do tego pliku lub do bazy nowe wartości.
Idealnie było by gdyby to mogło się dziać bez mojej ingerencji automatycznie, wtedy mógłbym to wystawić na serwer razem z innymi stronami które już zrobiłem w 100% i to pozwoliło by wszystkim użytkownikom pobierać od razu gotowe softy które będą chcieli.
Jeżeli nie da się tak zrobić to myślę że raz dziennie też znalazłbym trochę czasu żeby chwilkę poklikać, poodświeżać itp. w każdym razie wszystko jest lepsze niż robienie tego ręcznie poprzez kopiowanie wpisów do pliku.
Nie oczekuję że ktoś zrobi za mnie wszystko, da mi gotowy kod i nie będzie chciał nic w zamian ale nie ukrywam że takie rozwiązanie było by najlepsze ;d
Muszę to zrobić jak najszybciej bo to już ostatnie dni kiedy mogę tak beztrosko siedzieć przed komputerem.
Mam nadzieję że chociaż w części uda się wam mi pomóc. Z góry dziękuję.

@Edit po edycji zaawansowanej wysypują się kody xml, na szczęście miałem kopię całego tekstu i sobie poradziłem.
aras785
Ja bym to zrobił tak:

  1. <?php
  2.  
  3. $configs = array(
  4. array('country'=>'PL','buyer'=>'POL'),
  5. array('country'=>'DE','buyer'=>'VD2'),
  6. );
  7.  
  8. foreach($configs as $config) {
  9.  
  10. $site = trim(file_get_contents('http://csmg.lgmobile.com:9002/csmg/b2c/client/optest_rndapps_websw_list.jsp?country='.$config['country'].'&region=E&buyer='.$config['buyer']));
  11. $xml = simplexml_load_string($site);
  12. var_dump($xml);
  13. }


Oczywiście dużo tutaj nie zobaczysz ale otrzymasz tablice z której łatwo wszystko wyciągnać smile.gif Dodatkowo możesz sobie zdeklarować od razu wszystkie kraje itd. To tylko przykład. Jak wrócę do domu mogę coś więcej wyskrobać smile.gif Pozdrawiam


//ps. użyłem ...load_string ponieważ strona wygenerowana posiada dużo lini pustych przez co load_file nie zadziała wink.gif
BigBoyPL
Nie wiem czy to już cały kod czy tylko część i coś trzeba dopisać bo potraktowałem to jako gotowy kod, wrzuciłem na serwer plik.php i spróbowałem otworzyć i na obu serwerach mam jakieś błędy.
chmiello
Chyba warto by było, abyś podał jakie błędy Ci wyskakują, bo tak w ciemno to raczej ciężko będzie pomóc smile.gif
BigBoyPL
Na pierwszym serwerze wyskakuje mi
Kod
Warning: file_get_contents(http://csmg.lgmobile.com:9002/csmg/b2c/client/optest_rndapps_websw_list.jsp?country=PL&region=E&buyer=POL) [function.file-get-contents]: failed to open stream: Connection refused in /srv/disk3/1441943/www/jamarchive.mygamesonline.org/new.php on line 10
bool(false)
Warning: file_get_contents(http://csmg.lgmobile.com:9002/csmg/b2c/client/optest_rndapps_websw_list.jsp?country=DE&region=E&buyer=VD2) [function.file-get-contents]: failed to open stream: Connection refused in /srv/disk3/1441943/www/jamarchive.mygamesonline.org/new.php on line 10
bool(false)

natomiast na innym wyskakuje
Kod
bool(false) bool(false)

Może to wina tego że używam darmowych serwerów ?
Czy komuś działa ten skrypt inaczej niż mi biggrin.gif ?
aras785
mi działa: http://ceasar.website.pl/test.php
BigBoyPL
Prawdopodobnie funkcja
jest wyłączona na wszystkich darmowych serwerach ;]
chmiello
możesz zobaczyć czy CURL jest włączony, bo nim można też pobrać plik
aras785
To kup za 10 zł jakiś i się ciesz:)
BigBoyPL
znalazłem taki kod :
  1. <?php
  2. $c = curl_init();
  3. $strona = curl_setopt($c, CURLOPT_URL, "http://www.google.pl");
  4. curl_exec($c);
  5. curl_close($c);
  6. echo $strona;
  7. ?>

Na pierwszym serwerze nie działa, na drugim pojawia się "1", a na trzecim pojawiła się najpierw "1" a po odświeżeniu pojawiła się cała strona google.
czy to wystarczy do sprawdzenia czy działa CURL czy trzeba coś jeszcze bo naprawdę php całkowicie nie ogarniam ;]
aras785
  1. <?php
  2. //funkcja pobierania strony
  3. function pobierz($url) {
  4. $curl = curl_init($url);
  5. curl_setopt( $curl, CURLOPT_RETURNTRANSFER , TRUE );
  6. $content = curl_exec( $curl );
  7. curl_close( $curl );
  8. return $content;
  9. }
  10. //konfiguracja
  11. $configs = array(
  12. array('country'=>'PL','buyer'=>'POL'),
  13. array('country'=>'DE','buyer'=>'VD2'),
  14. );
  15.  
  16. foreach($configs as $config) {
  17.  
  18. $site = trim(pobierz('http://csmg.lgmobile.com:9002/csmg/b2c/client/optest_rndapps_websw_list.jsp?country='.$config['country'].'&region=E&buyer='.$config['buyer']));
  19. $xml = simplexml_load_string($site);
  20. var_dump($xml);
  21. }

Sprawdź i powiedz czy śmiga
BigBoyPL
Niby powinno się wykonać ale zostawiłem na godzinę a strona nadal się ładowała ;]
Także stwierdzam że wszystkie darmowe serwery są ble do takiego zadania.
Z drugiej strony szkoda wydawać kasę w błoto na coś co jeszcze nie działa dlatego postaram się zainstalować XAMPP'a albo coś innego co pozwoli mi wykonywać php na komputerze. Myślę że to będzie najprostsze i najtańsze rozwiązanie ;]

Analizując troszkę kod oraz odpowiedź ze strony użytkownika aras785 stwierdziłem że polecenie var_dump daje wyniki w ten sposób że wymienia wszystkie wartości jakie są w każdym znaczniku xml i grupuje je według znaczników i jeszcze dodatkowo wartości z każdej strony są osobno.
Jeśli była by wczytana tylko jedna strona to zapewne następnym krokiem byłoby umieszczenie tego skryptu php w kodzie html, dodanie do skryptu polecenia uformowania tabeli podobnie jak w kodzie JS który podałem poprzez użycie
  1. echo "<table>
  2. <tr><th>MODEL</th><th>SW_VER</th><th>COUNTRY</th><th>BUYER</th><th>DATE</th><th>DL LINK</th></tr>
  3. <tr>"
jako tytuł
oraz dodanie w jakiś sposób
  1. getElementsByTagName
do
echo "<td>$model[0]</td><td>$country_name[0]</td><td>$buyer_name[0]</td><td>$live_date[0]</td><td><a href=$sw_locale_url[0]>Download</a></td>
</tr>"[/php]
zamiast tych [0] zapewne trzeba użyć [i] oraz zdefiniować jakoś ilość tych elementów i dodać pętle do tworzenia tabeli na końcu zakończyć ją </table> Można to pewnie zrobić przez sprawdzenie ile jest wpisów typu <model> albo też jaka jest liczba w <total_count>.
Nie wiem kompletnie jak to z 2 i więcej stronami zrobić bo tam się powtarzają wtedy numery poszczególnych elementów ale treść jest inna.

W miarę jak czas będzie mi na to pozwalał zrobię całą listę wszystkich krajów + operatorów.



Tak sobie myślę że w sumie wyświetlanie to jest najmniejszy problem. Można to zrobić nawet w JS odpowiednio modyfikując kod z pierwszego postu, bez użycia PHP.
Natomiast najważniejsza jest raczej część która ma za zadanie pobierać dane, następnie porównywać je z plikiem i wpisywać do tego pliku tylko te dane których nie ma jeszcze w tym pliku.
Jakby to zrobić tak że PHP będzie tworzyć plik xml dodatkowo ze znacznikami każdego wpisu, następnie modyfikując go uzupełniając o brakujące nowe elementy ze stron to wtedy można zastosować gotowy skrypt i nie będzie problemu z wyświetlaniem.
Rozumiem że żeby to się działo automatycznie to trzeba mieć dostęp do cron na swojej stronie i tam ustawić żeby co jakiś czas wykonywał ten skrypt.


@Refresh temat się wyczerpał, nikt nie ma nic do dodania ?
Może coś powinienem zrobić o czym nie wiem?

@Refresh 2
Uwaga, teraz najlepsze !
Otrzymałem wiadomość od swojego hostingu że nie mam jeszcze utworzonej strony, w odpowiedzi napisałem że nie jest mi potrzebny hosting gdzie funkcja file_get_contents jest wyłączona. Po kilku dniach otrzymałem odpowiedź że funkcja jest domyślnie włączona a problem leży w kodzie :E

Na szybko wkleiłem takie coś na serwer :
  1. <?php
  2. $homepage = file_get_contents('http://www.google.com/');
  3. echo $homepage;
  4. ?>

Jak to wykonałem to zobaczyłem stronę google normalnie, tylko bez obrazków.
Jeśli tylko zmienię link na
Kod
http://csmg.lgmobile.com:9002/csmg/b2c/client/optest_rndapps_websw_list.jsp?country=DE&region=E&buyer=DEU
to po wykonaniu jest pusta strona.
Tajgeer
Większość hostingów blokuje możliwość pobierania stron z użyciem cURL / file_get_contents na portach innych niż standardowa "80". To jest zapewne problem.
BigBoyPL
Dzięki za twoją odpowiedź.
Serwery csmg są bardziej uniwersalne i mają kilka hostów, nie tylko na porcie 9002.
wystarczyło zmienić
Kod
csmg.lgmobile.com:9002/
na
Kod
csmgdl.lgmobile.com/
i już na stronie wyświetla mi się tablica.
@Edit zrobiłem takie coś.
Nie jest to jeszcze pełna lista, docelowo będzie przynajmniej 4 razy większa. Są tylko operatorzy krajowi typu OPEN. (Kupowanie telefonu bez operatora w sklepach a nie w salonach operatora).
Kod
http://wklej.to/0KLky

Na dzień dzisiejszy daje to 102 linki do softów w tablicy.
Oczywiście niektóre strony są puste i widzę że tam zostaje tylko jeden
Kod
   ["req_cmd"]=>
    string(9) "XMLReturn"
    ["status"]=>
    string(4) "FAIL"
który za bardzo nie śmieci.
Jak teraz przejść z tego co się wyświetla w odpowiedzi (to się chyba nazywa tablica questionmark.gif) do zapisywania potrzebnych informacji (nie wszystkich) do pliku xml, txt lub o dowolnym innym rozszerzeniu, a następnie porównywanie nowych wartości z odświeżonej strony z tymi które znajdują się w pliku i zapisywaniu tylko tych które są nowe ?
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.