Java调用百度搜索API的完整实现指南

Java调用百度搜索API的完整实现指南

在互联网应用开发中,集成搜索引擎功能是提升用户体验的重要手段。百度作为国内领先的搜索引擎服务商,提供了标准化的API接口供开发者调用。本文将系统阐述如何通过Java程序调用百度搜索API,涵盖从前期准备到功能实现的全流程。

一、技术准备与API申请

1.1 百度开放平台账号注册

开发者需首先注册百度开发者账号,通过百度开放平台完成实名认证。认证通过后可在控制台创建应用,获取调用搜索API所需的AK(Access Key)SK(Secret Key)

1.2 服务选择与配额管理

百度搜索API提供多种服务类型,包括网页搜索、新闻搜索、图片搜索等。开发者应根据业务需求选择对应服务,并注意:

  • 免费版每日调用配额限制(通常为500次/日)
  • QPS(每秒查询数)限制(通常为5次/秒)
  • 超出配额后的计费规则

建议通过控制台设置调用预警阈值,避免意外产生费用。

二、Java环境配置

2.1 依赖管理

推荐使用Maven管理项目依赖,在pom.xml中添加HTTP客户端依赖:

  1. <!-- Apache HttpClient -->
  2. <dependency>
  3. <groupId>org.apache.httpcomponents</groupId>
  4. <artifactId>httpclient</artifactId>
  5. <version>4.5.13</version>
  6. </dependency>
  7. <!-- JSON处理库 -->
  8. <dependency>
  9. <groupId>com.fasterxml.jackson.core</groupId>
  10. <artifactId>jackson-databind</artifactId>
  11. <version>2.13.0</version>
  12. </dependency>

2.2 签名生成工具类

百度API要求每次请求携带签名(sign),可通过以下工具类生成:

  1. import javax.crypto.Mac;
  2. import javax.crypto.spec.SecretKeySpec;
  3. import java.nio.charset.StandardCharsets;
  4. import java.security.MessageDigest;
  5. import java.util.Arrays;
  6. import java.util.Base64;
  7. public class SignUtils {
  8. // HMAC-SHA256签名
  9. public static String hmacSha256(String data, String key) throws Exception {
  10. Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
  11. SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
  12. sha256_HMAC.init(secret_key);
  13. byte[] bytes = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8));
  14. return Base64.getEncoder().encodeToString(bytes);
  15. }
  16. // MD5加密(备用)
  17. public static String md5(String input) {
  18. try {
  19. MessageDigest md = MessageDigest.getInstance("MD5");
  20. byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));
  21. return Arrays.toString(messageDigest);
  22. } catch (Exception e) {
  23. throw new RuntimeException(e);
  24. }
  25. }
  26. }

三、核心实现步骤

3.1 请求参数构造

百度搜索API采用GET请求方式,关键参数包括:

  • wd: 搜索关键词(必填)
  • pn: 结果页码(从0开始)
  • rn: 每页结果数(默认10,最大50)
  • ie: 输入编码(utf-8)
  • oe: 输出编码(utf-8)

示例参数构造:

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. import java.util.TreeMap;
  4. public class BaiduSearchRequest {
  5. private String ak;
  6. private String sk;
  7. private String query;
  8. private int page;
  9. private int size;
  10. public BaiduSearchRequest(String ak, String sk) {
  11. this.ak = ak;
  12. this.sk = sk;
  13. }
  14. public Map<String, String> buildParams(String query, int page, int size) {
  15. Map<String, String> params = new TreeMap<>(); // 保证参数排序
  16. params.put("wd", query);
  17. params.put("pn", String.valueOf(page * size));
  18. params.put("rn", String.valueOf(size));
  19. params.put("ie", "utf-8");
  20. params.put("oe", "utf-8");
  21. params.put("ak", ak);
  22. params.put("timestamp", String.valueOf(System.currentTimeMillis()));
  23. return params;
  24. }
  25. }

3.2 签名生成与URL拼接

完整请求流程:

  1. 构造基础参数
  2. 生成待签名字符串(参数按字典序拼接)
  3. 使用SK生成签名
  4. 拼接最终URL

