【新增】bing、google search

This commit is contained in:
cherishsince 2025-03-02 12:05:39 +08:00
parent 2a9dffb6ed
commit 86801517d1
3 changed files with 193 additions and 0 deletions

View File

@ -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<WebSearchRespVO> bingSearch(String query, Integer count);
/**
* Google 搜索
*
* @param query 搜索关键词
* @param count 返回结果数量
* @return 搜索结果列表
*/
List<WebSearchRespVO> googleSearch(String query, Integer count);
}

View File

@ -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<WebSearchRespVO> 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<WebSearchRespVO> 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<WebSearchRespVO> 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<WebSearchRespVO> 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();
}
}
}

View File

@ -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;
}