【问题标题】:Find keyword in text when keyword match certain conditions - C#当关键字匹配某些条件时在文本中查找关键字 - C#
【发布时间】:2013-01-13 03:40:18
【问题描述】:

我正在寻找一种很好的方法来执行以下操作:

我有一篇文章,其中包含 HTML 标记,例如锚点和段落等。
我也有关键字,我需要在文章中找到并将其设置为锚点(我有一些网址要设置在那里)。
如果文章中确实存在关键字,则在使其成为锚点之前,它应符合以下两个条件:

  1. 它不能在任何标签内。 例如,像

    <img alt="keyword"> 
    

    将无效/不匹配。

  2. 关键字不能已经在锚点内。例如,类似

    <a>keyword</a>
    

    将无效/不匹配。


    任何帮助,将不胜感激。 谢谢

【问题讨论】:

  • 请说明您试图在哪里创建此限制。在 JavaScript 函数中?在网络框架中?
  • 我正在尝试在 C# 中执行此操作
  • 不,这是我的错。在你提到它之后,我会将它添加到标题中:)
  • 我不清楚你想做什么。只是想澄清一下。你需要放一个链接,但你不能使用&lt;a&gt;标签?
  • 不,我需要在文章中的一些现有单词周围放置一个链接。但是,我必须确保当它是某个元素的属性的一部分或已经是链接(在锚元素内)时,我不会将它作为链接。希望能进一步澄清一些事情。

标签: html search tags conditional-statements keyword


【解决方案1】:

我已经成功了!

非常感谢这篇文章,它在 xpath 表达式方面帮助了我很多: http://social.msdn.microsoft.com/Forums/en-US/regexp/thread/beae72d6-844f-4a9b-ad56-82869d685037/

我的任务是使用我数据库中的关键字和 url 表将 X 个关键字添加到文章中。
一旦关键字匹配 - 它不会再次搜索它,但会尝试在文本中查找下一个关键字。
“关键字”可能由多个单词组成。这就是我添加替换(“”,“\s+”)的原因。
另外,我必须优先考虑最长的关键字。那就是如果我有:
“good day”和“good”作为两个不同的关键字 - “good day”总是胜出。

这是我的解决方案:

static public string AddLinksToArticle(string article, int linksToAdd)
    {
        try
        {
            //load keywords and urls
            var dt = new DAL().GetArticleLinks();

            //sort the it
            IEnumerable<ArticlesRow> sortedArticles = dt.OrderBy(row => row.keyword, new StringLengthComparer());

            // iterate the dictionary to get keyword to replace with anchor
            foreach (var item in sortedArticles)
            {
                article = FindAndReplaceKeywordWithAnchor(article, item.keyword, item.url, ref linksToAdd);
                if (linksToAdd == 0)
                {
                    break;
                }
            }

            return article;
        }
        catch (Exception ex)
        {
            Utils.LogErrorAdmin(ex);
            return null;
        }
    }

    private static string FindAndReplaceKeywordWithAnchor(string article, string keyword, string url, ref int linksToAdd)
    {
        //convert text to html
        HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
        doc.LoadHtml(article);

        // \w* - means it can start with any alphanumeric charactar
        // \s+ - was placed to replace all white spaces (when there is more than one word).
        // \b - set bounderies for the keyword
        string pattern = @"\b" + keyword.Trim().Insert(0, "\\w*").Replace(" ", "\\s+") + @"\b";

        //get all elements text propery except for anchor element 
        var nodes = doc.DocumentNode.SelectNodes("//text()[not(ancestor::a)]") ?? new HtmlAgilityPack.HtmlNodeCollection(null);
        foreach (var node in nodes)
        {
            if (node.InnerHtml.Contains(keyword))
            {
                Regex regex = new Regex(pattern);
                node.InnerHtml = regex.Replace(node.InnerHtml, "<a href=\"" + url + "\">" + keyword + "</a>", 1);//match only first occurrence
                linksToAdd--;
                break;
            }
        }

        return doc.DocumentNode.OuterHtml;
    }
}

public class StringLengthComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        return y.Length.CompareTo(x.Length);
    }
}

希望将来能对某人有所帮助。

【讨论】:

  • 此代码无法正常工作,因为 FindAndReplaceKeywordWithAnchor 方法存在严重缺陷。 node.InnerHtml.Contains(keyword) 如果您的标签在文本中,即使是某个单词的一部分,也会返回 true。因此,如果您需要“儿子”但有“杰森”,它将返回 true。然后你的 break 将取消循环,因此不会找到“儿子”。您需要将 node.InnerHtml.Contains(keyword) 更改为 regex.IsMatch(node.InnerHtml) ,其中 regex 是新的 Regex(pattern)。
  • 你是对的。我已经修好了。谢谢!我不会编辑我的答案,所以未来的人会看到你对它的贡献。
猜你喜欢
  • 2021-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-13
  • 1970-01-01
相关资源
最近更新 更多