aicher1998
Goto Top

GetElementByID von String ohne WebBrowser

Hallo,

Ich hab folgendes Problem:
Ich möchte von einer bekannten Webseite Werte auslesen. Jetzt möchte ich aber keinen WebBrowser verwenden, zum einen aus dem Grund, dass ich dann über Events schauen muss, ob die Seite fertig geladen hat und zum anderen - und das ist das komische - wenn ich mit einem Browser, der nicht IE heißt, den QuellCode aufruf, dann findet man zum Beispiel den Code
<div id="w1-16-_mtb" class="notranslate u-flL bid-note">Geben Sie mehr als EUR 41,00 ein</div>  

Wenn ich allerdings von der gleichen Seite den QuellCode mittels IE oder dem WebClient hole, siehts auf einmal so aus:
<div id="w1-15-_mtb" class="notranslate u-flL bid-note">Geben Sie mehr als EUR 41,00 ein</div>  

Das nervt furchtbar, da ich so nicht einfach im Google Chrome über "Element untersuchen" den richtigen HTML-Tag (also das Element) raussuchen kann, aber egal, das ist ja erst mal nicht meine Frage...

Ich suche schon länger eine Möglichkeit wie ich aus einem String ein HtmlDocument machen kann ohne den Umweg über einen WebBrowser. Also in etwas so:
Function StringToHtml(ByVal s As String) As HtmlDocument

Im Grunde würde es mir reichen, wenn ich auf folgendes zugreifen kann:
  • GetElementByID
  • GetElementByClassName

Wie mach ich das?

Hier hatte jemand das gleiche Problem, es wurde aber leider nicht gelöst. das was der dortige Fragesteller möchte, ist genau das was ich möchte.

//EDIT
So, wollte ich es eigentlich nicht machen:
 Public Shared Function HtmlDocumentFromString(ByVal sSource As String) As HtmlDocument
        Using w As New WebBrowser With {.Url = New Uri("about:blank"), .ScriptErrorsSuppressed = True}  
            Dim doc As HtmlDocument = CType(w.Document, HtmlDocument) : doc.OpenNew(True) : doc.Write(sSource)
            Return w.Document
        End Using
    End Function

Es wäre super, wenn mir da jemand auf die Sprünge helfen könnte (eine externe DLL kommt leider nicht in Frage).

Gruß Chris

Content-ID: 294843

Url: https://administrator.de/contentid/294843

Ausgedruckt am: 22.11.2024 um 01:11 Uhr

126919
126919 01.02.2016 aktualisiert um 14:32:45 Uhr
Goto Top
Cherio,
Wenn ich allerdings von der gleichen Seite den QuellCode mittels IE oder dem WebClient hole, siehts auf einmal so aus:
Logisch, eine Webseite kann den Useragent auswerten und entsprechend eine Seite anders formatieren oder entsprechende Klassen hinzufügen. Den Useragent kann man bei einem WebRequest etc. auch angeben.

Im Grunde würde es mir reichen, wenn ich auf folgendes zugreifen kann:
GetElementByID
GetElementByClassName
Wie mach ich das?
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim html As HtmlDocument = StringToHTML("<html><body><p id=""TestID"">Das ist ein Test</p><body></html>")  
        Dim obj As HtmlElement = html.GetElementById("TestID")  
        MsgBox(obj.innerText)
    End Sub
    Function StringToHTML(s As String) As HtmlDocument
        Dim wb As New WebBrowser
        wb.Navigate("about:blank")  
        Dim htdoc As HtmlDocument = wb.Document.OpenNew(True)
        htdoc.Write(s)
        Return htdoc
    End Function
End Class
fk
VMWare , Silicon Valley
Aicher1998
Aicher1998 01.02.2016 um 14:39:17 Uhr
Goto Top
Zitat von @126919:

Cherio,
Wenn ich allerdings von der gleichen Seite den QuellCode mittels IE oder dem WebClient hole, siehts auf einmal so aus:
Logisch, eine Webseite kann den Useragent auswerten und entsprechend eine Seite anders formatieren oder entsprechende Klassen hinzufügen. Den Useragent kann man bei einem WebRequest etc. auch angeben.
Nein, daran lag es nicht, ich hatte den UserAgent von Chrome mitgeschickt, deshalb wundert mich das ja auch.

Im Grunde würde es mir reichen, wenn ich auf folgendes zugreifen kann:
GetElementByID
GetElementByClassName
Wie mach ich das?
> Public Class Form1
>     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
>         Dim html As HtmlDocument = StringToHTML("<html><body><p id=""TestID"">Das ist ein Test</p><body></html>")  
>         Dim obj As HtmlElement = html.GetElementById("TestID")  
>         MsgBox(obj.innerText)
>     End Sub
>     Function StringToHTML(s As String) As HtmlDocument
>         Dim wb As New WebBrowser
>         wb.Navigate("about:blank")  
>         Dim htdoc As HtmlDocument = wb.Document.OpenNew(True)
>         htdoc.Write(s)
>         Return htdoc
>     End Function
> End Class
> 

