Elasticsearch 使用误区之六——富文本内容写入前不清洗

embedded/2024/12/21 21:23:42/

0、引言

在很多应用场景中,我们会将富文本内容(如 HTML 格式的网页内容)存储到 Elasticsearch 中,以实现全文检索

然而,在实际使用过程中,我们可能会遇到一些问题,比如在检索时,HTML 标签被截断,或者检索结果中会显示部分 HTML 标签内容。这种现象不仅影响了检索体验,还可能对页面展示造成困扰。

本文将详细介绍如何解决这种富文本处理中的常见问题,帮助大家在使用 Elasticsearch 时更加高效地处理和展示富文本内容。

1、具体问题描述

Elasticsearch 所存储的数据包含但不限于:

  • 业务数据

  • 日志数据

  • 互联网采集数据

  • 其他数据 如果遇到互联网采集数据场景,Elasticsearch 的 content 字段极大可能需要存储的是富文本内容(HTML)。

遇到这种情况,咱们得非常的慎重。

不信,你看!如下 QQ 群群友出现的问题可见一斑。

91da735e4460cd43358a55a14913d80c.jpeg

827521b03d1210fac36f116f3b419258.png


什么问题呢?

在输入关键词进行检索时,可能会出现 HTML 标签被截断的情况,导致返回的结果中显示部分 HTML 标签内容。

这种情况对用户展示极为不友好。

那么,我们应该如何处理这种问题呢?

2、原因分析

Elasticsearch 本质上是一个文本检索引擎,它会对输入的文本进行分析、分词、索引,并对用户的搜索关键词进行相应匹配。

富文本(HTML)的特殊性在于,它不仅包含可见的文字,还包含大量的标记语言(如 <div>、<p>、<span> 等标签),这些标签在检索过程中可能会被 Elasticsearch 解析和处理,进而影响检索结果。

3、解决方案

针对这种情况,我们可以通过以下几个步骤来解决问题,确保检索结果更加干净、准确。

3.1. 清洗 HTML 内容

在将 HTML 内容写入 Elasticsearch 之前,最好先对其进行清洗。

清洗操作的目的是去除不必要的 HTML 标签,提取其中的有用文本信息。这可以通过编写自定义算法或使用 HTML 解析库来实现。

常用的 HTML 解析库包括 Jsoup、BeautifulSoup 等,其实采集团队或许已经做过处理。

如果公司采集团队和存储不是一个团队,建议深入交流一下字段细节内容。

3.2. 利用 Elasticsearch 的 HTML Strip 字符过滤器

Elasticsearch 提供了 html_strip  字符过滤器,可以用来自动去除 HTML 标签。

详细参见: 

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-htmlstrip-charfilter.html

通过该过滤器,我们可以确保在索引过程中,HTML 标签不会被保留下来,只有纯文本内容会被处理和检索。

示例如下:

