[Qt] Parsowanie dokumentu www |
[Qt] Parsowanie dokumentu www |
4.08.2012, 15:30:02
Post
#1
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
Mam taki kodzik :
Kod QWebPage page; QWebFrame * frame = page.mainFrame(); frame->setHtml(str); QWebElement document = frame->documentElement(); QWebElementCollection tables = document.findAll(".table"); int numTables = tables.count(); qDebug() << numTables; return; Pod zmienną str znajduje się źródło tej strony : http://panoramafirm.pl/szukaj/mazowieckie,...wa/firmy,1.html Chcę pobrać ilość elementów o klasie table. Niestety program podaje, że tych elementów jest 0. Podczas gdy w rzczywistości jest ich 15. Gdy zamiast ".table" dam "a", to zwraca mi to 17, czyli jakieś linki znajduje ale chyba jest ich ciut za mało. W czym może być problem ? Wszystkie tabelki są w divie o klasie "results" <- tego diva nie mogę pobrać. Mogę za to pobrać div o nazwię 'socialIcons right" ale nie w całości - na nim program kończy parsowanie. Ten post edytował peter13135 4.08.2012, 16:07:05 -------------------- :)
|
|
|
6.08.2012, 12:51:01
Post
#2
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) |
Dawno nie miałem już z Qt styczności ale spróbuj zobaczyć co wyrzuca metoda QWebFrame::toHtml. Webkit wykonuje Javascript - możliwe więc że te klasy zostają usunięte w trakcie przetwarzania (albo to zabezpieczenie przed zewnętrznymi skanerami). Ostatecznie zostaje struktura dokumentu HTML - może jest tak zwalona że nie przechodzi (ale to mało prawdopodobne).
-------------------- Już mi się ani wiedzieć, ani tym bardziej myśleć nie chce.
[Think different]! |
|
|
6.08.2012, 13:30:49
Post
#3
|
|
Grupa: Zarejestrowani Postów: 898 Pomógł: 80 Dołączył: 31.05.2008 Ostrzeżenie: (20%) |
Pobierz treść najprościej jak się da, wrzuć do DOM'a prze-iteruj jak xml'a, wyciąg i zlicz dane. Amen.
-------------------- cojack blog - mój blog (na jakiś czas off).
"jak czegoś nie wiem, to nie myślę że wiem" - moja domena |
|
|
6.08.2012, 19:20:43
Post
#4
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
Kod frame->setHtml(str); qDebug() << frame->toHtml(); Dziwna sprawa. Ostatnie linijki tego "debuga" to: Kod <div class="socialIcons right"> <!-- AddThis Button BEGIN --> <span class="shareItText left">Podziel się wynikami</span> <div class="addthis_toolbox addthis_default_style"> <a class="addthis_button_facebook" title="dodaj do facebook'a"></a> <a class="addthis_button_google" title="dodaj do google'a"></a> <a class="addthis_button_compact" title="dodaj do innych"></a> </div> <script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#pubid=xa-4fe954876fcacb33"></script></div></div></div></div></div></div></div></body></html>" Za tym divem (socialIcons) powinien być jeden pusty div z klasą "clear" i potem div reslults z tabelkami. -------------------- :)
|
|
|
6.08.2012, 21:38:53
Post
#5
|
|
Grupa: Zarejestrowani Postów: 592 Pomógł: 62 Dołączył: 3.08.2006 Ostrzeżenie: (0%) |
ten kod, który podałeś znajduje się z źródle strony, sprawdź w firebugu,
co prawda powinien byc jeszcze ten clear i result, ale nie wiem z jakiej strony jest ten wyciąg -------------------- :]
|
|
|
7.08.2012, 08:28:46
Post
#6
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
Nie wiem o co Ci chodzi.
Dałem linka w pierwszym poście, więc chyba powinieneś wiedzieć skąd ten wyciąg . Po divie socialicons powinien być div clear i div results a w nim interesujące mnie dane. Następnie jakieś tam footerki. Niestety metoda toHtml zwraca mi nie takie źródło, jakie jest w krzeczywistości, bo już po divie socialicons zamykane są divy, body i html. -------------------- :)
|
|
|
7.08.2012, 11:04:53
Post
#7
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) |
Znalezione w necie:
Wyłącza parsowanie JS. Jeśli to nie pomoże to spróbuj metodę cojacka -------------------- Już mi się ani wiedzieć, ani tym bardziej myśleć nie chce.
[Think different]! |
|
|
7.08.2012, 17:10:50
Post
#8
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
Zrobiłem inaczej. Za pomocą regexpa znalazłem pozycję (czyli od którego znaku w stringu zaczyna się ten div) obciąłem to co było wcześniej za pomocą QString::remove(), to coś wrzuciłem do QWebFrame i teraz mi hula
Pewnie wasze sposoby są lepsze, ale póki co mój sposób działa Dzięki za odpowiedź, idą pochwały. -------------------- :)
|
|
|
8.08.2012, 02:15:39
Post
#9
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 1 Dołączył: 1.05.2007 Ostrzeżenie: (0%) |
Całe api webkita jest po to, żebyś nie musiał korzystać z regexpa do takich rzeczy. W tym przypadku table.table da ten sam wynik co .table, ale.. Te ostatnie linijki debuga- gdzie wykonujesz ten kod? Ja pozwoliłbym webkitowi ściągnąć stronę i coś podobnego tego co dałeś wykonał pod sygnałem load_finished;>
Niby pytanie o banał, ale nie takie rzeczy już na forach wychodziły. |
|
|
8.08.2012, 16:39:56
Post
#10
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
Cytat Całe api webkita jest po to, żebyś nie musiał korzystać z regexpa do takich rzeczy. Do pewnego czasu mój program działał bez regexpa (kod z pierwszego postu działał) ale ponieważ od pewnego czasu mój program przestał działać (kończył parsowanie na pewnym kodzie js), to za pomocą regexpa wyciąłem sobie kod od interesującego mnie diva, do końca dokumentu (czyli </html> ). I ten "ucięty" html wrzuciłem tak samo jak w pierwszym poście i działa Daj mi działający kod nie wymagający regexpa, to chętnie użyję. Cytat W tym przypadku table.table da ten sam wynik co .table Napławde ? Cytat ale.. Te ostatnie linijki debuga- gdzie wykonujesz ten kod? Ja pozwoliłbym webkitowi ściągnąć stronę i coś podobnego tego co dałeś wykonał pod sygnałem load_finished;> Nie rozumiem. -------------------- :)
|
|
|
8.08.2012, 18:36:53
Post
#11
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 1 Dołączył: 1.05.2007 Ostrzeżenie: (0%) |
Zrobiłem po swojemu, wklejając kod gdzie trzeba. Debug zwrócił dwie liczby:
0 25 Na szybko wstawiłem ramkę (ui->webView), kod: MainWindow.h Kod #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QWebElementCollection> #include <QWebFrame> #include <QDebug> namespace Ui { class MainWindow; } PS: Bez okien też jakoś się dało, ale nie pamiętam:P class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_webView_loadFinished(bool arg1); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H mainwindow.cpp Kod #include "mainwindow.h"
#include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QUrl url("http://panoramafirm.pl/szukaj/mazowieckie,warszawa/firmy,1.html"); ui->webView->setUrl(url); ui->webView->load(url); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_webView_loadFinished(bool arg1) { QWebPage* page = ui->webView->page(); QWebFrame * frame = page->mainFrame(); QWebElement document = frame->documentElement(); QWebElementCollection tables = document.findAll(".table"); int numTables = tables.count(); qDebug() << numTables; } Ten post edytował katsuo 8.08.2012, 18:41:48 |
|
|
8.08.2012, 20:00:02
Post
#12
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) |
@katsuo prawdopodobnie ma rację. Jeśli QWebFrame zachowuje się analogicznie jak UIWebView w iOSie to asynchroniczne ładowanie zawartości mogło powodować twój błąd. Twoje regexowanie mogło to jedynie zamaskować (poprzez opóźnienie wywołania findAll() ). Wszystko to przy założeniu że QWebFrame rzeczywiście zachowuje się asynchronicznie
-------------------- Już mi się ani wiedzieć, ani tym bardziej myśleć nie chce.
[Think different]! |
|
|
8.08.2012, 20:30:35
Post
#13
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
Jak to debug zwrócił 0 i 25 ?
Tabelek o tej klasie jest 15 Nie bardzo wiem o co wam chodzi Mogę prosić o jakiś prostsze wyjaśnienie ? Nie roumiem jak ten regexp ma maskować błąd. -------------------- :)
|
|
|
8.08.2012, 21:08:07
Post
#14
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) |
Jeśli moje przypuszczenie jest poprawne - metoda setHtml instruuje QWebView żeby zaczął parsować HTML. Ale on to robi asynchronicznie więc reszta kodu spokojnie się wykonuje, nawet jeśli drzewo DOM nie zostało do końca zbudowane. UIWebView w iOSie udostępnia metodę delegata (coś ala slot w Qt) żeby powiadomić nas kiedy jest on gotowy do użycia. Nie rozumiem do końca kodu @katsuo ale przypuszczam że QWebFrame udostępnia jakiś sygnał informujący o załadowaniu się htmla w który można się wpiąć.
Co do regexpa to wolne przypuszczenie. Możliwe że kiedy ty dokonujesz manipulacji regexem te parę ms wystarcza żeby drzewo DOM zostało załadowane. * Wydaje mi się dziwne żeby samo obcięcie końcówki taga magicznie "naprawiło" HTMLa - jest niby taka możliwość, ale wtedy dokument sypałby się wszędzie. @EDIT Z dokumentacji Qt Cytat ExternalThe html is loaded immediately; external objects are loaded asynchronously. Sam już nie wiem niby drzewo DOM jest ładowane od razu a tylko reszta dociągana. Chyba dokument jest generowany JSem. Ten post edytował everth 8.08.2012, 21:12:35 -------------------- Już mi się ani wiedzieć, ani tym bardziej myśleć nie chce.
[Think different]! |
|
|
8.08.2012, 21:24:12
Post
#15
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 1 Dołączył: 1.05.2007 Ostrzeżenie: (0%) |
1. Następnym razem dołączaj cały kod, nie wróżymy z fusów
2. Poczytaj o sygnałach, slotach i event driven programming. Wczytaj się w dokumentację samego qt- w pewnym momencie myślałem, że wklejasz html do qLineEdit który ma limit długości(patrz pkt.1) @everth: Mimo, że dołączone są biblioteki jquery do strony, tabelki są dostępne bez js- kolega coś skopał, i nie wiadomo co(pkt. 1) |
|
|
8.08.2012, 21:46:13
Post
#16
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
No dobra, więc przerobiłem swój kodzik na taki :
to metoda która się odpala wtedy, gdy dokument html został zassany i zapisany do zmiennej str (QString) Kod void Widget::httpFinished(){ qDebug() << "httpFinished()"; QWebPage page; frame = page.mainFrame(); frame->setHtml(str);//jak debuguje str, to dostaje taki dokument html jak w oryginale (czyli jest ok) connect(frame, SIGNAL(loadFinished(bool)), this, SLOT(htmlParsed()));//gdy skończy się "parsowanie" dokumentu html, odpalam slot, który pobierze interesujące mnie informacje } Kod void Widget::htmlParsed() { QWebElement document = frame->documentElement(); QWebElementCollection tables = document.findAll("table.table"); int num_tables = tables.count();//to ma oczywiście wartość 0 (czyli źle);) qDebug() << frame->toHtml();//to wyświetla mi "niepełny" kod html, który kończy się na któryś tam divie. To co mnie interesuje nie zawiera się w tym kodzie. return; //reszta kodu } Ale nie hula. -------------------- :)
|
|
|
8.08.2012, 21:51:55
Post
#17
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 1 Dołączył: 1.05.2007 Ostrzeżenie: (0%) |
spakuj cały projekt i wyślij na jakiś (lekki)hosting, na prawdę będzie łatwiej.
|
|
|
9.08.2012, 21:46:09
Post
#18
|
|
Grupa: Zarejestrowani Postów: 1 447 Pomógł: 191 Dołączył: 26.03.2008 Ostrzeżenie: (0%) |
http://www.sendspace.pl/file/b9a852801bddf23ea604782
Wywaliłem całe gui i inne rzeczy, żebyś nie musiał zbyt wiele szukać edit:// Co tak umilkłeś ? Nie chcesz mi już pomóc ? edit:// Zrobiłem Twoją metodą, tzn nie łąduję za pomocą QNetworkManagera, tylko za pomocą QWebPage i teraz działa. Nie wiem tylko czemu tak wolno. I nadal nie wiem czemu sposób z użyciem setHtml() nie działa. Pozwolę nieco skomentować Twój wcześniejszy post. Cytat 1. Następnym razem dołączaj cały kod, nie wróżymy z fusów Jeśli by problemem miała być asynchrnicznicznie działąjąca klasa (czy o czym tam mówiłeś), to w moim kodzie wyraźnie widać, że od razu po wywołaniu setHtml, "parsuję" cały dokument. Poza tym, tak się składa, że błąd jest właśnie gdzieś w tym kodzie, który dałem w pierwszym poście. Cytat 2. Poczytaj o sygnałach, slotach i event driven programming. Po co ? Cytat Wczytaj się w dokumentację samego qt- w pewnym momencie myślałem, że wklejasz html do qLineEdit który ma limit długości(patrz pkt.1) Jak się ma początek tego zdania, do drugiej części ? Jak się ma moje "wczytywanie w dokumentację Qt" do tego, że myślałeś, że wklejam html do QLineEdit ? Co zasugerowało, że wklejam html do QLineEdit ? Przecież na podstawie mojego kodu widać bardzo przejrzyście, instancją jakiej klasy jest każda ze zmniennych, bo właśnie w tej funkcji są one deklarowane. Może poza zmienną str, ale po nazwie możesz się domyśleć, że to QString, oraz po tym, że metoda QWebFrame::setHtml() przyjmuje parametr QString (a nie żadne QLineEdit). Ten post edytował peter13135 9.08.2012, 22:16:32 -------------------- :)
|
|
|
10.08.2012, 00:13:30
Post
#19
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) |
popisz trochę więcej w JavaScript - to Ci powinno ułatwić programowanie zdarzeniowe... dodatkowo drzewo DOM w przeglądarkach zawsze renderowało się asynchronicznie (stąd były specjalnie tworzone metody pokroju .ready np. w jQuery)...
edit:// Zrobiłem Twoją metodą, tzn nie łąduję za pomocą QNetworkManagera, tylko za pomocą QWebPage i teraz działa. Nie wiem tylko czemu tak wolno. I nadal nie wiem czemu sposób z użyciem setHtml() nie działa. wyłącz obrazki i wyłącz wykonywanie JavaScript skoro to Ci nie potrzebne... w Twoim kodzie niewiele zmieniłem i działa - zdarzenie jest przypisane do QWebPage, więc musi on trochę dłużej istnieć itd... tabel z tą klasą znajduje 25...
Ten post edytował zegarek84 10.08.2012, 00:30:10 -------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
Wersja Lo-Fi | Aktualny czas: 19.04.2024 - 04:29 |