尝试在 c# 中使用 xpath select 光滑的 href 属性
Trying to select slippery href attribute with xpath in c#
试图从站点抓取 .pdf,但 XPath 很顽固。
Site I'm trying to get the .pdf from
检查给出的 xpath > 复制 > 复制 xpath:
//*[@id="content"]/div/table[2]/tbody/tr[0]/td[3]/a
出于某种原因,/tbody
除了引发问题外什么也没做。删除它对我正在使用的所有其他 Xpath 都有效,而且似乎也是去这里的方法。
//*[@id="content"]/div/table[2]/tr[0]/td[3]/a
这会产生结果:
<img width="16" height="16" src="/apps/cba/g_doctype_pdf.gif" border="0"><br><small>Download<br>Agreement</small>
哪个似乎是 child 节点?
在任何情况下都支持 xpath 到:
//*[@id="content"]/div/table[2]/tr[0]/td[3]
让我明白
<a target="_blank" href="/apps/cba/docs/1088-CBA6-2017_Redacted.pdf"><img width="16" height="16" src="/apps/cba/g_doctype_pdf.gif" border="0"><br><small>Download<br>Agreement</small></a>
这很好,因为我只需要 href
属性中的值,我可以重建 URL 等等。我不是 XPath 的向导,但在我看来,这个最后的调整应该让我得到我想要的东西:
//*[@id="content"]/div/table[2]/tr[0]/td[3]/@href
不过它又 returns 了标签。
我对此感到难过。有什么建议吗?
编辑:
标记的解决方案让我明白我是在做一个假设。我假设我可以像取消引用其他 节点 一样取消引用 href 标签。事实并非如此,我不得不将取消引用调整为如下所示:
var node_collection = hdoc.DocumentNode.SelectNodes(@"//*[@id=""content""]/div/table[2]/tr[1]/td[3]/a/@href");
string output = node[0].Attributes["href"].Value
问题根本不在 Xpath 上。问题是我对我正在处理的 HtmlDocument object 缺乏理解。粘贴我试图获取 href 标签的位置会让任何有经验的人都明白这一点。对 copy-pasting 我的整个混乱代码块过于自我意识使得任何人都无法帮助我。孩子们,从我的错误中吸取教训,健壮的代码段更容易准确地识别问题。
你说得对,tbody
是由 Chromes 在复制 XPath 上添加的,应该删除,因为它不存在于原始 HTML 代码中。 *
选择 href
属性应按建议工作://*[@id="content"]/div/table[2]/tr[1]/td[3]/a/@href
我可以像这样加载第一个 href:
HtmlWeb web = new HtmlWeb();
HtmlDocument hdoc = web.Load("https://work.alberta.ca/apps/cba/searchresults.asp?query=&employer=&union=&locality=&local=&effective_fy=&effective_fm=&effective_ty=&effective_tm=&expiry_fy=&expiry_fm=&expiry_ty=&expiry_tm=");
var nav = (HtmlNodeNavigator)hdoc.CreateNavigator();
var val = nav.SelectSingleNode(@"//*[@id=""content""]/div/table[2]/tr[1]/td[3]/a/@href").Value;
或者所有人都这样:
XPathNavigator nav2 = hdoc.CreateNavigator();
XPathNodeIterator xiter = nav2.Select(@"//*[@id=""content""]/div/table[2]/tr/td[3]/a/@href");
while (xiter.MoveNext())
{
Console.WriteLine(xiter.Current.Value);
}
* 但是,某些引擎确实要求 tbody
出现在 XPath 中,正如 here. Only then we get a result. See this answer 为什么 Chrome 添加了 tbody
, Firebug,和第一个一样。
试图从站点抓取 .pdf,但 XPath 很顽固。
Site I'm trying to get the .pdf from
检查给出的 xpath > 复制 > 复制 xpath:
//*[@id="content"]/div/table[2]/tbody/tr[0]/td[3]/a
出于某种原因,/tbody
除了引发问题外什么也没做。删除它对我正在使用的所有其他 Xpath 都有效,而且似乎也是去这里的方法。
//*[@id="content"]/div/table[2]/tr[0]/td[3]/a
这会产生结果:
<img width="16" height="16" src="/apps/cba/g_doctype_pdf.gif" border="0"><br><small>Download<br>Agreement</small>
哪个似乎是 child 节点?
在任何情况下都支持 xpath 到:
//*[@id="content"]/div/table[2]/tr[0]/td[3]
让我明白
<a target="_blank" href="/apps/cba/docs/1088-CBA6-2017_Redacted.pdf"><img width="16" height="16" src="/apps/cba/g_doctype_pdf.gif" border="0"><br><small>Download<br>Agreement</small></a>
这很好,因为我只需要 href
属性中的值,我可以重建 URL 等等。我不是 XPath 的向导,但在我看来,这个最后的调整应该让我得到我想要的东西:
//*[@id="content"]/div/table[2]/tr[0]/td[3]/@href
不过它又 returns 了标签。 我对此感到难过。有什么建议吗?
编辑:
标记的解决方案让我明白我是在做一个假设。我假设我可以像取消引用其他 节点 一样取消引用 href 标签。事实并非如此,我不得不将取消引用调整为如下所示:
var node_collection = hdoc.DocumentNode.SelectNodes(@"//*[@id=""content""]/div/table[2]/tr[1]/td[3]/a/@href");
string output = node[0].Attributes["href"].Value
问题根本不在 Xpath 上。问题是我对我正在处理的 HtmlDocument object 缺乏理解。粘贴我试图获取 href 标签的位置会让任何有经验的人都明白这一点。对 copy-pasting 我的整个混乱代码块过于自我意识使得任何人都无法帮助我。孩子们,从我的错误中吸取教训,健壮的代码段更容易准确地识别问题。
你说得对,tbody
是由 Chromes 在复制 XPath 上添加的,应该删除,因为它不存在于原始 HTML 代码中。 *
选择 href
属性应按建议工作://*[@id="content"]/div/table[2]/tr[1]/td[3]/a/@href
我可以像这样加载第一个 href:
HtmlWeb web = new HtmlWeb();
HtmlDocument hdoc = web.Load("https://work.alberta.ca/apps/cba/searchresults.asp?query=&employer=&union=&locality=&local=&effective_fy=&effective_fm=&effective_ty=&effective_tm=&expiry_fy=&expiry_fm=&expiry_ty=&expiry_tm=");
var nav = (HtmlNodeNavigator)hdoc.CreateNavigator();
var val = nav.SelectSingleNode(@"//*[@id=""content""]/div/table[2]/tr[1]/td[3]/a/@href").Value;
或者所有人都这样:
XPathNavigator nav2 = hdoc.CreateNavigator();
XPathNodeIterator xiter = nav2.Select(@"//*[@id=""content""]/div/table[2]/tr/td[3]/a/@href");
while (xiter.MoveNext())
{
Console.WriteLine(xiter.Current.Value);
}
* 但是,某些引擎确实要求 tbody
出现在 XPath 中,正如 here. Only then we get a result. See this answer 为什么 Chrome 添加了 tbody
, Firebug,和第一个一样。