PUT my-index
{"settings": {"analysis": {"char_filter": {"html_strip": {"type": "html_strip"}},"analyzer": {"html_analyzer": {"type": "custom","char_filter": ["html_strip"],"tokenizer": "standard"}}}},"mappings": {"properties": {"content": {"type": "text","analyzer": "html_analyzer"}}}
解释:
  1. char_filter 部分定义了 HTML 过滤器,用于去除 HTML 标签。

  2. html_analyzer 是自定义的分析器,首先使用 html_strip 过滤器去除 HTML 标签,随后通过标准分词器 standard 进行分词和处理。

使用这个分析器进行索引和搜索时,HTML 标签会自动被过滤掉,确保只有纯文本内容参与搜索,进而避免了 HTML 标签截断的问题。

3.3 存储多版本的内容

为了兼顾搜索和展示,推荐在存储时将富文本内容存为两个字段:

  1. 原始 HTML 内容:用于在前端完整展示。

  2. 纯文本版本:用于索引和检索。

并且负责任告诉大家,真实互联网采集数据存储与展示场景,就得这么干

例如,我们可以在 Elasticsearch 中定义两种字段:

"mappings": {"properties": {"html_content": {"type": "text", "index": false  // 不参与索引,仅用于展示},"cleaned_content": {"type": "text", "analyzer": "html_analyzer"  // 纯文本版本,参与检索}}
}

这样,html_content 字段保留原始 HTML,用于页面回显;

而 cleaned_content 字段则经过清洗处理,专用于检索操作。

3.4. 通过前端处理回显内容

为了避免搜索结果中显示部分 HTML 标签的情况,我们可以在前端对回显的内容进行进一步处理:

  1. 使用前端的 HTML 渲染器,比如 Vue.js 或 React.js 的 v-html 和 dangerouslySetInnerHTML,确保内容正确渲染。

  2. 结合高亮功能,确保用户能够清晰地看到与查询关键词匹配的文本部分,而非 HTML 标签。

3.5. 关键词高亮功能

为了增强用户体验,Elasticsearch 提供了高亮显示功能,可以在返回结果时高亮显示与关键词匹配的部分。

通过以下 DSL 语句,我们可以实现对匹配部分的高亮显示:

POST my-index/_search
{"query": {"match": {"cleaned_content": "搜索关键词"}},"highlight": {"fields": {"cleaned_content": {}}}
}

这样,在展示时,只会高亮纯文本部分,HTML 标签将不会出现在检索结果中。

4、完整示例,彻底解决富文本存储

Elasticsearch 处理富文本内容(HTML)的方案如下:

4.1 创建索引并配置 HTML 过滤器

如前方案探讨所述,我们首先创建一个新的索引,使用 Elasticsearch 的 html_strip 过滤器来去除 HTML 标签,并配置两个字段:一个存储清洗后的纯文本内容用于检索,另一个存储原始 HTML 内容用于展示。

PUT html_content_index
{"settings": {"analysis": {"char_filter": {"html_strip": {"type": "html_strip"}},"analyzer": {"html_analyzer": {"type": "custom","char_filter": ["html_strip"],"tokenizer": "standard"}}}},"mappings": {"properties": {"html_content": {"type": "text","index": false  // 原始 HTML 内容不参与索引,仅用于展示},"cleaned_content": {"type": "text","analyzer": "html_analyzer"  // 清洗后用于检索的纯文本}}}
}

4.2 向索引中写入数据

我们将两种不同的内容分别写入到 html_content 和 cleaned_content 字段。

html_content 保存的是原始 HTML,而 cleaned_content 保存的是清洗后的纯文本。

POST /html_content_index/_doc
{"html_content": "<p>这是一段关于<strong>Elasticsearch</strong>的文章。</p>","cleaned_content": "这是一段关于 Elasticsearch 的文章。"
}

在这个例子中,html_content 保留了 HTML 标签,而 cleaned_content 则去除了 HTML 标签,只保留了纯文本内容。

4.3 进行搜索并返回高亮结果

接下来,我们对 cleaned_content 字段进行全文检索,同时启用高亮功能,确保关键词匹配部分能够在前端得到突出显示。

GET /html_content_index/_search
{"query": {"match": {"cleaned_content": "Elasticsearch"}},"highlight": {"fields": {"cleaned_content": {}}}
}

返回结果示例如下:

5140743c83b4f4754dbb23193b81a877.png

{"took": 34,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 1,"relation": "eq"},"max_score": 0.2876821,"hits": [{"_index": "html_content_index","_id": "INbUKZIBSx0oX-FAHL8S","_score": 0.2876821,"_source": {"html_content": "<p>这是一段关于<strong>Elasticsearch</strong>的文章。</p>","cleaned_content": "这是一段关于 Elasticsearch 的文章。"},"highlight": {"cleaned_content": ["这是一段关于 <em>Elasticsearch</em> 的文章。"]}}]}
}

4.4 前端展示:结合原始 HTML 和高亮结果

在前端,我们可以使用 html_content 字段来展示完整的 HTML 内容,而使用 highlight 字段来突出显示用户搜索的关键词。这样,用户既可以看到完整的富文本格式的内容,又能清楚地识别出匹配的关键词。

伪代码:

<!-- 显示原始 HTML 内容 -->
<div v-html="html_content"></div><!-- 高亮显示匹配的关键词 -->
<div v-html="highlighted_cleaned_content"></div>

4.5 预处理 HTML 清洗

除了在 Elasticsearch 中使用 html_strip 过滤器,我们还可以在存入 Elasticsearch 之前预先清洗 HTML 内容。

以下是使用 Java 的 Jsoup 库来清洗 HTML 的示例:

import org.jsoup.Jsoup;public class HTMLCleaner {public static String cleanHTML(String html) {return Jsoup.parse(html).text();  // 将 HTML 内容转换为纯文本}
}

在保存数据到 Elasticsearch 之前,先调用 cleanHTML 方法去除不必要的 HTML 标签,然后将纯文本存入 cleaned_content 字段。

5、小结

在处理富文本内容时,合理的清洗和过滤是避免 HTML 标签影响检索结果的关键。

处理 HTML 内容的关键在于:清洗 + 分离存储 + 高亮展示

通过预处理富文本内容,使用 html_strip 过滤器,以及前端渲染和高亮展示,可以有效地避免 HTML 标签截断问题,从而确保用户获得干净、准确的搜索体验。

富文本不做处理直接写入是 Elasticsearch 使用中的常见误区之一,希望本文提供的解决方案能够帮助大家在日常工作中更好地应对类似问题。

更多推荐

  1. Elasticsearch 使用误区之一——将 Elasticsearch 视为关系数据库!

  2.   Elasticsearch 使用误区之二——频繁更新文档

  3. Elasticsearch 使用误区之三——分片设置不合理

  4. Elasticsearch 使用误区之四——不合理的使用 track_total_hits

  5. Elasticsearch 使用误区之五——单次请求获取大量数据

  6.    《一本书讲透 Elasticsearch》读者群的创新之路

594914e0a437769ac88bb0c1641c6059.jpeg

更短时间更快习得更多干货!

和全球2000+ Elastic 爱好者一起精进!

elastic6.cn——ElasticStack进阶助手

e50fc5c4ee467f9c921c3130b51dd601.gif

抢先一步学习进阶干货!


http://www.ppmy.cn/embedded/121080.html

相关文章

联想天逸100使用笔记

文章目录 配置整理过程锁定功能键怎么弄? 翻出好多年不用的老电脑&#xff0c;饱受折磨&#xff0c;做个笔记。 之前不是我在使用&#xff0c;本身配置就不高&#xff0c;还被装了各种流氓软件&#xff0c;卡的几乎动不了。 配置 老电脑配置不行&#xff1a; i3 5005U 4G内存…

Mybatis(进阶部分)

四 Mybatis完成CURD&#xff08;二&#xff09; 4.5 多条件CRUD 之前的案例中&#xff0c;接口里方法的形参个数都是1个&#xff1b;如果方法形参是两个或者两个以上时&#xff0c;MyBatis又该如何获取获取参数呢&#xff1f; Mybatis提供了好几种方式&#xff0c;可以获取多…

Windows环境 源码编译 FFmpeg

记录一下windows环境纯代码编译ffmeg的过程&#xff01; 目录 一、安装MSYS2 1.下载安装 2.配置 3.修改源 4.测试与更新 二、安装其他必要工具 1.安装MinGW-w64 2.安装git 3..安装make等工具 4.编译前的其他准备工作 ①.重命名link.exe ②.下载和安装YASM ③.安装…

【漏洞复现】泛微OA E-Office /E-mobile/App/init.php 任意文件上传漏洞

免责声明: 本文旨在提供有关特定漏洞的信息,以帮助用户了解潜在风险。发布此信息旨在促进网络安全意识和技术进步,并非出于恶意。读者应理解,利用本文提到的漏洞或进行相关测试可能违反法律或服务协议。未经授权访问系统、网络或应用程序可能导致法律责任或严重后果…

K8S精进之路-控制器DaemonSet -(3)

介绍 DaemonSet就是让一个节点上只能运行一个Daemonset Pod应用&#xff0c;每个节点就只有一个。比如最常用的网络组件&#xff0c;存储插件&#xff0c;日志插件&#xff0c;监控插件就是这种类型的pod.如果集群中有新的节点加入&#xff0c;DaemonSet也会在新的节点创建出来…

滚雪球学MySQL[8.2讲]:MySQL事件调度详解:定时任务的创建与管理及使用场景

全文目录&#xff1a; 前言8.2 MySQL事件调度1. 定时任务的创建与管理1.1 启用事件调度器1.2 创建定时任务1.2.1 一次性任务1.2.2 周期性任务1.2.3 管理事件的有效期 1.3 修改与删除事件1.3.1 修改事件1.3.2 删除事件 1.4 查看事件状态与执行日志 2. 事件调度器的使用场景2.1 数…

Python NumPy 数据分析:处理复杂数据的高效方法

Python NumPy 数据分析&#xff1a;处理复杂数据的高效方法 文章目录 Python NumPy 数据分析&#xff1a;处理复杂数据的高效方法一 数据来源二 获取指定日期数据三 获取指定行列数据四 求和计算五 比例计算六 平均值和标准差七 完整代码示例八 源码地址 本文详细介绍了如何使用…

HTML5实现好看的唐朝服饰网站模板源码2

文章目录 1.设计来源1.1 网站首页1.2 唐装演变1.3 唐装配色1.4 唐装花纹1.5 唐装文化 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.ne…