2013-04-05 12 views
5

Dies ist mein erster Versuch, einen Elementwert mithilfe von HAP zu ermitteln. Ich erhalte einen Null-Objektfehler, wenn ich versuche, InnerText zu verwenden.HTML Agility Pack - Verwenden von XPath zum Abrufen eines einzelnen Knotens - Objektreferenz nicht auf eine Instanz eines Objekts festgelegt

die URL ich Schaben bin, ist: - http://www.mypivots.com/dailynotes/symbol/659/-1/e-mini-sp500-june-2013 Ich versuche, den Wert für die aktuelle Hoch vom Tag ändern Übersichtstabelle zu erhalten.

Mein Code ist am unteren Rand. Erstens möchte ich nur wissen, ob ich das richtig mache. Wenn ja, ist mein XPath-Wert dann einfach falsch?

Der XPath-Wert wurde mit einem Dienstprogramm namens htmlagility Helfer gefunden. Die Firebug-Version des XPath unten gibt auch den gleichen Fehler: - /html/body/div [3]/div/Tabelle/tbody/tr [3]/td/Tabelle/tbody/tr [5]/td [ 3]

Mein Code: -

WebClient myPivotsWC = new WebClient(); 
string nodeValue; 
string htmlCode = myPivotsWC.DownloadString("http://www.mypivots.com/dailynotes/symbol/659/-1/e-mini-sp500-june-2013"); 
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); 
doc.LoadHtml(htmlCode); 
HtmlNode node = doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[3]/div[1]/table[1]/tbody[1]/tr[3]/td[1]/table[1]/tbody[1]/tr[5]/td[3]"); 
nodeValue=(node.InnerText); 

Danke, Will.

Antwort

22

Sie können sich nicht auf Entwicklungswerkzeuge wie FireBug oder Chrome usw. verlassen, um den XPATH für die Knoten zu ermitteln, die Sie suchen, da der XPATH, der von solchen Tools gegeben wird, dem im Speicher befindlichen HTML DOM entspricht Das Html Agility Pack kennt nur das vom Server zurückgesendete Raw-HTML.

Was Sie tun müssen, ist visuell zu sehen, was zurückgeschickt wird (oder einfach eine Quelle anzeigen). Sie werden sehen, dass zum Beispiel kein TBODY-Element vorhanden ist. Also wollen Sie etwas Diskriminierendes finden und zB XPATH axes verwenden. Auch wenn Ihr XPATH, selbst wenn es funktionierte, nicht sehr resistent gegen Änderungen im Dokument wäre, müssen Sie etwas "stabiler" für das Scraping finden, um zukunftssicherer zu sein.

Hier ist ein Code, der scheint zu funktionieren:

HtmlNode node = doc.DocumentNode.SelectSingleNode("//td[@class='dnTableCell']//a[text()='High']/../../td[3]"); 

Das ist, was es tut:

  • ein TD-Element mit einem CLASS-Attribut auf 'dnTableCell' gefunden. Das // Token bedeutet, dass die Suche in der XML-Hierarchie rekursiv ist.
  • Suchen Sie ein A-Element, das einen Text (inneren Text) enthält, der gleich 'High' ist.
  • navigate zwei Eltern auf (wir zum nächsten TR-Element erhalten werden)
  • die 3. TD Element wählen von dort
+0

Dankhaufen, das funktioniert. Ich werde Ihre Erklärung des XPath studieren, ich dachte, ich könnte das schaffen, ohne tatsächlich zu lernen, wie man XPath benutzt, aber klar muss ich es tun. – dontpanic

+0

@donstpanic: Lerne 'XPath', stelle Fragen zur Verfeinerung deiner' XPath' Anfragen, es gibt viele 'XPath' Fragen und Antworten zu SO. – MattH

+0

@Simon: Also habe ich ein ähnliches Problem und ich habe versucht, Ihrem Vorschlag zu folgen und immer noch kein Glück. Wären Sie in der Lage, ein Beispiel von einem Wert aus der Tabelle unten in http://weather.deltixlab.com/ zu zeigen Ich habe Folgendes geschrieben: 'string day1 = doc.DocumentNode.SelectNodes (" // * [@ class = 'table-block'] /../../../ tr [1]/td [1] ") [0] .InnerText;' – goodfella

2

wie Simon Mourier explaind, erhalten Sie den rohen HTML vom Server gesendet . Das von Ihnen benötigte Element wurde noch nicht gerendert. Sie können es noch nicht abrufen, da es im DOM nicht existiert. Eine einfache Lösung für dieses Problem besteht darin, einen Web-Renderer zum Erstellen des DOM zu verwenden, dann können Sie den HTML-Code abrufen und ihn abkratzen. Ich benutze WatiN wie folgt aus:

WatiN.Core.Settings.MakeNewInstanceVisible = false; 
WatiN.Core.Settings.AutoMoveMousePointerToTopLeft = false; 
IE ie = new IE(); 
ie.GoTo(urlLink); 
ie.WaitForComplete(); 
string html = ie.Html; 
ie.close(); 
+0

Vielen Dank, also im Grunde muss ich die Seite vollständig zu rendern, um das fehlende DOM zu bekommen. Was mich jetzt beunruhigt, ist die Verzögerung, die dies verursachen wird. – goodfella

Verwandte Themen