Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1688to1692
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

GetAttribute

GetAttribute
05.05.2019 23:10:55
Marc
Guten Abend liebe Forumsgemeinde,
ich versuche mal wieder einer Webseite einen Wert innerhalb der Dom-Struktur zu entlocken. Was eigentlich ganz simpel sein dürfte klappt bislang aber nicht so wie ich es mache.
Das ist das Element in der Dom-Struktur, welchem ich den innerText (75,67) entnehmen möchte:
 *span class="Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)" data-reactid="34">75,67

Da der Wert des data-reactid Attributs die eindeutigste Referenz in diesem Element darstellt möchte ich dieses referenzieren um an den innerText zu kommen.
Das ist mein Code: (Eine Fehlermeldung bekomme ich nicht, aber meine Varibale currPrice bleibt leer.)

IE.navigate "https://de.finance.yahoo.com/quote/BMW.DE"
Do
DoEvents
Loop Until IE.readyState = 4
Dim currPrice As String
Dim HTMLDoc3 As MSHTML.HTMLDocument
Dim dColl As MSHTML.IHTMLElementCollection
Dim dTag As MSHTML.IHTMLElement
Set HTMLDoc3 = IE.Document
Set dColl = HTMLDoc3.getElementsByTagName("span")
For Each dTag In dColl
If dTag.getAttribute(" data-reactid").Value = "34" Then currPrice = dTag.innerText
Next dTag

12
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: GetAttribute
06.05.2019 10:16:58
Zwenn
Hallo Marc,
nimm mal das .Value in der Zeile weg, in der Du auf das Attribut prüfst.
Viele Grüße,
Zwenn
AW: GetAttribute
06.05.2019 17:11:59
Marc
Hallo Zwenn,
vielen Dank. Ich habe es mit folgenden beiden Varianten versucht aber leider erfolglos:
If dTag.getAttribute(" data-reactid") = 34 Then currPrice = dTag.innerText
If dTag.getAttribute(" data-reactid") = "34" Then currPrice = dTag.innerText

AW: GetAttribute
06.05.2019 22:05:38
Zwenn
Hallo Marc,
ich hatte schon gesehen, dass es noch einen anderen Fehler gibt, aber ich war nicht sicher, ob Du nochmal antwortest. Die Angabe des Attributes stimmt nicht ;-) Es heißt nicht " data-reactid" sondern " data-reactid=". Der Wert ist im HTML-Quelltext in Anführungszeichen eingeschlossen, deshalb muss die Zeile so lauten:
If dTag.getAttribute(" data-reactid=") = "34" Then currPrice = dTag.innerText

Soooo, nun hast Du geschrieben, der eindeutige Identifikator ist das Attribut. Darüber kann man es zwar eindeutig machen, aber Du brauchst die Schleife dafür, weil man auf Attribute nicht direkt zugreifen kann, wenn man eine Menge von Möglichkeiten hat. Es gibt aber auch die Methode getElementsByClass() und die CSS-Klasse Deines gesuchten Span-Tags "Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)" ist sogar einmalig im ganzen HTML-Quelltext. Du kannst also direkt auf die richtige Stelle zugreifen mit:
dColl = HTMLDoc3.getElementsByClassName("Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)")(0)

Ich machs mal kurz als kleines Makro, damit klar wird, wie Du den Wert direkt über den IE abgreifen kannst. Ich verwende late binding, weshalb ich mit Objekt-Variablen arbeite, statt mit dem MSHTML-Gerümpel, für das ein Verweis gesetzt werden muss. Damit kann so ein Makro auf jedem Rechner unter Excel direkt verwendet werden, ohne einen Verweis setzen zu müssen (Ich habe auch mal die Variablen-Deklarationen nach vorne gesetzt, wo sie hingehören):

Sub AktienPreisVonYahooHolen()
'Für den Internetzugriff
Dim browser As Object
Dim url As String
Dim knotenWurzel As Object
Dim aktienPreisErmittelt As String
'URL als Variable, um direkt eine Schleife über
'mehrere Aktienkurse zu ermöglichen
url = "https://de.finance.yahoo.com/quote/BMW.DE"
'Internet Explorer initialisieren, Sichtbarkeit festlegen,
'URL aufrufen und warten bis Seite vollständig geladen wurde
Set browser = CreateObject("internetexplorer.application")
browser.Visible = False
browser.Navigate url
Do Until browser.ReadyState = 4: DoEvents: Loop
'Die Seite läd den "inneren Teil" nach. Also braucht es mehr Zeit (ggf. anpassen)
'Application.Wait (Now + TimeValue("Pause Stunden:Pause Minuten:Pause Sekunden"))
Application.Wait (Now + TimeValue("00:00:01"))
'Richtiges HTML-Element direkt abgreifen
Set knotenWurzel = browser.document.getElementsByClassName _
("Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)")(0)
If Not knotenWurzel Is Nothing Then
'Wenn es das Element gibt
aktienPreisErmittelt = Trim(knotenWurzel.innerText)
Else
'Wenn es das Element nicht gibt
aktienPreisErmittelt = "Es konnte kein Preis ermittelt werden."
End If
'Ausgabe des Ergebnisses
MsgBox aktienPreisErmittelt
End Sub

