From 86801517d1eac32dd42cca35df9e075271ee442f Mon Sep 17 00:00:00 2001 From: cherishsince Date: Sun, 2 Mar 2025 12:05:39 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91bing?= =?UTF-8?q?=E3=80=81google=20search?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/websearch/WebSearchService.java | 29 ++++ .../websearch/WebSearchServiceImpl.java | 139 ++++++++++++++++++ .../service/websearch/vo/WebSearchRespVO.java | 25 ++++ 3 files changed, 193 insertions(+) create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchService.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchServiceImpl.java create mode 100644 yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/vo/WebSearchRespVO.java diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchService.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchService.java new file mode 100644 index 0000000000..264ca74624 --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchService.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.ai.service.websearch; + +import cn.iocoder.yudao.module.ai.service.websearch.vo.WebSearchRespVO; + +import java.util.List; + +/** + * Web 搜索 Service 接口 + */ +public interface WebSearchService { + + /** + * bing 搜索 + * + * @param query 搜索关键词 + * @param count 返回结果数量 + * @return 搜索结果列表 + */ + List bingSearch(String query, Integer count); + + /** + * Google 搜索 + * + * @param query 搜索关键词 + * @param count 返回结果数量 + * @return 搜索结果列表 + */ + List googleSearch(String query, Integer count); +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchServiceImpl.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchServiceImpl.java new file mode 100644 index 0000000000..8c0036c94a --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/WebSearchServiceImpl.java @@ -0,0 +1,139 @@ +package cn.iocoder.yudao.module.ai.service.websearch; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.module.ai.service.websearch.vo.WebSearchRespVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * Bing Web 搜索实现类 + */ +@Service +@Slf4j +public class WebSearchServiceImpl implements WebSearchService { + + /** + * google url + */ + private static final String GOOGLE_URL = "https://google.serper.dev/search"; + /** + * bing url + */ + private static final String BING_URL = "https://api.bing.microsoft.com/v7.0/search"; + /** + * 腾讯搜索 url + */ + private static final String TENCENT_URL = "tms.tencentcloudapi.com"; + + @Value("${yudao.web-search.api-key:}") + private String bingApiKey; + + @Value("${yudao.web-search.api-key:}") + private String googleApiKey; + + /** + * bing 搜索 + * + * @param query 搜索关键词 + * @param count 返回结果数量 + * @return 搜索结果列表 + */ + @Override + public List bingSearch(String query, Integer count) { + if (query == null || query.isEmpty()) { + return CollUtil.newArrayList(); + } + + try { + // 发送请求 + HttpResponse response = HttpRequest.get(BING_URL) + .header("Ocp-Apim-Subscription-Key", bingApiKey) + .form("q", query) + .form("count", String.valueOf(count)) + .form("responseFilter", "Webpages") + .form("textFormat", "Raw") + .execute(); + + // 解析响应 + String body = response.body(); + JSONObject json = JSONUtil.parseObj(body); + + // 处理结果 + List results = new ArrayList<>(); + if (json.containsKey("webPages") && json.getJSONObject("webPages").containsKey("value")) { + JSONArray items = json.getJSONObject("webPages").getJSONArray("value"); + for (int i = 0; i < items.size(); i++) { + JSONObject item = items.getJSONObject(i); + WebSearchRespVO result = new WebSearchRespVO() + .setTitle(item.getStr("name")) + .setUrl(item.getStr("url")) + .setSnippet(item.getStr("snippet")); + results.add(result); + } + } + + return results; + } catch (Exception e) { + log.error("[bingSearch][查询({}) 发生异常]", query, e); + return CollUtil.newArrayList(); + } + } + + /** + * Google 搜索(使用Serper API) + * + * @param query 搜索关键词 + * @param count 返回结果数量 + * @return 搜索结果列表 + */ + @Override + public List googleSearch(String query, Integer count) { + if (query == null || query.isEmpty()) { + return CollUtil.newArrayList(); + } + + try { + // 构建请求体 + JSONObject payload = new JSONObject(); + payload.set("q", query); + payload.set("gl", "cn"); + payload.set("num", count); + + // 发送请求 + HttpResponse response = HttpRequest.post(GOOGLE_URL) + .header("X-API-KEY", googleApiKey) + .header("Content-Type", "application/json") + .body(payload.toString()) + .execute(); + + // 解析响应 + String body = response.body(); + JSONObject json = JSONUtil.parseObj(body); + JSONArray organicResults = json.getJSONArray("organic"); + + // 处理结果 + List results = new ArrayList<>(); + for (int i = 0; i < organicResults.size(); i++) { + JSONObject item = organicResults.getJSONObject(i); + WebSearchRespVO result = new WebSearchRespVO() + .setTitle(item.getStr("title")) + .setUrl(item.getStr("link")) + .setSnippet(item.containsKey("snippet") ? item.getStr("snippet") : ""); + results.add(result); + } + return results; + } catch (Exception e) { + log.error("[googleSearch][查询({}) 发生异常]", query, e); + return CollUtil.newArrayList(); + } + } +} diff --git a/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/vo/WebSearchRespVO.java b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/vo/WebSearchRespVO.java new file mode 100644 index 0000000000..215b4b44af --- /dev/null +++ b/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/websearch/vo/WebSearchRespVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.ai.service.websearch.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 搜索结果 + */ +@Data +@Accessors(chain = true) +public class WebSearchRespVO { + + /** + * 标题 + */ + private String title; + /** + * URL + */ + private String url; + /** + * 摘要 + */ + private String snippet; +} \ No newline at end of file