Frage von DasesColles, 134

C# Wie kann ich bestimmte Tags aus einem HTML Code auslesesn?

Hey Leute,

bin gerade auf ein Problem gestoßen beim Programmieren mit C#. Ich habe in meinem eingelesenen HTML Code den Tag

test

Wie kann ich genau diesen Taginhalt "test" in eine String Variable abspeichern?

Danke im Voraus für die Antwort,

DasesColles

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von CrystalixXx, 69

Auch hier hilft das HtmlAgilityPack. Einfach mal danach suchen.

Kommentar von CrystalixXx ,

Ich habe mal eben ein Beispiel geschrieben:

Dim webHtml As New HtmlAgilityPack.HtmlWeb
Dim webDocument As HtmlAgilityPack.HtmlDocument
Dim spanElements As HtmlAgilityPack.HtmlNodeCollection

webDocument = webHtml.Load("https://www.gutefrage.net/")
spanElements = webDocument.DocumentNode.SelectNodes("//span[@class='Button-text']")

If spanElements IsNot Nothing Then
For Each span In spanElements
Debug.WriteLine(span.InnerText)
Next
End If

Du kannst deine Span-Elemente mittels XPath ermitteln. Die dafür benötigte Methode ist "SelectNodes" oder - wenn du nur ein einziges Element haben willst - "SelectSingleNodes".

Kommentar von DasesColles ,

Danke für den Hinweis und den Code. Bei meinem Code bräuchte ich dann span[@class=message]

Sehe ich das richtig?

Kommentar von CrystalixXx ,

Ja, vergiß die Hochkomma nicht.

Kommentar von DasesColles ,

Kann ich den Html-Code auch aus einem webbrowser auslesen mit dem HtmlAgilityPack? Das wäre nämlich wichtig.

Kommentar von CrystalixXx ,

Ja.

Dim webDocument As New HtmlAgilityPack.HtmlDocument
Dim spanElements As HtmlAgilityPack.HtmlNodeCollection

webDocument.LoadHtml(WebBrowser1.DocumentText)
spanElements = webDocument.DocumentNode.SelectNodes("//span[@class='Button-text']")

If spanElements IsNot Nothing Then
For Each span In spanElements
Debug.WriteLine(span.InnerText)
Next
End If
Kommentar von DasesColles ,

Du hast mir ja den code immern in vb.net geschrieben, hab ihn bis jetzt zwar immer umschreiben können, jedoch bei der foreach schleife gibt es bei mir kein span sondern nur timespan und das ist ja nicht das was ich brauche. Was muss ich da bei C# hinschreiben?

Kommentar von CrystalixXx ,

Stimmt, sorry. So sollte es funktionieren.

HtmlAgilityPack.HtmlDocument webDocument = new HtmlAgilityPack.HtmlDocument();
HtmlAgilityPack.HtmlNodeCollection spanElements;

webDocument.LoadHtml(WebBrowser1.DocumentText);
spanElements = webDocument.DocumentNode.SelectNodes("//span[@class='Button-text']");

if (spanElements != null)
{
foreach (HtmlAgilityPack.HtmlNode span in spanElements)
{
Debug.WriteLine(span.InnerText);
}
}
Kommentar von DasesColles ,

Könntest du mir vielleicht noch erklären warum das 

"//span[@class='message']

heißen muss und nicht so wie in dem Html code

<SPAN class="message">

denn ich bekomme keine ausgabe, obwohl im HtmlCode das drin steht

Kommentar von CrystalixXx ,

Das ist XPath. XPath ist eine Abfragesprache und besitzt daher eine eigene Syntax. Kurz eläutert:

  • //span - wählt alle <span>-Elemente aus dem Dokument aus
  • [@class] - schränkt die Auswahl auf jene <span>-Elemente ein, die ein class-Attribut besitzen
  • ='message' - schränkt die Auswahl auf jene <span>-Elemente ein, die ein class-Attribut mit dem Wert message besitzen

Das wären dann genau deine von dir beschriebenen Elemente. Es gibt noch deutlich mehr Möglichkeiten um Einschränken zu treffen. Du kannst dich mal hier bei den Beispielen umsehen: https://msdn.microsoft.com/de-de/library/ms256086.aspx

Kommentar von DasesColles ,

Danke, aber warum macht der nach einer bestimmten Anzahl an Zeichen einen Zeilen Umbruch?

HtmlCode

<SPAN class="message">sehrsehrlangertext undnochvielmehrtexthier</SPAN>

aber als Ausgabe bekomm ich aber zwei Zeilen und zwar

sehrsehrlangertext                                undnochvielmehrtexthier