Viele Grüße,
Zwenn
Anzeige
Ups, Aufräumarbeiten vergessen
06.05.2019 22:11:04
Zwenn
Der Browser muss beendet werden, sonst hängt er unsichtbar im Arbeitsspeicher:

Sub AktienPreisVonYahooHolen()
'Für den Internetzugriff
Dim browser As Object
Dim url As String
Dim knotenWurzel As Object
Dim aktienPreisErmittelt As String
'URL als Variable, um direkt eine Schleife über
'mehrere Aktienkurse zu ermöglichen
url = "https://de.finance.yahoo.com/quote/BMW.DE"
'Internet Explorer initialisieren, Sichtbarkeit festlegen,
'URL aufrufen und warten bis Seite vollständig geladen wurde
Set browser = CreateObject("internetexplorer.application")
browser.Visible = False
browser.Navigate url
Do Until browser.ReadyState = 4: DoEvents: Loop
'Die Seite läd den "inneren Teil" nach. Also braucht es mehr Zeit (ggf. anpassen)
'Application.Wait (Now + TimeValue("Pause Stunden:Pause Minuten:Pause Sekunden"))
Application.Wait (Now + TimeValue("00:00:01"))
'Richtiges HTML-Element direkt abgreifen
Set knotenWurzel = browser.document.getElementsByClassName _
("Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)")(0)
If Not knotenWurzel Is Nothing Then
'Wenn es das Element gibt
aktienPreisErmittelt = Trim(knotenWurzel.innerText)
Else
'Wenn es das Element nicht gibt
aktienPreisErmittelt = "Es konnte kein Preis ermittelt werden."
End If
'Ausgabe des Ergebnisses
MsgBox aktienPreisErmittelt
'Aufräumen
browser.Quit
Set browser = Nothing
Set knotenWurzel = Nothing
End Sub

Anzeige
AW: GetAttribute
07.05.2019 23:31:32
Marc
Hallo Zwenn,
ganz herzlichen Dank für Deine Unterstützung. Es wundert mich zwar, dass Du der Meinung bist das Gleich Zeichen gehöre zur Beschreibung des Attributs denn in der gesamten Zeile sind nur 4 Gänsefüßchen von denen zwei den ClassName umschließen und zwei aus meinser Sicht den Wert des Attributs, also "34" aber ich habe es natürlich versucht, leider erfolglos.
Mir ist natürlich bewusst, dass ich das Ganze auch über den ClassName machen kann aber tatsächlich ist es so, dass ich beide Varianten in den Code integrieren möchte, als Backup wenn Yahoo mal wieder ganz unvorhergesehen die Bezeichnungen ändert, was gelegentlich vorkommt, um es Webscrapern ein wenig schwerer zu machen.
Ich habe folgende Varianten probiert:
If dTag.getAttribute(" data-reactid=") = "34" Then currPrice = dTag.innerText
If dTag.getAttribute(" data-reactid=") = 34 Then currPrice = dTag.innerText
If dTag.children(0)getAttribute(" data-reactid=") = "34" Then currPrice = dTag.innerText
Es hat in keinem der Fälle funktioniert. Der IE wird natürlich in meinem Skript im Anschluss wieder deaktiviert. Da das Skript aber sehr umfangreich ist habe ich nur den Teil hier geposted der relevant ist.
VG,
Marc
Anzeige
AW: GetAttribute
08.05.2019 09:45:39
Zwenn
Hallo Marc,
da hatte ich wohl Tomaten auf den Augen. Du hast völlig recht, das Gleichheitszeichen gehört natürlich nicht zum Namen des Attributs. Der Fehler liegt genau auf der anderen Seite, nämlich vor dem Attributnamen.
Nachmal die Zeile, um die es geht:
<span class="Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)" data-reactid="34">

In dem span-Tag gibt es die CSS-Klasse und das Attribut. Beide sind durch ein Leerzeichen getrennt und das gehört natürlich nicht zum Namen des Attributs.
CSS-Klasse:
class="Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(ib)"

