Wyrażenia regularne,wyciąganie danych z pomiędzy znaczników

0

Cześć ,

pisze ponieważ nie mogę się dokopać w internetach do jakiegoś sensownego przykładu ,który pokazał by w ogóle coś sensownego :P.
Chce wyciągnąć dane z pomiędzy znaczników HTML np. div a /div?
Przepraszam że w takiej formie ale nie wyświetla mi znaczników html,macie w swoich zasobach coś co by mi pomogło ?

0

Nie bardzo rozumiem pytanie. <\w+>(.*?)</\w+>
http://ideone.com/32Sbj3

0

Chodził mi o wzorzec który wyciągnął by mi dane z pomiędzy dwóch znaczników html :) tylko tyle .. Nie moge sie odnaleźć w internacie..:p ps. Jak nauczyć sie w jakiś sensowny sposób wyrazem regularnych

0

No to wyżej masz odpowiedni kod. Możesz ewentualnie zamienić \w+ na konkretny znacznik.

0

Jakbyś chciał sobie sprawdzić poprawność wyrażenia, to polecam: http://www.regexplanet.com tam w menu Testing wybierasz język. Niestety nie mają C++, ale wybierz sobie jakiś inny język i też będzie ok.
Tylko uważaj, bo w niektórych przypadkach są różnice między językami.
A tak na marginesie, to lepszy od regexów będzie dla ciebie jakiś parser html.

0

Najlepiej skorzystać z Selenium albo WatiN.

A co do wyrażanie regularnego: <\(w+)>([^<]*)</\1>

0

Można tego dokonać np tak:

#include <iostream>
#include <regex>
#include <iterator>

int main(){
    std::string html_string =
        "<div>emty: </div><html>\n\t<head>\n\t\t<title>Title</title>\n\t</head>\n"
        "\t<body>\n"
        "\t\t<div>Some text :(@*#D(*<#9382ue92d<>j,.<,.as>doij</div>\n"
        "<div>second text: ksjdla</div>"
        "\t</body>\n</html><div>numer : 123456789 </div>";
    std::cout << html_string << std::endl;

    std::regex get_div_expression("<div>(.*?)</div>");              //expression
    std::smatch match;                                              //container to which we collect data

    for(std::string::const_iterator start = html_string.cbegin();               //start C iterator
        std::regex_search(start,html_string.cend(),match,get_div_expression);   //search and match pattern
        std::advance(start,match.str(1).size() + match.prefix().str().size())){ //add len prefix and size match
            std::cout << "We get: " << match.str(1) << std::endl;               //print
    }
}

Tutaj wycinasz niezachłannym operatorem ".*?" wszystko pomiędzy

a
.
For jest znacznie przeładowany, nic nie stoi na przeszkodzie aby go trochę rozbić.</p>
0
Wesoły Kot napisał(a):

Można tego dokonać np tak:

#include <iostream>
#include <regex>
#include <iterator>

int main(){
    std::string html_string =
        "<div>emty: </div><html>\n\t<head>\n\t\t<title>Title</title>\n\t</head>\n"
        "\t<body>\n"
        "\t\t<div>Some text :(@*#D(*<#9382ue92d<>j,.<,.as>doij</div>\n"
        "<div>second text: ksjdla</div>"
        "\t</body>\n</html><div>numer : 123456789 </div>";
    std::cout << html_string << std::endl;

    std::regex get_div_expression("<div>(.*?)</div>");              //expression
    std::smatch match;                                              //container to which we collect data

    for(std::string::const_iterator start = html_string.cbegin();               //start C iterator
        std::regex_search(start,html_string.cend(),match,get_div_expression);   //search and match pattern
        std::advance(start,match.str(1).size() + match.prefix().str().size())){ //add len prefix and size match
            std::cout << "We get: " << match.str(1) << std::endl;               //print
    }
}

Tutaj wycinasz niezachłannym operatorem ".*?" wszystko pomiędzy

a
.
For jest znacznie przeładowany, nic nie stoi na przeszkodzie aby go trochę rozbić.</p>

