如何选取包含特定关键字的表格 - c# - xpath - htmlagilitypack

3

我需要从一个没有类或id的产品页面中收集信息。我正在使用htmlagilitypack和c# 4.0。

在这个产品页面源代码中有很多表格。价格表格包含“KDV”字符串。因此,我想获取包含此“KDV”字符串的表格。我该怎么做?

以下xpath将选择所有表格,例如:

string srxPathOfCategory = "//table";
var selectedNodes = myDoc.DocumentNode.SelectNodes(srxPathOfCategory);

下面的代码选择了最外层的表格,但我需要选择包含给定字符串的最内层表格。
//table[contains(., ' KDV')]

c# , xpath , htmlagilitypack


不行。我需要使用HtmlAgilityPack通过XPath选择包含特定字符串的表格。 - Furkan Gözükara
KDV在我的语言中是指税。因此,它是用于价格的特定词汇 :),如45 TL + KDV。你无法相信他们使用的HTML结构有多糟糕,但他们是土耳其排名前十的在线卖家之一。示例页面:http://www.pratikev.com/fractalv33/pratikEv/pages/viewProduct.jsp?pInstanceId=3138821 - Furkan Gözükara
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/6128/discussion-between-pencho-ilchev-and-monstermmorpg - Pencho Ilchev
2个回答

4
下面的代码选择表格,但是从最外层表格开始。我需要选择包含给定字符串的最内层表格。 用法:
//table
    [not(descendant::table) 
   and 
     .//text()[contains(., ' KDV')]
    ]

这个 XPath 表达式选择 XML 文档中任何没有 table 子孙节点,且具有包含字符串 " KDV" 的文本节点后代的 table 元素。

一般来说,上述表达式可能会选择许多这样的 table 元素。

如果你只想选择其中一个(比如第一个),使用此 XPath 表达式——请注意括号:

   (//table
        [not(descendant::table) 
       and 
         .//text()[contains(., ' KDV')]
        ]
    )[1]

记住:如果您想选择文档中的第一个someName元素,使用以下方法(与当前接受的答案相同)是错误的:

//someName[1]

这是XPath中第二个最常见的问题(在如何选择带有默认命名空间的XML文档中未命名名称的元素之后)。

上面的表达式实际上选择文档中任何一个父元素的第一个子元素someName - 试一下。

这种令人费解的行为的原因是XPath [] 运算符具有比//伪运算符更高的优先级。

如果存在,则真正只选择任何XML文档中的第一个someName元素的正确表达式是:

(//someName)[1]

这里使用括号来显式地覆盖默认的XPath运算符优先级。


我必须说你是最棒的 :) 所以这个表达式正在选择那个表。为了选择它的TD作为节点,我该怎么做?谢谢:http://pastebin.com/2hHxUHa8 - Furkan Gözükara
@MonsterMMORPG:不用谢。要选择表格的td,只需在末尾添加/td:(//table [not(descendant::table) and .//text()[contains(., ' KDV')] ] )[1]/descendant::td[1] 选择此表格的第一个td。 - Dimitre Novatchev

1

可能有更有效的方式来完成它。不管怎样,这是我为你的情况使用的整个代码,并且对我起作用:

        HtmlDocument doc = new HtmlDocument();
        string url = "http://www.pratikev.com/fractalv33/pratikEv/pages/viewProduct.jsp?pInstanceId=3138821";
        using (var response = (WebRequest.Create(url).GetResponse()))
        {
            doc.LoadHtml(new StreamReader(response.GetResponseStream()).ReadToEnd());
        }
        /*There is an bug in the xpath used here. Should have been 
          (//table/tr/td/font[contains(.,'KDV')])[1]/ancestor::table[2] 
          See Dimitre's answer for an explanation and an alternative / 
          more generic / (needless to say) better approach */
        string xpath = "//table/tr/td/font[contains(.,'KDV')][1]/ancestor::table[2]"; 
        HtmlNode table = doc.DocumentNode.SelectSingleNode(xpath);

这段代码选择了表格,但是它从最外层开始选择。我需要选择最内层的表格,也就是包含KDV的第一个父级表格://table[contains(., ' KDV')]。 - Furkan Gözükara
非常有趣。这两个代码的行为完全不同,因为在我的文档get方法中,您的xpath返回null:http://pastebin.com/S9fvyMcL - Furkan Gözükara
奇怪的是,HtmlWeb似乎是引起问题的原因。哦,好吧,至少有一种方法可以让它工作:) 顺便说一句,我已经改变了xpath。我认为现在更有效率了。 - Pencho Ilchev
Pencho,这个答案有一些问题--我在我的回答中提供了一些见解。 - Dimitre Novatchev
@DimitreNovatchev,谢谢。我知道你可能会过来,因此我确保在答案开头加上了免责声明 :) - Pencho Ilchev
1
@PenchoIlchev:没问题,当我们学到新东西时,我们都是幸运的。 - Dimitre Novatchev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接