历史文章

Spring AI:对接DeepSeek实战
Spring AI:对接官方 DeepSeek-R1 模型 —— 实现推理效果
Spring AI:ChatClient实现对话效果
Spring AI:使用 Advisor 组件 - 打印请求大模型出入参日志
Spring AI:ChatMemory 实现聊天记忆功能
Spring AI:本地安装 Ollama 并运行 Qwen3 模型
Spring AI:提示词工程
Spring AI:提示词工程 - Prompt 角色分类(系统角色与用户角色)
Spring AI:基于 “助手角色” 消息实现聊天记忆功能
Spring AI:结构化输出 - 大模型响应内容
Spring AI:Docker 安装 Cassandra 5.x(限制内存占用)&& CQL
Spring AI:整合 Cassandra - 实现聊天消息持久化
Spring AI:多模态 AI 大模型
Spring AI:文生图:调用通义万相 AI 大模型
Spring AI:文生音频 - cosyvoice-V2
Spring AI:文生视频 - wanx2.1-i2v-plus
Spring AI:上手体验工具调用(Tool Calling)
Spring AI:整合 MCP Client - 调用高德地图 MCP 服务
Spring AI:搭建自定义 MCP Server:获取 QQ 信息
Spring AI:对接自定义 MCP Server
Spring AI:RAG 增强检索介绍
Spring AI:Docker 安装向量数据库 - Redis Stack
Spring AI:文档向量化存储与检索
Spring AI:提取 txt、Json、Markdown、Html、Pdf 文件数据,转换为 Document 文档
Spring AI:Apache Tika 读取 Word、PPT 文档
Spring AI:Docker 安装 SearXNG 搜索引擎
Spring AI:整合 OKHttp3:获取 SearXNG 搜索结果
Spring AI:自定义线程池 - 通过 CompletableFuture 并发获取搜索结果页面内容

在这里插入图片描述
上文中,我们已经成功通过 CompletableFuture 并发去获取多个页面 HTML 代码。但是,也要考虑到一个问题,那就是如果直接将 HTML 添加到提示词上下文中,不做任何处理的话,那么,势必会导致提示词长度太大,调用 AI 大模型的费用成本,也会显著增加。

为了避免此问题,我们还需要对 HTML 提纯一下,这里选型的是 Jsoup 库,它能够将 css 、js 、html 等无用的代码部分去除掉,仅提取出纯文本。

Jsoup 介绍

Jsoup 是一个强大的 Java HTML 解析、操作、清理和数据抓取库。专为处理 “现实世界” 的 HTML(即使格式混乱)而设计。

其核心功能如下:

  • 极简 API (类似 jQuery): 最大亮点是提供极其易用、基于 CSS 选择器 (select()) 和流畅链式调用的 API,学习成本低,代码简洁高效。
  • 强大容错解析: 能优雅处理格式错误、标签未闭合等“脏” HTML,构建合理的 DOM 树,而严格 XML 解析器会失败。
  • 高效数据抽取: 结合 CSS 选择器和 DOM 方法,轻松精准提取链接、文本、图片、属性值等目标数据(Web Scraping 利器)。
  • 健壮 HTML 清理 (XSS 防护): 提供强大的白名单机制,可清除用户提交的 HTML 中的危险内容(如恶意脚本),有效防御跨站脚本攻击 (XSS)。
  • 灵活输入支持: 可直接从 URL、文件、字符串或 InputStream 加载并解析 HTML 文档。
  • 良好性能: 对于常见 HTML 处理任务(解析、抓取、清理),性能表现优秀,比无头浏览器轻量快速。
  • 整洁 HTML 输出: 输出的 HTML 会自动格式化(缩进、换行),结构清晰易读。
  • 轻量级: 独立 JAR 包,无复杂依赖,易于集成。

添加依赖

编辑 pom.xml ,添加 Jsoup 的依赖,如下:

<properties>
     // 省略...
    <jsoup.version>1.17.2</jsoup.version>
</properties>

// 省略...

<dependencies>
    // 省略...

    <!-- Jsoup -->
    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>${jsoup.version}</version>
    </dependency>
</dependencies>

// 省略...

添加完成后,刷新一下 Maven, 将包下载到本地仓库中。

提取 HTML 中的纯文本

接着,编辑 SearchResultContentFetcherServiceImpl 业务类,将 batchFetch() 方法中 “步骤3” 的 map() 方法改造一下,通过 Jsoup 提取 HTML 中的纯文本,代码如下:

// 步骤3:当所有任务完成后收集结果
return allFutures.thenApplyAsync(v -> // 所有任务完成后触发
                futures.stream() // 遍历所有已完成的任务
                        .map(future -> {
                            SearchResult searchResult = future.join();
                            // 获取页面 HTML 代码
                            String html = searchResult.getContent();

                            if (StringUtils.isNotBlank(html)) {
                                // 提取 HTML 中的文本
                                searchResult.setContent(Jsoup.parse(html).text());
                            }

                            return searchResult;
                        }) // 提取每个任务的结果
                        .collect(Collectors.toList()), // 合并所有结果为一个集合,并返回
        processingExecutor // 使用专用的 processingExecutor 线程池
);

测试

接着,我们将 SearXNGServiceImpl 中的搜索引擎指定部分,先改为仅使用 baidu 百度,如下图所示:

在这里插入图片描述
在这里插入图片描述
重启后端项目,浏览器请求如下地址,先看看是否能够成功提取出 HTML 中的纯文本:

http://localhost:8090/network/test?message=最新上映的最火的剧叫什么

有些页面的 content 字段值可能会出现:
空字符串:这是因为防止用户等待时间较长,代码中有设置超时时间,如果长时间未响应,或者请求发生异常,则会直接返回 “空字符串”;
拿不到页面真实数据:如上图 ② 提示 “百度安全校验” 等等,这是因为有些网站有反爬虫机制,或者是异步渲染,这会导致我们拿不到真实的文本信息;

增加聚合的搜索引擎

考虑上述问题的存在,我们可以增加提取搜索结果的最大数量,如 50 页,以免样本数太少,导致能够提供给 AI 大模型的信息太少,无法正确回答问题的情况发生!

如何提升 SearXNG 获取的搜索结果数呢?可以增加聚合的搜索引擎数量。进入到 SearXNG 的 “首选项” 中,如下图,将所有搜索引擎都勾选上:

在这里插入图片描述
然后,执行一下搜索,看看效果,如下图,点击展开右侧栏的 “响应时间”,就能看到哪些搜索引擎基于本地的网络环境,能够成功获取响应,哪些获取不到响应了(由于墙的原因):

TIP: 如果你有科学上网方式,建议开下自动代理,这样能够拿到的搜索结果会更多。

知道哪些搜索引擎响应正常后,就可以在请求 SearXNG API 接口时,将它们都添加到 engines 参数中:

// 构建 SearXNG API 请求 URL
HttpUrl httpUrl = HttpUrl.parse(searxngUrl).newBuilder()
        .addQueryParameter("q", query) // 设置搜索关键词
        .addQueryParameter("format", "json") // 指定返回 JSON 格式
        .addQueryParameter("engines", "wolframalpha,presearch,seznam,mwmbl,encyclosearch,bpb,mojeek,right dao,wikimini,crowdview,searchmysite,bing,naver,360search") // 指定聚合的目标搜索引擎(配置本地网络能够访问的通的搜索引擎)
        .build();

重启后端项目,再次测试一下。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