【问题标题】:How do we show clean, Google-style excerpts in our search results?我们如何在搜索结果中显示干净、Google 风格的摘录?
【发布时间】:2023-03-23 22:16:01
【问题描述】:

我们正在使用 dtSearch 来索引一些外部网页。它抓取页面的整个 HTML 内容。

当页面出现在我们网站的搜索结果列表中时,我们希望显示包含其突出显示/粗体搜索词的内容的摘录作为结果的一部分(换句话说,每个人都习惯在每个 Google 结果下看到相同的内容)。

实现这一目标的最佳方法是什么?您是否必须解析和删除 HTML 标签?如果是这样,您如何有效地做到这一点?

我们有一个概念验证工作,显示带有突出显示的搜索词的摘录,但我们必须渲染标签,或者尝试将它们剥离(正如我们所尝试的那样)并最终得到一些不是垃圾信息真的很满足。

我认为我们使用 dtSearch 是偶然的。如果替代搜索工具能够代表我们执行此类操作,我们会考虑使用它。

我们基本上是在尝试决定是否需要编写自己的正则表达式来完成此任务,或者这是一个众所周知的问题,已经被某些库或工具解决了。

我们碰巧在使用 .NET/C#。我认为这不是问题的核心,但可能会影响我们可以使用哪些库。

【问题讨论】:

  • 使用谷歌?许多网站都嵌入了 Google 搜索...
  • google 节目的摘录取决于您搜索的内容。所以同一网站可以有多个摘录!以及为什么要删除 html 标签!还建议使用 regex 解析 html 是...
  • 我应该补充一点,除了索引外部网页之外,我们还在索引我们自己的一些数据库内容。至于使用谷歌搜索,我不确定它搜索你自己的数据库而不是爬取页面的能力如何,我也不确定你可以在多大程度上自定义结果的外观。
  • @Some1.Kill.The.DJ 假设我们不删除 HTML 标签。这意味着我们必须渲染它们。这似乎会产生奇怪的结果。我以前从未见过无序列表或浮动 div 出现在 Google 搜索结果中。你有什么建议?

标签: c# .net regex search dtsearch


【解决方案1】:

Google 使用meta 描述标签(如果存在),并且还将使用rich snippet information(如果可用)。

除此之外,您可能需要执行自定义解析,但不要使用正则表达式来执行整个任务。相反,使用适当的解析器(例如HTML Aglity Pack)并找到具有语义意义的标签(可能是标题、段落等)。一旦您找到了这些元素,您可能会使用正则表达式来确定哪些匹配的标签会给出你最好的 sn-p,在哪里截断它等等。

一个简单的流程:

  1. 解析文档并定位所有具有显着数量的元素 文本内容。
  2. 去除内部标签(例如strongp 内)
  3. 首选靠近文档开头的元素。
  4. 运行一个算法(可能使用正则表达式,并且可能使用文化感知)来尝试提取句子。
  5. 强烈偏爱单词与一个或多个搜索词匹配的句子(根据您声明的要求)。
  6. 更喜欢带有少量干扰词的句子。
  7. (高级)喜欢在文档中经常出现单词的句子。
  8. (高级)将多个可能有用的句子组合成一个描述 sn-p。

这不是一门精确的科学,即使对 Google 来说也是如此。

【讨论】:

    【解决方案2】:

    这是我用来生成带有 dtsearch 的项目的搜索摘要(具有文档文本的缓存存储版本):

    你的问题的关键点是rj.OutputFormat = dtSearch.Engine.OutputFormats.itUTF8;(它覆盖了默认的html格式) 您应该得到一个带有粗体突出显示的清理摘要。

    希望这会有所帮助

    public string GetSumary(String ItemEncoded)
    {
        using (var res = new dtSearch.Engine.SearchResults())
        {
            res.UrlDecodeItem(ItemEncoded);
            res.GetNthDoc(0);
    
            using (var rj = res.NewSearchReportJob())
            {
                // next line asumes you store your document text version in cache. remove if not 
                rj.Flags |= dtSearch.Engine.ReportFlags.dtsReportGetFromCache;
                rj.Flags |= dtSearch.Engine.ReportFlags.dtsReportByWordExact;
                rj.Flags |= dtSearch.Engine.ReportFlags.dtsReportLimitContiguousContext;
                rj.OutputToString = true;
                rj.OutputFormat = dtSearch.Engine.OutputFormats.itUTF8;
                rj.OutputStringMaxSize = 2000;
                rj.MaxContextBlocks = 1;
                rj.WordsOfContext = 12;
    
                rj.Header = "";
                rj.FileHeader = "";
                rj.ContextHeader = "";
                rj.BeforeHit = "<b>";
                rj.AfterHit = "</b>";
                rj.ContextFooter = "";
                rj.ContextSeparator = " ... ";
                rj.FileFooter = "";
                rj.Footer = "";
    
                rj.SelectItems(0, 0);
                rj.Execute();
    
                // some final clean-up
                return
                        new Regex(@"[\t\r\n]+|[\.;\,\*]{2,}").Replace(rj.OutputString, "&nbsp; &nbsp;");            }
        }
    }
    

    【讨论】:

      【解决方案3】:
      Use dtsearch ISearchStatusHandler interface with OnFound method, OnFound method Called each time a document is found 
      
      public class HomeController : Controller, ISearchStatusHandler
      {
      
      public void Search()
      {
         SearchJob sj = new SearchJob();
         sj.Request = "fast";
         sj.IndexesToSearch.Add(@"D:\R & D\Indexpath\aaa");
         sj.SearchFlags = SearchFlags.dtsSearchSynonyms &         
         SearchFlags.dtsSearchWordNetRelated;        
         sj.Execute();
         SearchResults result = sj.Results;
      }
      
       public void OnFound(SearchResultsItem item)
       {
              int DocId = item.DocId;
              string FileName = item.Filename;
       }
      
       public void OnSearchingFile(string filename)
       {
              throw new NotImplementedException();
       }
      
       public void OnSearchingIndex(string index)
       {
              throw new NotImplementedException();
       }
       }
      

      有一种更有条理和更全面的方式来处理获得的搜索结果。 SearchJob 对象有一个 StatusHandler 属性,该属性可以设置为一个对象,该对象具有一组在搜索过程中调用的方法。使用它,您可以在找到文件时对其进行处理,并且可以通过不占用 UI 线程来保持 UI 响应。喜欢:SJob1.StatusHandler = this; SJob1.Execute();
      SJob1.StatusHandler = 这个; SJob1.ExecuteInThread();每次找到文档时,StatusHandler 都会调用 OnFound 方法,因此如果找不到文档,则不会执行 OnFound 方法,因此不再加载。

      【讨论】:

      • 欢迎使用 StackOverflow!虽然您发布的代码可能很好地回答了这个问题,但请添加一些解释。
      • 请在您的答案中添加(编辑它),而不是在 cmets 中。
      猜你喜欢
      • 1970-01-01
      • 2013-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-19
      • 2021-12-10
      • 1970-01-01
      • 2012-03-21
      相关资源
      最近更新 更多