kann man das noch ändern?

Kommentar von CrystalixXx ,

Wahrscheinlich, weil der Umbruch auch so im HTML-Dokument vorhanden ist.

Du kannst aber auch im Nachhinein den Zeilenumbruch entfernen, wenn er dich stört. Dafür gibt es zum Beispiel die Replace-Funktion des String-Objektes. Das überlasse ich aber dir - immerhin willst du ja programmieren. Eine Suchmaschine deiner Wahl hilft dir dafür sicherlich auch. Viel Erfolg!

Kommentar von DasesColles ,

Danke für die ausführliche Hilfe. Jetzt funktioniert alles. Hab den Webbrowser einfach ein wenig größer gemacht. Danke vielmals.

Expertenantwort
von TeeTier, Community-Experte für programmieren, 74

HtmlAgilityPack ist vorzuziehen, aber bei so einer kleinen Aufgabe evtl. ein Overkill.

Nimm einfach alternativ einen Regulären Ausdruck:

Regex re = new Regex("<span class=\"message\">(.+?)</span>", RegexOptions.IgnoreCase);

string text = re.Match(html).Groups[1].Value

Der Quelltext der HTML-Seite muss dabei in der Variable "html" vorliegen. :)
Kommentar von TeeTier ,

Ach du meine Güte ... der WYSIWYG-Editor hier auf GF ist ja noch viel verbuggter, als ich befürchtet habe.

Was für ein Pfusch ... ><

Kommentar von DasesColles ,

Danke für die Antwort. Hat mir echt weiter geholfen. Danke vielmals.

Kommentar von DasesColles ,

Noch eine weitere Frage:
span class=message text /span kann öfter in dem Html Code vorkommen, jedoch nicht unbedingt mit "text" sondern auch z.B. "bla". Wie kann ich die verschiedenen "messages" in ein String[] schreiben?

Kommentar von CrystalixXx ,

Verwendet statt "re.Match" die Methode "re.Matches". Die gibt dir eine Collection aller gefundenen Übereinstimmungen zurück.

Wenn du willst, dann kannst du durch die Collection mit einer For Each Schleife iterieren und sie z.B. einer "List(Of String)" hinzufügen.

Kommentar von DasesColles ,

aber ich muss schon .Groups[1].Value weglassen oder? Sonst gibts einen Fehler

Kommentar von DasesColles ,

Kannst du mir da vllt ein Code-Beispiel schicken? Check grad nicht wie ich des mit re.Matches machen soll.

Kommentar von DasesColles ,

Hat sich erledigt. Trotzdem Danke.

Kommentar von DasesColles ,

Ok, ein Problem hab ich noch. Der Text in den Tags "Text" darf anscheinend nicht länger als 15 Zeichen sein. Kann man das irgendwie ändern?

Kommentar von CrystalixXx ,

Es werden beliebig lange Zeichenketten ausgewertet, da gibt es keine konkrete Begrenzung. Problematisch wird es aber, wenn das zugrundeliegende HTML-Format nicht wohlgeformt ist und Inline-Elemente verschachtelt werden, z.B. wenn ein span-Element innerhalb eines anderen span-Elementes vorliegt.

Kommentar von CrystalixXx ,

@TeeTier

Wenn du seinen letzten Kommentar anschaust, dann verstehst du vielleicht, wieso ich selten zu Regex rate, wenn es Alternativen gibt. :) Das Problem bei Regex ist häufig, dass nicht alle Bedingungen klar formuliert sind, weshalb das Pattern nicht gleich den Vorstellungen des Fragenden entspricht. Dann wuselt man immer ewig rum - ist eben schwierig. Aber immerhin ist Regex schnell in der Ausführung und Programmierung und auch kurz, man muss es nur verstehen.

Kommentar von GustavAT ,

Das HtmlAgilityPack ist auch bei so einer kleinen Anwendung kein Overkill, schließlich zielt es ja genau auf seine Problemstellung ab. Außerdem hat die Assembly eh nur ca. 132kb, was in meinen Augen jetzt nicht so extrem viel ist.

Btw. Html mit regex parsen ist nicht so optimal, siehe einen Artikel hierzu:

http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-se...

Kommentar von CrystalixXx ,

Kurz: Reguläre Ausdrücke können nur reguläre Sprachen parsen.(X)Html ist aber eine kontextfreie Sprache.

(Obwohl Regex auch bedingt zum Ziel führen kann...)

Antwort
von DasesColles, 72

Hier nochmal der tag ohne spitze Klammern

SPAN class="message" test /SPAN

Keine passende Antwort gefunden?

Fragen Sie die Community