Sprawdziłem twój kod,działa na prawdę świetnie i szybko
#include <iostream>
#include <curl/curl.h>
#include <fstream>
#include <regex>
#include <string>

using namespace std;

fstream plik1;
string tekst;
plik1.open("kodHTML.txt",std::ios::in);

string wynik; // Dane z pliku1 przechytuje ta zmienna
smatch dopasowanie; //wynik dopasowania
regex wzorzec("<tbody>(.*?)</tbody>");
while(!plik1.eof())
{
    //getline(basic_istream<char>&, string&, char)
    getline(plik1,wynik);

    if(regex_search(wynik,dopasowanie,wzorzec))
    {
       cout <<wynik[0]<<endl;
    }


}
return 0;

}

U mnie to nie śmiga ... w dodatku działa wolno.. do ściągnięcia kodu strony używam biblioteki CURL, zawartość pliku przekierowuje do stringa ,no a dalej chce wyświetlić dane dopasowane pod wzorzec

Czu umiecie mi wyjaśnić co to za typ danych smatch i czemu wynik dopasowania muszę wyświetlić z indexem 0 [0]?

0

Jedno zaznaczenie. To tylko prosty przykład i nie działa dla zagnieżdżonych znaczników.
Czyli zadziała dla

<div>cokolwiek</div>

ale dla

<div> cos <div> cos2 </div></div> 

Wytnie nie tak jak trzeba.
Smatch to klasa przechowująca dopasowania. W kolejnych polach tej klasy (do których masz dostęp za pomocą operatora[]), są umieszczone dane po dopasowaniu kolejno po nawiasach ze wzorca.

0

Okej , zatem zapytam już bezpośrednio Ciebie :) . Czy wiesz lub masz jakąś koncepcję jak to ugryźć ;)?

0
pain368 napisał(a):

Okej , zatem zapytam już bezpośrednio Ciebie :) . Czy wiesz lub masz jakąś koncepcję jak to ugryźć ;)?

Dostałeś rozwiązanie na tacy.

Teraz robisz sobie graf jak w javascript DOM,
Rekurencyjnie wewnątrz znacznika szukasz znacznika, jak najgłębiej znajdzie, jak regex nie znajdzie, to masz koniec odnóża grafu, wracasz wyżej i szukasz dalej.
Aż do przeczesania dokumentu.

0

Okej , przepraszasz :) .Myślałem że jest jakiś inny sposób .. wolałem się upewnić .. zatem działam !!!

0

Hej , zrobiłem wczoraj mapę tej strony i wygląda ona tak :)

string kodHTML="<html>\
                            <body>\
                                <div>\
                                <p>\
                                    <table>\
                                        <tbody>\
                                            <tr>\
                                                <td>\
                                                    <img>ikona flagi państwa</img>\
                                                <\td>\
                                              <td>Dolar<td>usd<td>kurs/sprzedaz<td>kurs/skup\  
                                            </tr>\
                                        </tbody>\
                                    </table>\
                                </p>\
                                </div>\
                            </body>";

I tu mam pytanie.. dziwi mnie fakt że znaczniki w kodzie strony nie są zamykane ,mam na myśli linie w której jest kolejno: Dolar,usd,kurs/sprzedaż,kurs/skup(oczywiście dwa ostatnie to liczby typu float)

Sprawdzałem dokładnie w Np++ ,ale nie znalazłem żadnego domknięcia .

Chwilowo muszę spróbować dopasować wyrażenie pod ten szablon , potem będę robił to już pod stroną z której pobierałem kod źródłowy .
Pytanie co do tego szablonu .. Czy znak \ jest widoczny dla wyrażenia regularnego ,czy tylko jest traktowany jak coś typu end of line

0

HTML nie jest językiem regularnym, więc nie da się go sparsować wyrażeniami regularnymi (ktoś tu już pokazywał problem z zagnieżdżonymi znacznikami). Trzeba użyć odpowiedniej biblioteki, która sparsuje tekst do drzewa DOM, np. https://github.com/lexborisov/myhtml

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