【问题标题】:Filtering HTML document with 1-10k keywords过滤带有 1-10k 个关键字的 HTML 文档
【发布时间】:2013-01-11 23:10:06
【问题描述】:

我有一个 html 文档,并希望根据多个 (1 - 10k) [目前为 1k,稍后最多为 10k] 关键字的出现对其进行过滤。

我有一个预编译的正则表达式,它存储我的搜索词,例如:

static Regex r = new Regex(@"keyword1|keyword2|keyword999",RegexOptions.Compiled | RegexOptions.IgnoreCase);

这是我的代码:

Stopwatch sw = new Stopwatch();
sw.Start();
MatchCollection matches = Cache.r.Matches(doc.DocumentNode.InnerHtml);
string s = "";
if (matches.Count > 0)
{
    foreach (Match m in matches)
    {
        s += m.Value + ",";
    }
}
long time = sw.ElapsedMilliseconds;
Console.Write(time + " = "+matches.Count+" -> "+s );

平均时间大约需要 5-8 秒。这太过分了。 是否有任何有效的方法来过滤针对大量关键字的 html 文档? 或者也许有更有效的算法来过滤这个..

【问题讨论】:

  • 您需要了解或使用 html 做什么?你需要知道哪些词出现了,它们出现了多少次?
  • 那些关键字是什么..我们无法读懂你的想法..
  • 我想知道是否出现自定义关键字。它可以是任何东西。我想知道哪些关键字匹配
  • @unr3al011 在将其用作正则表达式之前,您应该使用Regex.Escape 转义关键字,否则如果关键字中出现.*,它将被视为特殊字符。
  • 我希望它被视为特殊字符

标签: c# regex full-text-search string-matching


【解决方案1】:

正如lboshuizen指出的那样

用 10k 个关键字创建一个正则表达式似乎不是可行的方法 [...]

如果您负担得起产生多个线程的费用,您可以并行扫描文档以查找关键字的出现:

IEnumerable<string> keywords = LoadKeywords();
List<string> list = new List<string>();
keywords.AsParallel()
    .Aggregate(list, (seed, keyword) =>
    {
        if(doc.DocumentNode.InnerHtml.Contains(keyword))
            seed.Add(keyword);
        return seed;
    });

【讨论】:

  • 产生多个线程接缝是个好主意,但我怎样才能等到处理完成?我认为我的代码将继续运行,但线程的处理可能尚未完成还是我错了?
  • @unr3al011,在并行查询完成执行之前,您的进程不会继续。
  • @unr3al011,我不明白你的问题。但是,您需要知道的是,您不必担心使用答案中的构造加入或等待线程。
  • 非常感谢!这个真的很快。检查 900 个单词的平均时间为 50 毫秒。有没有可能让它准备好通配符?
  • @unr3al011,我给了你一个做什么模板。您可以根据需要扩展逻辑:)
【解决方案2】:

你应该使用StringBuilder 而不是string..

除非你告诉我们更多关于关键字是什么,否则几乎没有任何优化..

【讨论】:

    【解决方案3】:

    有些答案已经很不错了,但我想我也会把这个扔进去......

    我也做过同样的事情,我使用 HTML Agility Pack 来帮助减少我正在分析的关键字。

    http://htmlagilitypack.codeplex.com/

    获取 HTML 片段非常容易,仅搜索文本节点,然后在该空间而不是整个文档上运行关键字分析。

    它还有助于消除误报(出现在 javascript cmets、alt 标记等任何其他内容中的关键字)。

    只是一个尝试缩小搜索空间的想法。

    【讨论】:

      【解决方案4】:

      建议:

      用 10k 个关键字创建一个正则表达式似乎不是从我的 POV 出发的方法。正则表达式是贪婪的,会尝试各种冗余匹配。 (=浪费时间)

      使用较小的关键字集构建正则表达式并在您的 html 文档中以增量方式运行它们。

      优化可以是从文档中删除匹配的关键字(和相关内容),将缩小并且剩余的正则表达式的工作更少==运行得更快。

      或者

      把它转过来,不要使用正则表达式来扫描文档。 将文档分解为单词并再次使用字典检查它们。我怀疑该文档将包含所有 10k 个单词。 (从最小集合循环比从最大集合循环更有效)

      【讨论】:

      • 我认为匹配的执行方式不会有什么不同(可能相当于朴素的字符串搜索算法)。使用小型正则表达式仅对内存有用。
      • 不完全正确。让正则表达式进行“蛮力”匹配可能比检查字典更糟糕。它涉及更多的思考,但这就是我工作的精髓
      • 我指的是“使用较小的关键字集构建正则表达式并在您的 html 文档中以增量方式运行它们。”方法。对于另一种方法(检查字典),它非常依赖于实现(模拟 DFA 的散列或树状结构似乎更有效)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多