Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Delphi - Jak przekształcić tabelę HTML na tekst?

leburaque 28 Sie 2013 17:19 1614 7
  • #1 28 Sie 2013 17:19
    leburaque
    Poziom 17  

    Witam.

    Mam kilka tabelek w HTML'u i chciałbym je przekształcić na tekst. Czy znacie jakieś sposoby, procedury, albo implementacje, które pozwalają na taki zabieg?

    Z góry dziękuję za każdą wskazówkę.

    Dodam do siebie tylko, że próbowałem usunięcia tagów HTML, dzięki prostej procedurze znalezionej tu: http://stackoverflow.com/questions/3001443/get-the-rendered-text-from-html-delphi niemniej nie chodzi mi o usunięcie tych tagów, a o jakieś pozostawienie układu danych w tabeli html...

    Pozdrawiam

    Dodano po 18 [minuty]:

    Może być też opcja konwersji do dowolnego formatu tekstowego, np. CSV, żebym po prostu wiedział od czego zacząć.

    0 7
  • #3 29 Sie 2013 00:27
    leburaque
    Poziom 17  

    Zacząłem od modyfikacji tego znalezionego ekstraktora do tagów. Ale modyfikacja programu polega na kilku rzeczach. Po pierwsze wczytuję cały plik HTML do jednego stringa, usuwając przy tym wszelakie entery i znaki końca wiersza, by wyjściowy CSV miał entery tylko po tagach.

    Następnie jeśli program odczytuje znaki "w tagu" to sprawdza, czy nie jest to TR albo TD - wówczas przypisuje odpowiednio enter lub średnik do wyjściowego stringa, a jeśli TR lub TD poprzedza "/" to nie robi nic.

    Czy da się to jakoś ładniej wykonać? I czy to wczytanie do stringa większej ilości znaków niż 255 nie robi problemu?

    Kod: delphi
    Zaloguj się, aby zobaczyć kod

    0
  • #4 29 Sie 2013 14:22
    leburaque
    Poziom 17  

    Zmodyfikowałem kod.

    Teraz program wykrywa, czy niektóre z komórek w tabeli nie są przypadkiem scalone. Jeśli tak - rozszerza następne komórki, tak, aby zgadzały się początki skrajów tabeli. W tym celu posłużyłem się po prostu sprawdzeniem, czy gdzieś tam nie ma ROWSPAN i COLSPAN, a jeśli jest to odpowiednią ilość średników doda program.

    Poprawiłem też znak końca linijki z #13 na #13#10

    Kod: delphi
    Zaloguj się, aby zobaczyć kod


    I to już działa pięknie. Pojawił mi się jednak problem z konwersją polskich znaków z HTML do zwykłego tekstu. Otrzymuję dokument w formacie UTF-8, więc nie mam polskich znaków normalnie widocznych, tylko po prostu ślaczki wynikające z UTF-8.

    Myślę zatem nad konwersją i tego.

    Mam tabelę polskich znaków wraz z ich kodowaniem w HTML. Dla literki "ć" przysługuje numer 263. Nie mam pomysłu jednak jak posłużyć się poleceniem

    Result := StringReplace(Result, szukana, polskaliterka, [rfReplaceAll]);

    abym znalazł taki kod jak ć. Próbowałem konwertować tę wartość do postaci hex, czyli np. C4 87. Ord od tych dwóch znaków mi zwraca odpowiednio 196 135. Czyli zgadza się, ale nie wiem jak mam sobie policzyć &#263 -> hex, dec, albo cokolwiek? Nie rozumiem jak to dwuznakowe kodowanie się zapisuje do postaci dec. Nie mogę tego ogarnąć, a nad tym siedzę...

    0
  • Pomocny post
    #5 29 Sie 2013 19:46
    Dżyszla
    Poziom 42  

    A jakiej wersji Delphi używasz? Jeśli >= 2010 to nie ma problemu z funkcją bodajże Utf8ToAnsi.

    Ponadto na 100% od XE2 są też wyrażenia regularne, które by znacznie ułatwiły usuwanie tagów :)

    0
  • #6 30 Sie 2013 11:10
    leburaque
    Poziom 17  

    Wszystko działa! Używam wprawdzie wersji 10.00 (2005), ale jest ta funkcja i jest w pełni obsługiwana.

    Zatem w finalnej wersji posłużyłem się na końcu funkcji nie:

    Kod: delphi
    Zaloguj się, aby zobaczyć kod


    Kod: delphi
    Zaloguj się, aby zobaczyć kod


    I wszystko jest w jak najlepszym porządku.

    Poza tym, ponieważ wczytuję czasem długie bloki tekstu zmieniłem String'i na AnsiString, które pozwala wczytać blok tekstu do (właściwie) 2 GB.

    Dżyszlo, Twoja pomoc jest jak zawsze nieoceniona!

    Został mi ostatni problem, może zabrzmieć głupio. W html'u mam czasem odwołania do innego pliku. Bez problemu je (tzn. ścieżki plików) wyciągam z kodu i wczytuję. Problem w tym, że się posługuję wskaźnikiem P który wskazuje mi na miejsce w pamięci w którym mam AnsiString'a. Czy jeśli coś wstawię w tego AsniStringa to jest to działanie na pamięci, zatem wstawienie czegoś za wskaźnikiem sprawi, że będę mógł to przez wskaźnik odczytać? Bo jeśli tak, to wystarczy mi zwykła funkcja Insert chyba? Chodzi mi o coś takiego:

    Insert('WSTAWIONE', STRHTML, P + 1));

    Tu mi oczywiście wyrzuca dla P+1
    [Pascal Error] HTMLtoText.dpr(47): E2008 Incompatible types

    Może powinienem użyć Integer(P+1)? Czy jakoś inaczej?

    Wówczas (P+1)^ powinno mi wskazać "W", czyli pierwszą literę wstawionego bloku tekstu?

    Zaś co do wyrażeń regularnych - jeszcze przyjdzie na nie czas... ;)

    Dodano po 2 [godziny] 8 [minuty]:

    OK, doszedłem do tego, że funkcja Insert daje mi możliwość wstawienia czegoś w stringa, a wskaźnik wskazuje tylko miejsce w pamięci, więc wszystko gra i buczy. Mogę poprzez wskaźnik dalej analizowac tekst. Niemniej nie potrafię uzyskać punktu odniesienia... Już tłumaczę o co chodzi:

    Mam

    Kod: delphi
    Zaloguj się, aby zobaczyć kod


    Jeśli P zmieniło w trakcie działania programu swoją wartość poprzez Inc(P) i P^ wskazuje mi na 'B', to jak mogę zobaczyć o ile się P przesunęło?

    Sam wykombinowałem taki sposób: deklaruję dodatkowe

    PPoczatkowe,
    P: PChar;

    i na początku procedury

    P := PChar(T);
    PPoczatkowe := PChar(T);

    W ten sposób mam dwa wskaźniki.

    Potem różnica w potraktowanych integerem wskaźnikach daje mi o ile się to przesunęło:

    Insert('****', T, Integer(P) - Integer(PPoczatkowe) + 1);

    Czy to dobre podejście?

    0
  • Pomocny post
    #7 30 Sie 2013 17:50
    Dżyszla
    Poziom 42  

    @leburaque - ale String i AnsiString to to samo, z tego co pamiętam ;) (zobacz definicję tego drugiego).

    Dobre podejście :) Tylko nie jestem pewien, czy przypadkiem Insert nie zmieni położenia w pamięci... Znacznie bezpieczniej byłoby po takiej operacji na nowo ustawić P na pozycję wynikającą z poprzedniej + długość dodanego.

    0
  • #8 31 Sie 2013 13:00
    leburaque
    Poziom 17  

    Rzeczywiście, musiałem ponownie przydzielać po wycięciu adres wskaźnika poprzez

    P := PChar(strHTML);

    I wówczas wszystko pięknie zadziałało.

    Kod: delphi
    Zaloguj się, aby zobaczyć kod


    Załączam dwie funkcje - nie wiem, czy przydadzą się na gotowca, bo pewnie ktoś będzie potrzebował pozmieniać przynajmniej ścieżki dostępu do plików wczytywanych, ale może się komuś przyda.

    Pierwsza funkcja wczytuje plik tekstowy do AnsiStringa, druga ten AnsiString przekształca z HTML do tekstu z uwzględnieniem tabel i odczytu/konwesrsji takowych. Użyłem tu jednak tab'a (#9) a nie średnika, bo łatwiej mi się je wkleja do np. Excella potem. Jeśli program natrafi na tabelę zagnieżdżoną w innym pliku, to ją wczyta i wstawi do analizowanego AnsiStringa.

    Bardzo dziękuję Dżyszlo za wskazówki. Temat chyba jest do zamknięcia.

    0