Piszę prosty program skrobania ekranu w języku C#, dla którego muszę wybrać wszystkie dane wejściowe umieszczone w jednym formularzu o nazwie "aspnetForm" (na stronie są 2 formularze i nie chcę danych wejściowych od innych), a wszystkie dane wejściowe w tej formie znajdują się w różnych tabelach, div lub po prostu na pierwszym poziomie podrzędnym tego formularza.Wybór XPath w HTMLAgilityPack nie działa zgodnie z oczekiwaniami
Więc napisany naprawdę proste zapytanie XPath:
//form[@id='aspnetForm']//input
Działa jako oczekiwane we wszystkich przeglądarkach, które testowałem (Chrome, IE, Firefox) - zwraca to, co chcę.
Ale w HTMLAgilityPack to w ogóle nie działa - SelectNodes po prostu zawsze zwraca NULL.
Te zapytania, które napisałem dla testów, działają dobrze, ale nie zwracają tego, co chcę. Najpierw należy wybrać wszystkie wejścia, że są pierwszymi-Childs dla mojej postaci i forma drugiego prostu wrócić za:
//form[@id='aspnetForm']/input
//form[@id='aspnetForm']
Tak, wiem, że mogę po prostu wymienić na węzły z ostatniego zapytania, lub dokonać innego selectNodes na jego wynik, ale naprawdę nie chcę tego robić. Chcę użyć tego samego zapytania, co w przeglądarkach.
Czy XPath jest obecnie uszkodzony w HTMLAgilityPack? Czy istnieją jakieś alternatywne implementacje XPath dla C#?
UPDATE: Kod Test:
using HtmlAgilityPack;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace HtmlAGPTests
{
[TestClass]
public class XPathTests
{
private const string html =
"<form id=\"aspnetForm\">" +
"<input name=\"first\" value=\"first\" />" +
"<div>" +
"<input name=\"second\" value=\"second\" />" +
"</div>" +
"</form>";
private static HtmlNode GetHtmlDocumentNode()
{
var document = new HtmlDocument();
document.LoadHtml(html);
return document.DocumentNode;
}
[TestMethod]
public void TwoLevelXpathTest() // fail - nodes is NULL actually.
{
var query = "//form[@id='aspnetForm']//input"; // what i want
var documentNode = GetHtmlDocumentNode();
var inputNodes = documentNode.SelectNodes(query);
Assert.IsTrue(inputNodes.Count == 2);
}
[TestMethod]
public void TwoSingleLevelXpathsTest() // works
{
var formQuery = "//form[@id='aspnetForm']";
var inputQuery = "//input";
var documentNode = GetHtmlDocumentNode();
var formNode = documentNode.SelectSingleNode(formQuery);
var inputNodes = formNode.SelectNodes(inputQuery);
Assert.IsTrue(inputNodes.Count == 2);
}
[TestMethod]
public void SingleLevelXpathTest() // works
{
var query = "//form[@id='aspnetForm']";
var documentNode = GetHtmlDocumentNode();
var formNode = documentNode.SelectSingleNode(query);
Assert.IsNotNull(formNode);
}
}
}
. NET ma wbudowaną implementację XPath, która jest używana przez HtmlAgilityPack (HAP nie implementuje własnego silnika XPath). I faktycznie XPath używany przez HAP działał dobrze dla mnie, więc sugeruję podejrzenie czegoś innego. – har07
Spróbuj zapisać 'HtmlDocument', a następnie sprawdź, czy zapisany plik zawiera oczekiwany format HTML. – har07
@ har07, zawiera - testowałem to przed opublikowaniem pytania. Również metody "brudnego obejścia" działają, więc nie stanowi to problemu z wprowadzaniem danych. Dodano kod testowy do zapytania, więc możesz go przetestować samodzielnie - to NIE działa zgodnie z oczekiwaniami. – rufanov