Danke, genau den Code hatte ich auch schon, aber ich wollte eigentlich keinen WebBrowser verwenden.
Meine Version sieht wie folgt aus:
 Public Shared Function HtmlDocumentFromString(ByVal sSource As String) As HtmlDocument
        Using w As New WebBrowser With {.Url = New Uri("about:blank"), .ScriptErrorsSuppressed = True}  
            Dim doc As HtmlDocument = CType(w.Document, HtmlDocument) : doc.OpenNew(True) : doc.Write(sSource)
            Return w.Document
        End Using
    End Function

Aber ich glaub, ich werds jetzt dich mal bei dem HtmlDocumentFromString belassen, das wird die einfachste Möglichkeit sein... Aber ist das sauber??

Gruß Chris
126919
126919 01.02.2016 aktualisiert um 14:41:20 Uhr
Goto Top
Aber ist das sauber??
Warum nicht, wenns funktioniert und macht was es soll ...
Aicher1998
Aicher1998 01.02.2016 um 14:45:11 Uhr
Goto Top
Zitat von @126919:

Aber ist das sauber??
Warum nicht, wenns funktioniert und macht was es soll ...
Aha, also wenns funktioniert, ist es sauber?

Das hier
MsgBox("Hallo" + "Das ist ein Text")  
funktioniert auch perfekt (wenn Option Strict aus ist), ist aber sehr unprofessionell.
126919
126919 01.02.2016 aktualisiert um 14:48:50 Uhr
Goto Top
Dann schreib dir halt deine eigenen Klassen und HTML-Parser vielleicht genügts dir ja dann ...
Btw. mit Regex lässt sich alles extrahieren da braucht es kein Dummie-HTMLDocument ...
Aicher1998
Aicher1998 01.02.2016 um 14:51:54 Uhr
Goto Top
Zitat von @126919:

Dann schreib dir halt deine eigenen Klassen und HTML-Parser vielleicht genügts dir ja dann ...
Btw. mit Regex lässt sich alles extrahieren da braucht es kein Dummie-HTMLDocument ...
So zum Beispiel:
<(.*)?id="1234"(\s.*)?>(?<content>(.*)?)<\/(.*)>  


Ist das professionell? Oder kann es da Probleme geben?
126919
126919 01.02.2016 aktualisiert um 14:56:58 Uhr
Goto Top
Kommt drauf an was du genau extrahieren willst. Kenne den Inhalt deines Files ja nicht.
Aicher1998
Aicher1998 01.02.2016 um 15:03:11 Uhr
Goto Top
Naja
<(.*)?id="1234"(\s.*)?>(?<content>(.*)?)<\/(.*)>  

Sollte doch allgemein funktionieren oder?
Außer halt bei Felder ohne dem schließenden tag aber das lässt sich ja noch schnell ändern
126919
126919 01.02.2016 aktualisiert um 15:07:22 Uhr
Goto Top
Zitat von @Aicher1998:
Sollte doch allgemein funktionieren oder?
Außer halt bei Felder ohne dem schließenden tag aber das lässt sich ja noch schnell ändern
Wenn es um verschachtelte Tags (HTML in HTML-Tag) geht dann nicht face-wink

http://htmlagilitypack.codeplex.com/
Aicher1998
Aicher1998 01.02.2016 um 15:14:58 Uhr
Goto Top
Zitat von @126919:

Zitat von @Aicher1998:
Sollte doch allgemein funktionieren oder?
Außer halt bei Felder ohne dem schließenden tag aber das lässt sich ja noch schnell ändern
Wenn es um verschachtelte Tags (HTML in HTML-Tag) geht dann nicht face-wink
Wieso nicht?
.*
repräsentiert doch jedes Zeichen beliebig oft oder?

Ich möchte keine DLLs benutzen und noch dazu, schaut mir das etwas zu überqualifiziert aus, für das was ich machen möchte....
114757
114757 01.02.2016 aktualisiert um 15:24:42 Uhr
Goto Top
Moin,
Wieso nicht?
@126919 hat recht.

Beispiel:
Du willst den gesamten HTML-Inhalt des DIVs mit der ID outer erfassen, dann wird dein Regex beim schließenden Tag DIV mit der ID inner aufhören und den Text "Noch mehr Text" nicht mit erfassen face-wink
<div id="outer">  
 	Outertext
 	<div id="inner">InnerText</div>  
 	Noch mehr Text
 </div>
Gruß jodel32
Aicher1998
Aicher1998 01.02.2016 um 15:35:30 Uhr
Goto Top
ach ja stimmt.
Wie mach ich das dann?
114757
114757 01.02.2016 aktualisiert um 15:37:35 Uhr
Goto Top
Eigenen HTML-Parser schreiben oder mit mshtml arbeiten, das gibt's auf jedem Windows.