Attribut:
data-reactid="34"

Die richtige Zeile für Dein Macro muss also so aussehen:
If dTag.getAttribute("data-reactid=") = "34" Then currPrice = dTag.innerText

Ich habe mich durch den Aufbau des CSS-Klassennamen mit den Klammerausdrücken verwirren lassen und das schließende Anführungszeichen auch falsch zugeordnet. Wenn es so auch nicht klappt teste ich es selbst mit einem Beispielmakro.
Viele Grüße,
Zwenn
Anzeige
AW: GetAttribute
08.05.2019 09:54:54
Zwenn
Nein,
wie ausgeführt ohne das Gleichheitszeichen im Namen natürlich. Oh man, oh man ;-)
If dTag.getAttribute("data-reactid") = "34" Then currPrice = dTag.innerText

Viele Grüße,
Zwenn
AW: GetAttribute
08.05.2019 17:36:39
Marc
Hallo Zwenn,
da haben wir dann wohl beide Tomaten auf den Augen gehabt. :) Wie ich jetzt das Leerzeichen herausgenommen habe hat es dann endlich geklappt. :)
Vielen Dank! ;)
AW: GetAttribute
08.05.2019 20:16:42
Marc
Hallo Zwenn,
ich habe gerade festgestellt, dass die Trim-Funktion nicht funktioniert in Deinem kleinen Beispiel Makro insofern, dass der Wert als Text in die Zielzelle übernommen wird.
Ich habe es schon versucht mit Replace aber es hat nicht geholfen.
Hast Du einen Tipp?
VG,
Marc
Anzeige
AW: GetAttribute
08.05.2019 20:32:43
Marc
Ich habe soeben eine recht einfache Lösung gefunden, die manch anderen Anfänger vielleicht auch interessieren könnte.
Man teile den Wert in der Zelle einfach durch 1 dann wird das Format automatisch umgewandelt in Zahlenformat. (Multiplizieren geht vermutlich auch.)
VG,
Marc
AW: GetAttribute
08.05.2019 22:23:04
Zwenn
Hallo Marc,
Trim() sorgt lediglich dafür, dass führende und schließende Leerzeichen entfernt werden. Der Wert, der übrig bleibt ist ein String, weil die Variable aktienPreisErmittelt in der er steht vom Datentyp String ist.
Für die Umwandlung zu einem Datentyp, der eine Zahl repräsentiert, gibt es zwei Möglichkeiten. Eine hast Du schon selbst genannt, nämlich eine mathematische Operation, die den Wert selbst nicht verändert. Es gibt jedoch auch Funktionen für diesen "Vorgang". Der "Vorgang" nennt sich type casting (sinngemäß Typ Umwandlung) und die gezielten Funktionen dafür findest Du hier:
http://docs.microsoft.com/de-de/office/vba/language/concepts/getting-started/type-conversion-functions
Für Deinen Fall willst Du eine Zeichenkette (String) in eine Zahl umwandeln. Du hast den intuitiven Weg genommen, womit sich der neue Datentyp automatisch ergibt. Wenn Du die Funktionen zur Umwandlung des Datentyps nimmst, musst Du wissen was Du machst. In Deinem Fall handelt es sich nämlich um eine Gleitkommazahl, also eine Zahl, in der es einen Nachkommaanteil gibt. Dafür eignet sich die Funktion CDbl(). Um einen String in einen Double-Wert umzuwandeln, würde man also schreiben:
variableVomDatentypDouble = CDbl(zahlImStringFormat)

So wie Du es gemacht hast kommt aber genau das Gleiche raus. Über die Funktionen kann man aber gezielt Datentypen umwandeln und sei es nur zur Übung um zu wissen, was man da eigentlich grade macht ;-) Wenn Du in Deinem Makro jedoch mit dem so gewonnenen Wert weiter arbeiten willst, brauchst Du auf jeden Fall eine Variable vom richtigen Datentyp und musst dann natürlich auch genau wissen, was Du da grade machst. Egal welchen der beiden Wege zum type casting du wählst.
Viele Grüße,
Zwenn
Anzeige
AW: GetAttribute
09.05.2019 21:15:03
Marc
Hallo Zwenn,
das ist genau das wonach ich eigentlich auch gesucht hatte um den String umzuwandeln aber ich wurde nirgends fündig. Kommt natürlich auch immer darauf an ob man den korrekten Suchbegriff wählt. Wenn ich mal wieder vor dem Problem stehe, und das wird hundertprozentig der fall sein, dann weiß ich ja jetzt was zu tun ist.
Ich danke Dir. ;)

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige