【问题标题】:xpath search for multiple keywordsxpath 搜索多个关键字
【发布时间】:2014-03-31 17:11:44
【问题描述】:

我正在使用 htmlagilitypack 和 xpath 为特定关键字抓取网页。我在一次搜索多个关键字时遇到了麻烦。

所以我得到的关键字东西的代码是(随机选择的关键字:Frozen 和 obamacare):

HtmlDocument doc = new HtmlDocument();
HtmlWeb web = new HtmlWeb();
doc = web.Load(uri);
HtmlNodeCollection Nodes = doc.DocumentNode.SelectNodes("//text()[contains(., 'Frozen obamacare')]");

即使我知道该页面特别有两个关键字,这也不起作用,并且从其他发现基本上得知SelectNodes("//text()[contains(., 'Frozen obamacare')]"); 是多个关键字的正确方法。

我需要帮助验证这是否是使用多个关键字的正确方法,如果不是,那么我正在寻求帮助来纠正它。

【问题讨论】:

  • 您使用的查询不是搜索多个关键字,而是搜索字符串Frozen obamacare。试试这个//text()[contains(.,'Frozen') and contains(.,'obamacare')]
  • 我选择 Jens Erat 的答案是因为它现在可以工作,即使 XPath 2.0 功能可能是最好的方法,我也必须更改我拥有/正在使用的内容或修复裁剪的错误尝试 XPath 2.0 内容时启动。感谢大家的大力帮助。你们太棒了!

标签: c# xpath html-agility-pack


【解决方案1】:

这将检索包含字符串“Frozen obamacare”的所有文本节点。它不会标记为单词或任何东西。与您的查询匹配的示例是:

  • 冷冻奥巴马医改
  • fooFrozen obamacarebar

不匹配:

  • 冷冻 foo obamacare
  • 冷冻奥巴马医改

要匹配包含两个标记的 XPath 1.0 中的字符串,请使用

//text()[contains(., 'Frozen') and contains(., 'obamacare')]

HTML Agility Pack 仅支持 XPath 1.0,因此您无法使用 XPath 2.0 更高级的标记化功能。

【讨论】:

  • 既然 HTML Agility Pack 仅支持 XPath 1.0,我可以使用 XPath 2.0 来获得 Agility Pack 所具有的 HTML 文档功能吗?
  • 有一堆 XQuery/XPath 2.0 处理器可以从 .net 接口。看看提供本机功能的 Saxon。 BaseX 也有接口。还有另一个本地 .net 库,但我现在不记得名字了。顺便说一句,我的回答实际上是关于 XPath 1.0。在 XPath 2.0 中,您将在源字符串上使用 tokenize
【解决方案2】:

您的 XPath //text()[contains(., 'Frozen obamacare')] 会逐字检查包含字符串 Frozen obamacare 的文本节点。

您可能想检查是否可以使用 XPath 2.0 或 XQuery 1.0,因为您可以使用例如//text()[matches(., 'Frozen|obamacare')] 或考虑使用 .NET 和 HTML Agility Pack 中的 LINQ 支持以及可以使用的正则表达式支持

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using HtmlAgilityPack;

namespace ConsoleApplication63
{
    class Program
    {
        static void Main(string[] args)
        {
            HtmlWeb web = new HtmlWeb();
            HtmlDocument doc = web.Load("http://stackoverflow.com/questions/22767900/xpath-search-for-multiple-keywords");

            foreach (HtmlTextNode text in doc.DocumentNode.Descendants().OfType<HtmlTextNode>().Where(n => Regex.IsMatch(n.InnerText, @"\b(Frozen|obamacare)\b")))
            {
                Console.WriteLine("Found \"{0}\"", text.InnerText);
            }
        }
    }
}

【讨论】:

  • 这真的可以与 HTML Agility Pack 一起使用吗(我之所以这么问,是因为我认为它是您 using 语句的一部分)?
  • @shadonar,是的,当然,这是使用从 NuGet 获取的最新版本的 HTML Agility Pack 测试的代码。
猜你喜欢
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多