实现示例:

  1. import java.net.URLEncoder;
  2. import java.nio.charset.StandardCharsets;
  3. import java.util.Map;
  4. public class BaiduSearchClient {
  5. private static final String API_URL = "https://api.baidu.com/search/v1/websearch";
  6. public String search(BaiduSearchRequest request, String query, int page, int size) throws Exception {
  7. // 1. 构造参数
  8. Map<String, String> params = request.buildParams(query, page, size);
  9. // 2. 生成待签名字符串
  10. StringBuilder signStr = new StringBuilder();
  11. for (Map.Entry<String, String> entry : params.entrySet()) {
  12. if (!"sign".equals(entry.getKey())) { // 排除sign本身
  13. signStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
  14. }
  15. }
  16. signStr.append("sk=").append(request.getSk()); // 追加SK
  17. // 3. 生成签名
  18. String sign = SignUtils.hmacSha256(signStr.toString(), request.getSk());
  19. params.put("sign", sign);
  20. // 4. 拼接URL
  21. StringBuilder urlBuilder = new StringBuilder(API_URL);
  22. urlBuilder.append("?");
  23. for (Map.Entry<String, String> entry : params.entrySet()) {
  24. urlBuilder.append(entry.getKey())
  25. .append("=")
  26. .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name()))
  27. .append("&");
  28. }
  29. urlBuilder.deleteCharAt(urlBuilder.length() - 1); // 移除最后一个&
  30. // 5. 发送请求(此处省略HTTP请求代码)
  31. return sendGetRequest(urlBuilder.toString());
  32. }
  33. }

四、响应处理与结果解析

百度API返回JSON格式数据,典型响应结构如下:

  1. {
  2. "status": 0,
  3. "message": "success",
  4. "data": {
  5. "total": 1000,
  6. "results": [
  7. {
  8. "title": "示例标题",
  9. "url": "https://example.com",
  10. "abstract": "示例摘要..."
  11. }
  12. ]
  13. }
  14. }

解析示例:

  1. import com.fasterxml.jackson.databind.ObjectMapper;
  2. import java.io.IOException;
  3. public class SearchResponse {
  4. private int status;
  5. private String message;
  6. private SearchData data;
  7. // Getter/Setter省略
  8. public static class SearchData {
  9. private int total;
  10. private List<SearchResult> results;
  11. // Getter/Setter省略
  12. }
  13. public static class SearchResult {
  14. private String title;
  15. private String url;
  16. private String abstract;
  17. // Getter/Setter省略
  18. }
  19. public static SearchResponse parse(String json) throws IOException {
  20. ObjectMapper mapper = new ObjectMapper();
  21. return mapper.readValue(json, SearchResponse.class);
  22. }
  23. }

五、最佳实践与注意事项

5.1 性能优化建议

  1. 连接池管理:使用HttpClient连接池复用TCP连接
  2. 异步调用:对于高并发场景,可采用CompletableFuture实现异步请求
  3. 缓存策略:对相同查询词的结果进行本地缓存(建议TTL≤5分钟)

5.2 异常处理机制

需重点处理的异常类型:

  1. try {
  2. // API调用代码
  3. } catch (IOException e) {
  4. // 网络异常处理
  5. } catch (SignatureException e) {
  6. // 签名错误处理
  7. } catch (RateLimitException e) {
  8. // 配额超限处理(需实现自定义异常)
  9. } finally {
  10. // 资源释放
  11. }

5.3 安全规范

  1. 严禁将AK/SK硬编码在代码中,建议使用配置中心或环境变量
  2. 实现IP白名单机制,限制API调用来源
  3. 定期轮换密钥(建议每90天更换一次)

六、完整调用示例

  1. public class Main {
  2. public static void main(String[] args) {
  3. String ak = "your_access_key";
  4. String sk = "your_secret_key";
  5. BaiduSearchRequest request = new BaiduSearchRequest(ak, sk);
  6. BaiduSearchClient client = new BaiduSearchClient();
  7. try {
  8. String response = client.search(request, "Java开发", 0, 10);
  9. SearchResponse searchResponse = SearchResponse.parse(response);
  10. if (searchResponse.getStatus() == 0) {
  11. searchResponse.getData().getResults().forEach(result -> {
  12. System.out.println("标题: " + result.getTitle());
  13. System.out.println("URL: " + result.getUrl());
  14. });
  15. } else {
  16. System.err.println("请求失败: " + searchResponse.getMessage());
  17. }
  18. } catch (Exception e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. }

七、进阶功能扩展

  1. 多类型搜索:通过切换API端点实现新闻、图片等垂直搜索
  2. 语义搜索:结合NLP技术对查询词进行扩展
  3. 结果去重:对多页结果进行合并去重处理
  4. 监控告警:集成Prometheus监控API调用成功率

通过系统化的实现方法,开发者可以高效稳定地集成百度搜索功能。实际开发中需密切关注API文档更新,及时调整实现细节以适配最新接口规范。