我们如何在搜索结果中显示干净的Google风格摘录?

时间:2013-02-01 18:13:10

标签: c# .net regex search dtsearch

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

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

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

我们有一个概念验证工作,显示突出显示搜索词的摘录,但我们要么渲染标记,要么尝试去除它们(正如我们已经尝试过的)并最终得到一些不是垃圾信息非常满意。

我认为我们使用dtSearch的事实是偶然的。如果替代搜索工具能够代表我们做这类事情,我们会考虑使用它。

我们基本上试图决定是否需要创建我们自己的正则表达式来完成此操作,或者它是否已经由某些库或工具解决了一个众所周知的问题。

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

3 个答案:

答案 0 :(得分:3)

Google会使用meta个描述标记,并在可用时使用rich snippet information

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

一个简单的流程:

  1. 解析文档并找到大量的所有元素 文本内容。
  2. 剥离内部代码(例如strong内的p
  3. 更喜欢文档开头附近的元素。
  4. 运行算法(可能使用正则表达式,可能使用文化感知)来尝试提取句子。
  5. 非常喜欢使用与一个或多个搜索字词匹配的字词(根据您声明的要求)。
  6. 喜欢几乎没有噪音的句子。
  7. (高级)更喜欢在文档中定期出现单词的句子。
  8. (高级)将多个可能有用的句子合并到一个描述摘要中。
  9. 即使对谷歌来说,这也不是一门精确的科学。

答案 1 :(得分:0)

以下是我使用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;");            }
    }
}

答案 2 :(得分:0)

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 = this; SJob1.ExecuteInThread();每次发现文档时,StatusHandler调用OnFound都会进行调整,因此如果找不到文件而不执行OnFound方法,则不再执行加载。