AW: Nicht über eine txt, sondern direkt übers DOM
24.05.2017 15:49:34
Zwenn
Ich weiß, dass es funktioniert, weil ich es ausprobiert habe ;-)
Den Link hatte ich eigentlich wegen genau der von Dir nachgefragten Zeile angegeben. Aber seis drum, ich versuche es mal mit einem kurzen Abriss.
Das DOM (Document Object Model) ist in einer Baumstruktur organisiert. Genauer gesagt sind Webseiten als Baumstruktur organisiert, die den Regeln des DOM unterliegt. Unter anderem kann man direkt auf Elemente im Dokument des Browsers zugreifen. Dafür gibt es mehrere Möglichkeiten. Ich habe die Möglichkeit von zwei Get-Methoden verwendet.
GetElementsByClassName("CLASSNAME")
GetElementsByTagName("TAGNAME")
Mit GetElementsByClassName() spricht man direkt alle Elemente einer Seite an, die den in Klammern angegebenen CSS-Klassennamen haben. Die Elemente mit dem Klassennamen werden alle in einem Array abgelegt, das mit dem Index 0 beginnt. Ich habe in Deinem Seitenquelltext nachgesehen, in was für einem Codeblock der Wert steht, den Du auslesen willst. Dieser Block muss eindeutig identifizierbar sein und sollte einen möglichst kleinen Codeausschnitt einschließen.
In Deinem Fall gibt es die CSS-Klasse "fightResultsInner" und das genau ein einziges Mal auf der ganzen Seite. Deshalb habe ich hinter GetElementsByClassName("fightResultsInner") direkt (0) angegeben. Das ist der erste Index des gebildeten Arrays für alle Elemente mit dem Klassennamen "fightResultsInner". Wie gesagt, davon gibts nur eins, also muss der gesuchte Codeblock den Index 0 in unserem Array haben.
Zu diesem Zeitpunkt arbeiten wir nur noch auf dem Codeausschnitt:
(Alle Spitzen Klammenrn habe ich wegen der Darstellung gegen Eckige ausgetauscht)
[div class="fightResultsInner"]
[h1][em]riddersmurf gewinnt[/em][/h1][p]riddersmurf erbeutet [em]17[/em] Silber.[/p]
[p]riddersmurf erhält [em]1[/em] EP.[/p]
[p]legend erhält [em]1[/em] EP.[/p]
[div class="divider"] [/div]
[p]Schaden - Angreifer: [em]187[/em][/p]
[p]Schaden - Verteidiger: [em]0[/em][/p]
[/div]
Auch für diesen Abschnitt ist noch das DOM gültig. Deshalb habe ich den Code direkt weiter mit GetElementsByTagName("p")(0) eingegerenzt. Wie man sich jetzt leicht denken kann, wird hier ein Array aus allen Elementen mit dem Tag Namen "P" gebildet. Allerdings nur aus dem Codeblock, der vorher schon durch die Klassenauswahl begrenzt wurde. Du siehst hier die Begründung für meine Forderung weiter vorne, der entstehende Codeblock sollte möglichst eng um den gesuchten Wert liegen.
Wir bekommen also ein Array mit allen P-Tags:
[p]riddersmurf erbeutet [em]17[/em] Silber.[/p]
[p]riddersmurf erhält [em]1[/em] EP.[/p]
[p]legend erhält [em]1[/em] EP.[/p]
[p]Schaden - Angreifer: [em]187[/em][/p]
[p]Schaden - Verteidiger: [em]0[/em][/p]
Der von Dir gesuchte Wert befindet sich im ersten P-Tag, also im ersten Element unseres Arrays, mit dem Index 0. Nun habe ich nur auf dieses Element (0) noch einmal die Eingrenzung über den Tag-Namen angewendet. Diesmal auf den Tag "em".
Davon gibts wieder nur einen, weshalb nach GetElementsByTagName("em")(0) nur noch folgendes übrig bleibt:
[em]17[/em]
Auch dieser nun letzte Tag unterliegt den Regeln des DOM. Deshalb können wir auf seinen Inhalt mit der Methode Innertext zugreifen. Um zu prüfen, ob wir überhaupt einen Wert vorliegen haben, prüfen wir zunächst, ob das Object knotenAst wirklich gebildet werden konnte. Das machen wir mit dem komisch anmutenden Doppel-Negativ-Konstrukt:
If Not knotenAst Is Nothing Then
Wir fragen also, ob knotenAst nicht existiert, also Nothing ist und drehen das Ergebnis mit Not um. Auf diese Weise können wir entsprechend des Ergebnisses dieser Prüfung unseren Code weiter schreiben. Ich habe einfach zwei MsgBoxes verwendet. Du wirst sicherlich eine andere Verwendung für das Ergebnis haben.
Wie Du nun leicht sehen kannst, habe ich lediglich einen möglichen Weg gewählt, um an den Wert zu kommen. Du kommst genauso dran, mit der Zeile:
Set knotenAst = oIE.document.GetElementsByClassName("fightResultsInner")(0). _
GetElementsByTagName("em")(1)
Hier wird das zweite Array direkt aus den em-Tags gebildet. Der gesuchte Wert steht dann im zweiten Element des Arrays, das den Index 1 hat.
Ich hoffe das ist einigermaßen nachvollziehbar gewesen.
Wenn Der Aufbau der Seite sich ändert, muss das Makro angepasst werden. Deshalb empfehle ich Dir, prüfe mal ein paar verschiedene Ausgaben der Seite hinter deinem Link ab. Was steht z.B. im Quelltext, wenn gar kein Silber gewonnen wurde? Kann man auch Verlust machen? Wie wird der dargestellt? Kann "fightResultsInner" unter Umständen doch noch ein zweites Mal auftauchen, wenn ja wird das relevant, wenn es vor dem jetzigen ist. Denn dann wärst Du von vorn herein im falschen Codeabschnitt unterwegs (falscher Array Index).
Das klingt erstmal kompliziert. Diese Gedanken musst Du Dir aber nur einmal machen oder reagieren, wenn sich etwas ergibt, was Du vorher nicht gesehen hast. Ist das Ganze aber mal fertig, läuft das erfahrungsgemäß sehr stabil, weil sich Seitenstrukturen selten ändern.