Autor |
Beitrag |
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 07.02.14 18:20
Hallo!
Gibt es eine vorgefertigte Methode, den reinen Text ohne HTML-Formatierung zu extrahieren, wenn ich TIdHTTP verwende? Bisher mache ich das manuell.
Delphi-Quelltext 1: 2: 3:
| s := IdHTTP1.Get(... |
So enthält die Variable s einfach den HTML-Code, ich brauche aber nur den reinen Textstring!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
Beiträge: 19276
Erhaltene Danke: 1741
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 07.02.14 18:25
Dafür brauchst du einen HTML-Parser. Eine Möglichkeit ist der, der bei Windows dabei ist:
stackoverflow.com/a/14349613
(also via IHTMLDocument2)
Oder auch eigene Implementierungen:
htmlp.sourceforge.net/
Für diesen Beitrag haben gedankt: galagher
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 07.02.14 19:42
Komme nicht damit zurecht! Da ist HTML ja eine Konstante, ich muss also eine Sringvariable mit dem HTML-String füllen und das dann auswerten. Da kommt aber weder LABEL noch SPAN vor.
Möchte andererseits nichts installieren.
Da bleib ich lieber bei meinem selbstgeschriebenen Code.
//Edit: Was nicht heissen soll, dass ich nicht doch noch gerne Vorschläge und Tipps annehmen möchte!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
Beiträge: 19276
Erhaltene Danke: 1741
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 07.02.14 20:09
galagher hat folgendes geschrieben : | Komme nicht damit zurecht! Da ist HTML ja eine Konstante, ich muss also eine Sringvariable mit dem HTML-String füllen und das dann auswerten. Da kommt aber weder LABEL noch SPAN vor. |
In der Konstante mit dem Beispiel kommen doch die Tags label und span vor, und dieser Beispieltext wird in das HTML-Dokument geschrieben und dann über die Tags ausgelesen.
Wenn du das Beispiel ausführst, wird genau Name: und Value ausgegeben, so wie es auch in dem Beispiel in den Tags label und span drin ist. Probier es doch einfach aus, das funktioniert bei mir 1:1 kopiert problemlos.
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 07.02.14 20:17
jaenicke hat folgendes geschrieben : | Wenn du das Beispiel ausführst, wird genau Name: und Value ausgegeben, so wie es auch in dem Beispiel in den Tags label und span drin ist. Probier es doch einfach aus, das funktioniert bei mir 1:1 kopiert problemlos. |
Ja, das schon, aber das ist doch ein Beispiel, in dem "HTML" eine Konstante mit HTML-Code ist.
Will man dieses Beispiel einsetzen, muss man also stattdessen eine Variable mit dem HTML-Code befüllen, den man parsen will. Das klappt aber nicht, weil ich nicht weiss, was ich anstelle von 'LABEL', 'tvLabel', 'SPAN' und 'tvValue' angeben muss.
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
Beiträge: 19276
Erhaltene Danke: 1741
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 07.02.14 20:41
Das kann dir niemand sagen ohne den Quelltext der Seite zu kennen, um die es geht. Du kannst mir ein Beispiel auch per PN schicken, wenn du es hier nicht posten möchtest.
Du nimmst die Seite aber doch im Moment selbst auseinander. Da musst du doch wissen in welchen Tags der Inhalt steht, um den es dir geht.
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 07.02.14 21:11
jaenicke hat folgendes geschrieben : | Das kann dir niemand sagen ohne den Quelltext der Seite zu kennen, um die es geht. |
Es ist Text aus der Wikipedia, da brauche ich immer nur den ersten Satz. Ich lese also den gesamten HTML-Text ein, parse, bis ich den puren Text habe, suche dann die Position des ersten Punktes und schneide mit Copy ab.
Am Besten wäre natürlich ein Befehl wie HTMLToText. Das, was der tun soll, ist zwar auch, was ich jetzt mache, nur dachte ich, das gibt es vielleicht schon als fertige Methode.
Delphi-Quelltext 1: 2:
| s := IdHTTP1.Get(... sPureString := HTMLToText(s); |
Denn flexibel ist meine Methode nicht, da stecken viele hardgecodete Strings drin. Ich dachte, es gibt etwas Besseres!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
Beiträge: 19276
Erhaltene Danke: 1741
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 08.02.14 00:25
Ich hab mal kurz ein komplettes Beispiel dafür erstellt: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94:
| uses ActiveX, MSHTML, IdHTTP;
type IHtmlElementEnumerator = interface function GetEnumerator: IHtmlElementEnumerator; function GetCurrent: IHTMLElement; function MoveNext: Boolean; property Current: IHTMLElement read GetCurrent; end;
THtmlElementEnumerator = class(TInterfacedObject, IHtmlElementEnumerator) private var FEnum: IEnumVariant; FCurrent: IHTMLElement; function GetCurrent: IHTMLElement; function MoveNext: Boolean; public constructor Create(const AElements: IHTMLElementCollection); function GetEnumerator: IHtmlElementEnumerator; class function Enum(const AElements: IHTMLElementCollection): IHtmlElementEnumerator; end;
constructor THtmlElementEnumerator.Create(const AElements: IHTMLElementCollection); begin FEnum := AElements._newEnum as IEnumVariant; end;
class function THtmlElementEnumerator.Enum(const AElements: IHTMLElementCollection): IHtmlElementEnumerator; begin Result := THtmlElementEnumerator.Create(AElements); end;
function THtmlElementEnumerator.GetCurrent: IHTMLElement; begin Result := FCurrent; end;
function THtmlElementEnumerator.GetEnumerator: IHtmlElementEnumerator; begin Result := Self; end;
function THtmlElementEnumerator.MoveNext: Boolean; var CurrentElement: OleVariant; ElementCount: Cardinal; begin Result := FEnum.Next(1, CurrentElement, ElementCount) = S_OK; if Result then FCurrent := IUnknown(CurrentElement) as IHTMLElement else FCurrent := nil; end;
function GetFirstWikipediaParagraph(const AURL: String): String; var PageLoader: TIdHTTP; HtmlDocument: IHTMLDocument2; HtmlDocumentEx: IHTMLDocument3; PageContents: String; CurrentElement, ContentsElement, ParagraphElement: IHTMLElement; begin PageLoader := TIdHTTP.Create; try PageContents := PageLoader.Get(AURL); finally PageLoader.Free; end; HtmlDocument := CoHTMLDocument.Create as IHTMLDocument2; OleVariant(HtmlDocument).write(PageContents); HtmlDocument.close; while HtmlDocument.ReadyState <> 'complete' do Application.ProcessMessages; HtmlDocumentEx := HtmlDocument as IHTMLDocument3; for CurrentElement in THtmlElementEnumerator.Enum(HtmlDocumentEx.getElementsByTagName('sup')) do (CurrentElement as IHTMLDOMNode).removeNode(true); ContentsElement := HtmlDocumentEx.getElementById('mw-content-text'); ParagraphElement := (ContentsElement.children as IHTMLElementCollection).item(1, EmptyParam) as IHTMLElement; Result := ParagraphElement.innerText; end;
ShowMessage(GetFirstWikipediaParagraph('http://de.wikipedia.org/wiki/Topinambur')); | Den THtmlElementEnumerator bräuchte man natürlich nicht, aber es ist damit praktischer.
Für diesen Beitrag haben gedankt: galagher
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 08.02.14 13:25
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 08.02.14 14:15
Jetzt ist ein neues Problem aufgetaucht: Manchme Sätze enden mit einem Doppelpunkt. Wie muss ich deinen Code ändern, damit er beides, Punkt und Doppelpunkt, erkennt?
Als Beispiel de.wikipedia.org/wiki/Mers:
Zitat: | Mers ist der Name zweier Gemeinden in Frankreich:
Mers-les-Bains, Gemeinde im Département Somme
Mers-sur-Indre, Gemeinde im Département Indre
|
Hier kann ich schon "Mers ist der Name zweier Gemeinden in Frankreich:" als Satz gebrauchen.
//Edit: Bin schon an der Lösung dran!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
Beiträge: 19276
Erhaltene Danke: 1741
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 08.02.14 22:32
Dann so: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| function GetFirstWikipediaParagraph(const AURL: String): String; var PageLoader: TIdHTTP; HtmlDocument: IHTMLDocument2; HtmlDocumentEx: IHTMLDocument3; PageContents: String; CurrentElement, ContentsElement, ParagraphTestElement: IHTMLElement; ContentsElementChildren: IHTMLElementCollection; i: Integer; begin PageLoader := TIdHTTP.Create; try PageContents := PageLoader.Get(AURL); finally PageLoader.Free; end; HtmlDocument := CoHTMLDocument.Create as IHTMLDocument2; OleVariant(HtmlDocument).write(PageContents); HtmlDocument.close; while HtmlDocument.ReadyState <> 'complete' do Application.ProcessMessages; HtmlDocumentEx := HtmlDocument as IHTMLDocument3; for CurrentElement in THtmlElementEnumerator.Enum(HtmlDocumentEx.getElementsByTagName('sup')) do (CurrentElement as IHTMLDOMNode).removeNode(true); ContentsElement := HtmlDocumentEx.getElementById('mw-content-text'); ContentsElementChildren := ContentsElement.children as IHTMLElementCollection; Result := ''; for i := 0 to ContentsElementChildren.length - 1 do begin ParagraphTestElement := ContentsElementChildren.item(i, EmptyParam) as IHTMLElement; if AnsiSameText(ParagraphTestElement.tagName, 'p') then begin Result := ParagraphTestElement.innerText; Break; end; end; if Result = '' then Result := ContentsElement.innerText; end; |
Für diesen Beitrag haben gedankt: galagher
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 09.02.14 12:41
Mit ein bisschen Umbau klappt es jetzt!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 10.02.14 21:59
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
Beiträge: 19276
Erhaltene Danke: 1741
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 10.02.14 23:15
Ach du Schande, einen TWebBrowser zu missbrauchen ist... ähm... ich sag mal freundlich ungünstig. Da kannte sich der Autor leider nicht aus. Den Code dort kannst du genauso rein mit dem IHTMLDocument2 Interface aus dem CoHTMLDocument machen wie in meinem Code.
// EDIT:
Ach ja, und das createTextRange kann man sich meines Erachtens auch sparen, es reicht innerText des Body-Elements, wenn man den kompletten Text möchte. Aber es wäre ja Schwachsinn den hinterher zu parsen, wenn man wie in deinem Fall nur einen bestimmten Teil braucht.
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Di 11.02.14 18:22
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
jaenicke
Beiträge: 19276
Erhaltene Danke: 1741
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 11.02.14 18:55
Ja, genau.
Aber ich dachte du brauchst gar nicht den kompletten Text der Seite?
|
|
galagher
Beiträge: 2510
Erhaltene Danke: 44
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Di 11.02.14 19:14
jaenicke hat folgendes geschrieben : | Ja, genau.
Aber ich dachte du brauchst gar nicht den kompletten Text der Seite? |
Diesen Code will ich auch meiner Sammlung hinzufügen!
Für das aktuelle Projekt brauche ich tatsächlich nur die erste Zeile, nochmals danke für deinen Code dafür!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
|