【发布时间】:2014-06-07 14:23:50
【问题描述】:
我正在用 C# 编写简单的屏幕抓取程序,为此我需要选择放置在一个名为“aspnetForm”的单个表单中的所有输入(页面上有 2 个表单,我不希望输入来自另一个),并且此表单中的所有输入都放置在不同的表、div 中,或者只是在此表单的第一个子级。
所以我写了非常简单的 XPath 查询:
//form[@id='aspnetForm']//input
它在我测试的所有浏览器(Chrome、IE、Firefox)中都按预期工作 - 它返回我想要的。
但在 HTMLAgilityPack 中它根本不起作用 - SelectNodes 总是返回 NULL。
我为测试编写的这个查询工作正常,但返回的不是我想要的。首先为我的表单选择所有作为第一个孩子的输入,然后只选择返回的表单:
//form[@id='aspnetForm']/input
//form[@id='aspnetForm']
是的,我知道我可以枚举上一个查询中的节点,或者在它的结果上创建另一个 SelectNodes,但我真的不想这样做。我想使用与浏览器中相同的查询。
XPath 目前在 HTMLAgilityPack 中是否被破坏? C# 有任何替代的 XPath 实现吗?
更新:测试代码:
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 内置了 HtmlAgilityPack 使用的 XPath 实现(HAP 不实现自己的 XPath 引擎)。实际上,HAP 的 XPath 过去对我来说工作得很好,所以我建议先怀疑其他的东西。
-
尝试保存
HtmlDocument,然后检查保存的文件是否包含预期的HTML格式。 -
@har07,它包含 - 我在发布问题之前对其进行了测试。 “肮脏的解决方法”方法也有效,因此输入绝对不是问题。向问题添加了测试代码,因此您可以自己测试它 - 它没有按预期工作。
标签: c# xpath screen-scraping