Browse Source

删w12

main
Bilei 3 weeks ago
parent
commit
255e909c78
  1. 29
      w12/.vscode/launch.json
  2. 3
      w12/.vscode/settings.json
  3. BIN
      w12/202506050225-毕磊-高级程序设计实验报告.docx
  4. 56
      w12/hotsearch_results/hotsearch_20260528_140606.txt
  5. 60
      w12/hotsearch_results/hotsearch_20260531_121726.txt
  6. 4
      w12/总代码/.vscode/settings.json
  7. 76
      w12/总代码/pom.xml
  8. 667
      w12/总代码/src/main/java/WeiboStarHotSearcha.java
  9. 30
      w12/总代码/src/main/java/com/weibo/hotsearch/ConsoleOutputHandler.java
  10. 24
      w12/总代码/src/main/java/com/weibo/hotsearch/HotSearchFilter.java
  11. 16
      w12/总代码/src/main/java/com/weibo/hotsearch/Main.java
  12. 46
      w12/总代码/src/main/java/com/weibo/hotsearch/OutputHandler.java
  13. 18
      w12/总代码/src/main/java/com/weibo/hotsearch/StarFilter.java
  14. 133
      w12/总代码/src/main/java/com/weibo/hotsearch/cli/CliHandler.java
  15. 101
      w12/总代码/src/main/java/com/weibo/hotsearch/cli/CliParser.java
  16. 12
      w12/总代码/src/main/java/com/weibo/hotsearch/command/Command.java
  17. 41
      w12/总代码/src/main/java/com/weibo/hotsearch/command/CommandInvoker.java
  18. 47
      w12/总代码/src/main/java/com/weibo/hotsearch/command/CommandResult.java
  19. 34
      w12/总代码/src/main/java/com/weibo/hotsearch/command/FetchCommand.java
  20. 35
      w12/总代码/src/main/java/com/weibo/hotsearch/command/FilterCommand.java
  21. 27
      w12/总代码/src/main/java/com/weibo/hotsearch/command/HelpCommand.java
  22. 34
      w12/总代码/src/main/java/com/weibo/hotsearch/command/OutputCommand.java
  23. 30
      w12/总代码/src/main/java/com/weibo/hotsearch/command/SaveCommand.java
  24. 69
      w12/总代码/src/main/java/com/weibo/hotsearch/controller/HotSearchController.java
  25. 20
      w12/总代码/src/main/java/com/weibo/hotsearch/exception/CliException.java
  26. 20
      w12/总代码/src/main/java/com/weibo/hotsearch/exception/DataParseException.java
  27. 47
      w12/总代码/src/main/java/com/weibo/hotsearch/exception/ErrorCode.java
  28. 30
      w12/总代码/src/main/java/com/weibo/hotsearch/exception/HotSearchException.java
  29. 20
      w12/总代码/src/main/java/com/weibo/hotsearch/exception/NetworkException.java
  30. 49
      w12/总代码/src/main/java/com/weibo/hotsearch/model/AppContext.java
  31. 69
      w12/总代码/src/main/java/com/weibo/hotsearch/model/HotSearchItem.java
  32. 75
      w12/总代码/src/main/java/com/weibo/hotsearch/model/HotSearchResult.java
  33. 307
      w12/总代码/src/main/java/com/weibo/hotsearch/service/DataFetcher.java
  34. 44
      w12/总代码/src/main/java/com/weibo/hotsearch/service/FilterService.java
  35. 66
      w12/总代码/src/main/java/com/weibo/hotsearch/service/OutputService.java
  36. 12
      w12/总代码/src/main/java/com/weibo/hotsearch/strategy/FilterStrategy.java
  37. 30
      w12/总代码/src/main/java/com/weibo/hotsearch/strategy/FilterStrategyFactory.java
  38. 55
      w12/总代码/src/main/java/com/weibo/hotsearch/strategy/PolicyFilterStrategy.java
  39. 54
      w12/总代码/src/main/java/com/weibo/hotsearch/strategy/SportsFilterStrategy.java
  40. 76
      w12/总代码/src/main/java/com/weibo/hotsearch/strategy/StarFilterStrategy.java
  41. 51
      w12/总代码/src/main/java/com/weibo/hotsearch/view/ConsoleView.java
  42. 83
      w12/总代码/src/main/java/com/weibo/hotsearch/view/TextView.java
  43. 10
      w12/总代码/src/main/java/com/weibo/hotsearch/view/View.java
  44. 29
      w12/总代码/src/main/java/com/weibo/hotsearch/view/ViewFactory.java
  45. 4
      w12/总代码/src/run.bat
  46. BIN
      w12/总代码/target/classes/WeiboStarHotSearcha.class
  47. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/ConsoleOutputHandler.class
  48. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/HotSearchFilter.class
  49. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/Main.class
  50. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/OutputHandler.class
  51. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/StarFilter.class
  52. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/cli/CliHandler.class
  53. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/cli/CliParser.class
  54. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/Command.class
  55. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/CommandInvoker.class
  56. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/CommandResult.class
  57. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/FetchCommand.class
  58. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/FilterCommand.class
  59. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/HelpCommand.class
  60. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/OutputCommand.class
  61. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/command/SaveCommand.class
  62. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/controller/HotSearchController.class
  63. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/exception/CliException.class
  64. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/exception/DataParseException.class
  65. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/exception/ErrorCode.class
  66. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/exception/HotSearchException.class
  67. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/exception/NetworkException.class
  68. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/model/AppContext.class
  69. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/model/HotSearchItem.class
  70. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/model/HotSearchResult.class
  71. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/service/DataFetcher.class
  72. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/service/FilterService.class
  73. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/service/OutputService.class
  74. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/strategy/FilterStrategy.class
  75. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/strategy/FilterStrategyFactory.class
  76. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/strategy/PolicyFilterStrategy.class
  77. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/strategy/SportsFilterStrategy.class
  78. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/strategy/StarFilterStrategy.class
  79. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/view/ConsoleView.class
  80. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/view/TextView.class
  81. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/view/View.class
  82. BIN
      w12/总代码/target/classes/com/weibo/hotsearch/view/ViewFactory.class
  83. BIN
      w12/总代码/target/hotsearch-1.0.0-jar-with-dependencies.jar
  84. BIN
      w12/总代码/target/hotsearch-1.0.0.jar
  85. 3
      w12/总代码/target/maven-archiver/pom.properties
  86. 37
      w12/总代码/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  87. 37
      w12/总代码/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

29
w12/.vscode/launch.json

@ -1,29 +0,0 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "WeiboStarHotSearcha",
"request": "launch",
"mainClass": "WeiboStarHotSearcha",
"projectName": "weibo-hotsearch"
},
{
"type": "java",
"name": "Main",
"request": "launch",
"mainClass": "com.weibo.hotsearch.Main",
"projectName": "weibo-hotsearch"
}
]
}

3
w12/.vscode/settings.json

@ -1,3 +0,0 @@
{
"java.configuration.updateBuildConfiguration": "interactive"
}

BIN
w12/202506050225-毕磊-高级程序设计实验报告.docx

Binary file not shown.

56
w12/hotsearch_results/hotsearch_20260528_140606.txt

@ -1,56 +0,0 @@
热搜数据采集报告
================
采集时间: 2026年05月28日 14:06:04
【微博热搜数据】
--- 明星相关热搜 ---
排名:6 热度:414478 热搜:VOGUE直播间两位明星不出镜
排名:32 热度:373370 热搜:歌手第二期歌单
排名:34 热度:370959 热搜:小红书官宣获得世界杯版权
明星相关热搜总数:3 条
--- 体育相关热搜 ---
排名:34 热度:370959 热搜:小红书官宣获得世界杯版权
体育相关热搜总数:1 条
--- 国家政策相关热搜 ---
排名:37 热度:364897 热搜:双汇发布致歉声明
国家政策相关热搜总数:1 条
【百度贴吧热搜数据】
--- 明星相关热搜 ---
明星相关热搜总数:0 条
当前贴吧热搜暂无明星相关内容
--- 体育相关热搜 ---
体育相关热搜总数:0 条
当前贴吧热搜暂无体育相关内容
--- 国家政策相关热搜 ---
国家政策相关热搜总数:0 条
当前贴吧热搜暂无国家政策相关内容
【知乎热搜数据】
--- 明星相关热搜 ---
排名:6 热度:0 热搜:动作演员吴樾为什么火不起来
明星相关热搜总数:1 条
--- 体育相关热搜 ---
体育相关热搜总数:0 条
当前知乎热搜暂无体育相关内容
--- 国家政策相关热搜 ---
国家政策相关热搜总数:0 条
当前知乎热搜暂无国家政策相关内容

60
w12/hotsearch_results/hotsearch_20260531_121726.txt

@ -1,60 +0,0 @@
热搜数据采集报告
================
采集时间: 2026年05月31日 12:17:24
【微博热搜数据】
--- 明星相关热搜 ---
排名:43 热度:186709 热搜:敖瑞鹏新剧演鞠婧祎哥哥
明星相关热搜总数:1 条
--- 体育相关热搜 ---
排名:10 热度:387068 热搜:陈星旭王玉雯一起去看欧冠了
排名:21 热度:261492 热搜:姆巴佩欧冠金靴
排名:23 热度:250168 热搜:文班亚马西决MVP
排名:37 热度:191114 热搜:文班亚马回应成为西部决赛MVP
排名:41 热度:188900 热搜:巴黎欧冠夺冠后多地爆发骚乱
排名:42 热度:188188 热搜:孙千去看欧冠了
排名:49 热度:172821 热搜:世界杯
体育相关热搜总数:7 条
--- 国家政策相关热搜 ---
国家政策相关热搜总数:0 条
当前微博热搜暂无国家政策相关内容
【百度贴吧热搜数据】
--- 明星相关热搜 ---
明星相关热搜总数:0 条
当前贴吧热搜暂无明星相关内容
--- 体育相关热搜 ---
体育相关热搜总数:0 条
当前贴吧热搜暂无体育相关内容
--- 国家政策相关热搜 ---
国家政策相关热搜总数:0 条
当前贴吧热搜暂无国家政策相关内容
【知乎热搜数据】
--- 明星相关热搜 ---
明星相关热搜总数:0 条
当前知乎热搜暂无明星相关内容
--- 体育相关热搜 ---
体育相关热搜总数:0 条
当前知乎热搜暂无体育相关内容
--- 国家政策相关热搜 ---
国家政策相关热搜总数:0 条
当前知乎热搜暂无国家政策相关内容

4
w12/总代码/.vscode/settings.json

@ -1,4 +0,0 @@
{
"git.ignoreLimitWarning": true,
"java.debug.settings.onBuildFailureProceed": true
}

76
w12/总代码/pom.xml

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.weibo</groupId>
<artifactId>hotsearch</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>HotSearch CLI Tool</name>
<description>热搜数据采集工具 - CLI + MVC + Command + Strategy + Exception体系</description>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5-fluent</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.52</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.weibo.hotsearch.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

667
w12/总代码/src/main/java/WeiboStarHotSearcha.java

@ -1,667 +0,0 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.util.Timeout;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class WeiboStarHotSearcha {
private static final String WEIBO_HOT_URL = "https://weibo.com/ajax/side/hotSearch";
private static final String TIEBA_HOT_URL = "https://tieba.baidu.com/hottopic/browse/topicList";
private static final String ZHIHU_HOT_URL = "https://www.zhihu.com/api/v4/search/top_search";
private static final String OUTPUT_DIR = "hotsearch_results";
private static final String[] STAR_KEYWORDS = {
"明星", "演员", "歌手", "爱豆", "艺人", "红毯", "综艺", "新剧",
"恋情", "官宣", "演唱会", "代言", "造型", "封面"
};
private static final String[] SPORTS_KEYWORDS = {
"足球", "篮球", "世界杯", "NBA", "CBA", "奥运会", "世锦赛",
"冠军", "比赛", "夺冠", "进球", "比分", "运动员", "国足",
"乒乓", "排球", "羽毛球", "游泳", "田径", "体操", "跳水",
"MVP", "转会", "联赛", "中超", "英超", "西甲", "欧冠"
};
private static final String[] POLICY_KEYWORDS = {
"政策", "新规", "条例", "法规", "通知", "公告", "发布",
"国务院", "发改委", "财政部", "教育部", "工信部", "科技部",
"税收", "补贴", "优惠", "扶持", "改革", "开放", "创新",
"十四五", "计划", "规划", "方案", "意见", "办法", "细则",
"经济", "金融", "市场", "监管", "安全", "环保", "绿色"
};
private static final int CONNECT_TIMEOUT = 10000;
private static final int RESPONSE_TIMEOUT = 10000;
private static final int MAX_RETRIES = 3;
private static final StringBuilder outputBuilder = new StringBuilder();
public static void main(String[] args) {
try {
outputBuilder.append("热搜数据采集报告\n");
outputBuilder.append("================\n");
outputBuilder.append("采集时间: ").append(getCurrentTime()).append("\n\n");
// ========== 微博热搜 ==========
System.out.println("正在请求微博热搜数据...");
outputBuilder.append("【微博热搜数据】\n");
String weiboJson = fetchWithRetry(WEIBO_HOT_URL, MAX_RETRIES, "https://weibo.com/");
if (weiboJson == null || weiboJson.isEmpty()) {
System.out.println("获取微博热搜数据失败");
outputBuilder.append("获取微博热搜数据失败\n\n");
} else {
parseAndFilterWeibo(weiboJson);
}
// ========== 百度贴吧热搜 ==========
System.out.println("\n\n正在请求百度贴吧热搜数据...");
outputBuilder.append("\n【百度贴吧热搜数据】\n");
String tiebaJson = fetchWithRetry(TIEBA_HOT_URL, MAX_RETRIES, "https://tieba.baidu.com/");
if (tiebaJson == null || tiebaJson.isEmpty()) {
System.out.println("获取百度贴吧热搜数据失败");
outputBuilder.append("获取百度贴吧热搜数据失败\n");
} else {
parseAndFilterTieba(tiebaJson);
}
// ========== 知乎热搜 ==========
System.out.println("\n\n正在请求知乎热搜数据...");
outputBuilder.append("\n【知乎热搜数据】\n");
try {
String zhihuJson = fetchWithRetry(ZHIHU_HOT_URL, MAX_RETRIES, "https://zhuanlan.zhihu.com/");
if (zhihuJson == null || zhihuJson.isEmpty()) {
System.out.println("获取知乎热搜数据失败");
outputBuilder.append("获取知乎热搜数据失败\n");
} else {
System.out.println("知乎返回数据长度: " + zhihuJson.length() + " 字符");
if (zhihuJson.length() > 0) {
System.out.println("知乎返回数据预览: " + zhihuJson.substring(0, Math.min(500, zhihuJson.length())) + "...");
}
parseAndFilterZhihu(zhihuJson);
}
} catch (Exception e) {
System.out.println("获取知乎热搜数据异常: " + e.getMessage());
outputBuilder.append("获取知乎热搜数据异常: " + e.getMessage() + "\n");
e.printStackTrace();
}
// ========== 保存到文件 ==========
String filename = saveToFile();
System.out.println("\n\n结果已保存到文件: " + filename);
} catch (IOException e) {
System.err.println("网络请求失败: " + e.getMessage());
e.printStackTrace();
} catch (Exception e) {
System.err.println("数据解析失败: " + e.getMessage());
e.printStackTrace();
}
}
private static String fetchWithRetry(String url, int maxRetries, String referer) throws IOException {
int retryCount = 0;
IOException lastException = null;
while (retryCount < maxRetries) {
try {
System.out.println("正在请求: " + url);
String result = Request.get(url)
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
.addHeader("Referer", referer)
.addHeader("Accept", "application/json, text/plain, */*;charset=UTF-8")
.addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
.addHeader("Accept-Encoding", "identity")
.addHeader("Connection", "keep-alive")
.addHeader("Content-Type", "application/json;charset=UTF-8")
.connectTimeout(Timeout.ofMilliseconds(CONNECT_TIMEOUT))
.responseTimeout(Timeout.ofMilliseconds(RESPONSE_TIMEOUT))
.execute()
.returnContent()
.asString(StandardCharsets.UTF_8);
// 修复可能的编码问题
result = new String(result.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
return result;
} catch (IOException e) {
lastException = e;
retryCount++;
System.out.println("请求失败 (" + retryCount + "/" + maxRetries + "): " + e.getMessage());
if (retryCount < maxRetries) {
System.out.println("2秒后重试...");
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new IOException("重试被中断", ie);
}
}
}
}
throw lastException != null ? lastException : new IOException("请求失败");
}
private static void parseAndFilterWeibo(String json) {
JSONObject root = JSONObject.parseObject(json);
if (root == null || !root.containsKey("data")) {
System.out.println("微博数据格式错误或接口返回异常");
outputBuilder.append("数据格式错误或接口返回异常\n");
return;
}
JSONObject data = root.getJSONObject("data");
if (data == null || !data.containsKey("realtime")) {
System.out.println("微博热搜数据为空");
outputBuilder.append("热搜数据为空\n");
return;
}
JSONArray realtime = data.getJSONArray("realtime");
if (realtime == null || realtime.isEmpty()) {
System.out.println("微博热搜列表为空");
outputBuilder.append("热搜列表为空\n");
return;
}
List<JSONObject> starHotList = new ArrayList<>();
List<JSONObject> sportsHotList = new ArrayList<>();
List<JSONObject> policyHotList = new ArrayList<>();
System.out.println("\n===== 微博 - 明星相关热搜 =====");
outputBuilder.append("\n--- 明星相关热搜 ---\n");
for (int i = 0; i < realtime.size(); i++) {
JSONObject item = realtime.getJSONObject(i);
if (item == null) continue;
String word = item.getString("word");
if (word == null || word.isEmpty()) continue;
long num = item.getLongValue("num", 0);
int rank = item.getIntValue("rank", 0);
if (isStarRelated(word)) {
starHotList.add(item);
String line = String.format("排名:%d\t热度:%d\t热搜:%s", rank, num, word);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
String summary = "\n明星相关热搜总数:" + starHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (starHotList.isEmpty()) {
String emptyMsg = "当前微博热搜暂无明星相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
System.out.println("\n===== 微博 - 体育相关热搜 =====");
outputBuilder.append("\n--- 体育相关热搜 ---\n");
for (int i = 0; i < realtime.size(); i++) {
JSONObject item = realtime.getJSONObject(i);
if (item == null) continue;
String word = item.getString("word");
if (word == null || word.isEmpty()) continue;
long num = item.getLongValue("num", 0);
int rank = item.getIntValue("rank", 0);
if (isSportsRelated(word)) {
sportsHotList.add(item);
String line = String.format("排名:%d\t热度:%d\t热搜:%s", rank, num, word);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
summary = "\n体育相关热搜总数:" + sportsHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (sportsHotList.isEmpty()) {
String emptyMsg = "当前微博热搜暂无体育相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
System.out.println("\n===== 微博 - 国家政策相关热搜 =====");
outputBuilder.append("\n--- 国家政策相关热搜 ---\n");
for (int i = 0; i < realtime.size(); i++) {
JSONObject item = realtime.getJSONObject(i);
if (item == null) continue;
String word = item.getString("word");
if (word == null || word.isEmpty()) continue;
long num = item.getLongValue("num", 0);
int rank = item.getIntValue("rank", 0);
if (isPolicyRelated(word)) {
policyHotList.add(item);
String line = String.format("排名:%d\t热度:%d\t热搜:%s", rank, num, word);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
summary = "\n国家政策相关热搜总数:" + policyHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (policyHotList.isEmpty()) {
String emptyMsg = "当前微博热搜暂无国家政策相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
}
private static void parseAndFilterTieba(String json) {
JSONObject root = JSONObject.parseObject(json);
if (root == null || !root.containsKey("data")) {
System.out.println("贴吧数据格式错误或接口返回异常");
outputBuilder.append("数据格式错误或接口返回异常\n");
return;
}
JSONObject data = root.getJSONObject("data");
if (data == null || !data.containsKey("bang_topic")) {
System.out.println("贴吧热搜数据为空");
outputBuilder.append("热搜数据为空\n");
return;
}
JSONArray topics = data.getJSONArray("bang_topic");
if (topics == null || topics.isEmpty()) {
System.out.println("贴吧热搜列表为空");
outputBuilder.append("热搜列表为空\n");
return;
}
List<JSONObject> starHotList = new ArrayList<>();
List<JSONObject> sportsHotList = new ArrayList<>();
List<JSONObject> policyHotList = new ArrayList<>();
System.out.println("\n===== 百度贴吧 - 明星相关热搜 =====");
outputBuilder.append("\n--- 明星相关热搜 ---\n");
for (int i = 0; i < topics.size(); i++) {
JSONObject item = topics.getJSONObject(i);
if (item == null) continue;
String topicName = item.getString("topic_name");
if (topicName == null || topicName.isEmpty()) continue;
int discussNum = item.getIntValue("discuss_num", 0);
int readNum = item.getIntValue("read_num", 0);
if (isStarRelated(topicName)) {
starHotList.add(item);
String line = String.format("序号:%d\t阅读:%d\t讨论:%d\t话题:%s", i + 1, readNum, discussNum, topicName);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
String summary = "\n明星相关热搜总数:" + starHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (starHotList.isEmpty()) {
String emptyMsg = "当前贴吧热搜暂无明星相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
System.out.println("\n===== 百度贴吧 - 体育相关热搜 =====");
outputBuilder.append("\n--- 体育相关热搜 ---\n");
for (int i = 0; i < topics.size(); i++) {
JSONObject item = topics.getJSONObject(i);
if (item == null) continue;
String topicName = item.getString("topic_name");
if (topicName == null || topicName.isEmpty()) continue;
int discussNum = item.getIntValue("discuss_num", 0);
int readNum = item.getIntValue("read_num", 0);
if (isSportsRelated(topicName)) {
sportsHotList.add(item);
String line = String.format("序号:%d\t阅读:%d\t讨论:%d\t话题:%s", i + 1, readNum, discussNum, topicName);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
summary = "\n体育相关热搜总数:" + sportsHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (sportsHotList.isEmpty()) {
String emptyMsg = "当前贴吧热搜暂无体育相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
System.out.println("\n===== 百度贴吧 - 国家政策相关热搜 =====");
outputBuilder.append("\n--- 国家政策相关热搜 ---\n");
for (int i = 0; i < topics.size(); i++) {
JSONObject item = topics.getJSONObject(i);
if (item == null) continue;
String topicName = item.getString("topic_name");
if (topicName == null || topicName.isEmpty()) continue;
int discussNum = item.getIntValue("discuss_num", 0);
int readNum = item.getIntValue("read_num", 0);
if (isPolicyRelated(topicName)) {
policyHotList.add(item);
String line = String.format("序号:%d\t阅读:%d\t讨论:%d\t话题:%s", i + 1, readNum, discussNum, topicName);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
summary = "\n国家政策相关热搜总数:" + policyHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (policyHotList.isEmpty()) {
String emptyMsg = "当前贴吧热搜暂无国家政策相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
}
private static void parseAndFilterZhihu(String json) {
try {
JSONObject root = JSONObject.parseObject(json);
if (root == null) {
System.out.println("知乎数据格式错误:无法解析JSON");
outputBuilder.append("数据格式错误:无法解析JSON\n");
return;
}
// 尝试多种数据结构
JSONArray data = null;
// 结构1:直接在 data 数组中
if (root.containsKey("data") && root.get("data") instanceof JSONArray) {
data = root.getJSONArray("data");
}
// 结构2:在 data.topics 数组中
else if (root.containsKey("data")) {
JSONObject dataObj = root.getJSONObject("data");
if (dataObj != null && dataObj.containsKey("topics")) {
data = dataObj.getJSONArray("topics");
}
}
// 结构3:在 top_search.words 数组中(知乎搜索API)
else if (root.containsKey("top_search")) {
JSONObject topSearch = root.getJSONObject("top_search");
if (topSearch != null && topSearch.containsKey("words")) {
data = topSearch.getJSONArray("words");
}
}
// 结构4:直接是数组
else if (json.startsWith("[")) {
data = JSONArray.parseArray(json);
}
if (data == null || data.isEmpty()) {
System.out.println("知乎热搜数据为空或格式不匹配");
outputBuilder.append("热搜数据为空或格式不匹配\n");
return;
}
List<JSONObject> starHotList = new ArrayList<>();
List<JSONObject> sportsHotList = new ArrayList<>();
List<JSONObject> policyHotList = new ArrayList<>();
System.out.println("\n===== 知乎 - 明星相关热搜 =====");
outputBuilder.append("\n--- 明星相关热搜 ---\n");
for (int i = 0; i < data.size(); i++) {
JSONObject item = data.getJSONObject(i);
if (item == null) continue;
// 尝试多种标题字段
String title = null;
if (item.containsKey("title")) {
title = item.getString("title");
} else if (item.containsKey("topic_title")) {
title = item.getString("topic_title");
} else if (item.containsKey("name")) {
title = item.getString("name");
} else if (item.containsKey("target")) {
JSONObject target = item.getJSONObject("target");
if (target != null) {
title = target.getString("title");
}
} else if (item.containsKey("display_query")) {
title = item.getString("display_query");
} else if (item.containsKey("query")) {
title = item.getString("query");
}
if (title == null || title.isEmpty()) continue;
// 尝试获取热度值
long hotValue = 0;
if (item.containsKey("hot_score")) {
hotValue = item.getLongValue("hot_score", 0);
} else if (item.containsKey("score")) {
hotValue = item.getLongValue("score", 0);
} else if (item.containsKey("detail_text")) {
String detailText = item.getString("detail_text");
if (detailText != null) {
try {
String numStr = detailText.replaceAll("[^0-9]", "");
if (!numStr.isEmpty()) {
hotValue = Long.parseLong(numStr);
}
} catch (Exception e) {
hotValue = 0;
}
}
}
int rank = i + 1;
if (isStarRelated(title)) {
starHotList.add(item);
String line = String.format("排名:%d\t热度:%d\t热搜:%s", rank, hotValue, title);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
String summary = "\n明星相关热搜总数:" + starHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (starHotList.isEmpty()) {
String emptyMsg = "当前知乎热搜暂无明星相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
System.out.println("\n===== 知乎 - 体育相关热搜 =====");
outputBuilder.append("\n--- 体育相关热搜 ---\n");
for (int i = 0; i < data.size(); i++) {
JSONObject item = data.getJSONObject(i);
if (item == null) continue;
String title = null;
if (item.containsKey("title")) {
title = item.getString("title");
} else if (item.containsKey("topic_title")) {
title = item.getString("topic_title");
} else if (item.containsKey("name")) {
title = item.getString("name");
} else if (item.containsKey("target")) {
JSONObject target = item.getJSONObject("target");
if (target != null) {
title = target.getString("title");
}
}
if (title == null || title.isEmpty()) continue;
long hotValue = 0;
if (item.containsKey("hot_score")) {
hotValue = item.getLongValue("hot_score", 0);
} else if (item.containsKey("score")) {
hotValue = item.getLongValue("score", 0);
}
int rank = i + 1;
if (isSportsRelated(title)) {
sportsHotList.add(item);
String line = String.format("排名:%d\t热度:%d\t热搜:%s", rank, hotValue, title);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
summary = "\n体育相关热搜总数:" + sportsHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (sportsHotList.isEmpty()) {
String emptyMsg = "当前知乎热搜暂无体育相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
System.out.println("\n===== 知乎 - 国家政策相关热搜 =====");
outputBuilder.append("\n--- 国家政策相关热搜 ---\n");
for (int i = 0; i < data.size(); i++) {
JSONObject item = data.getJSONObject(i);
if (item == null) continue;
String title = null;
if (item.containsKey("title")) {
title = item.getString("title");
} else if (item.containsKey("topic_title")) {
title = item.getString("topic_title");
} else if (item.containsKey("name")) {
title = item.getString("name");
} else if (item.containsKey("target")) {
JSONObject target = item.getJSONObject("target");
if (target != null) {
title = target.getString("title");
}
}
if (title == null || title.isEmpty()) continue;
long hotValue = 0;
if (item.containsKey("hot_score")) {
hotValue = item.getLongValue("hot_score", 0);
} else if (item.containsKey("score")) {
hotValue = item.getLongValue("score", 0);
}
int rank = i + 1;
if (isPolicyRelated(title)) {
policyHotList.add(item);
String line = String.format("排名:%d\t热度:%d\t热搜:%s", rank, hotValue, title);
System.out.println(line);
outputBuilder.append(line).append("\n");
}
}
summary = "\n国家政策相关热搜总数:" + policyHotList.size() + " 条";
System.out.println(summary);
outputBuilder.append(summary).append("\n");
if (policyHotList.isEmpty()) {
String emptyMsg = "当前知乎热搜暂无国家政策相关内容";
System.out.println(emptyMsg);
outputBuilder.append(emptyMsg).append("\n");
}
} catch (Exception e) {
System.out.println("知乎数据解析异常: " + e.getMessage());
outputBuilder.append("数据解析异常: " + e.getMessage() + "\n");
e.printStackTrace();
}
}
private static boolean isStarRelated(String word) {
if (word == null || word.isEmpty()) {
return false;
}
for (String keyword : STAR_KEYWORDS) {
if (word.contains(keyword)) {
return true;
}
}
return false;
}
private static boolean isSportsRelated(String word) {
if (word == null || word.isEmpty()) {
return false;
}
for (String keyword : SPORTS_KEYWORDS) {
if (word.contains(keyword)) {
return true;
}
}
return false;
}
private static boolean isPolicyRelated(String word) {
if (word == null || word.isEmpty()) {
return false;
}
for (String keyword : POLICY_KEYWORDS) {
if (word.contains(keyword)) {
return true;
}
}
return false;
}
private static String getCurrentTime() {
return new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date());
}
private static String saveToFile() throws IOException {
File dir = new File(OUTPUT_DIR);
if (!dir.exists()) {
dir.mkdirs();
}
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String filename = "hotsearch_" + timestamp + ".txt";
String filepath = OUTPUT_DIR + File.separator + filename;
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filepath))) {
writer.write(outputBuilder.toString());
}
return filepath;
}
}

30
w12/总代码/src/main/java/com/weibo/hotsearch/ConsoleOutputHandler.java

@ -1,30 +0,0 @@
package com.weibo.hotsearch;
import com.alibaba.fastjson2.JSONObject;
import java.util.List;
public class ConsoleOutputHandler extends OutputHandler {
@Override
public void output(List<JSONObject> hotList, String filterName) {
System.out.println("\n===== " + filterName + " =====");
if (hotList == null || hotList.isEmpty()) {
System.out.println("当前暂无符合条件的热搜内容");
return;
}
for (int i = 0; i < hotList.size(); i++) {
JSONObject item = hotList.get(i);
System.out.println(formatHotItem(item, i, null));
}
System.out.println("\n===== 热搜总数:" + hotList.size() + " 条 =====");
}
@Override
public String getOutputType() {
return "控制台输出";
}
}

24
w12/总代码/src/main/java/com/weibo/hotsearch/HotSearchFilter.java

@ -1,24 +0,0 @@
package com.weibo.hotsearch;
public abstract class HotSearchFilter {
protected String[] keywords;
public HotSearchFilter(String[] keywords) {
this.keywords = keywords;
}
public boolean matches(String word) {
if (word == null || word.isEmpty()) {
return false;
}
for (String keyword : keywords) {
if (word.contains(keyword)) {
return true;
}
}
return false;
}
public abstract String getFilterName();
}

16
w12/总代码/src/main/java/com/weibo/hotsearch/Main.java

@ -1,16 +0,0 @@
package com.weibo.hotsearch;
import com.weibo.hotsearch.cli.CliHandler;
public class Main {
public static void main(String[] args) {
try {
CliHandler handler = new CliHandler(args);
handler.handle();
} catch (Exception e) {
System.err.println("程序执行异常: " + e.getMessage());
e.printStackTrace();
}
}
}

46
w12/总代码/src/main/java/com/weibo/hotsearch/OutputHandler.java

@ -1,46 +0,0 @@
package com.weibo.hotsearch;
import com.alibaba.fastjson2.JSONObject;
import java.util.List;
public abstract class OutputHandler {
public abstract void output(List<JSONObject> hotList, String filterName);
public abstract String getOutputType();
protected String formatHotItem(JSONObject item, int index, String dataSourceName) {
String word = getHotSearchWord(item);
long num = getHotSearchNum(item);
int rank = getHotSearchRank(item);
if (rank > 0) {
return String.format("排名:%d\t热度:%d\t热搜:%s", rank, num, word);
} else {
return String.format("序号:%d\t热度:%d\t热搜:%s", index + 1, num, word);
}
}
protected String getHotSearchWord(JSONObject item) {
if (item == null) return "未知";
String word = item.getString("word");
if (word == null || word.isEmpty()) {
word = item.getString("topic_name");
}
if (word == null || word.isEmpty()) {
word = item.getString("title");
}
return word != null ? word : "未知";
}
protected long getHotSearchNum(JSONObject item) {
if (item == null) return 0;
return item.getLongValue("num", 0);
}
protected int getHotSearchRank(JSONObject item) {
if (item == null) return 0;
return item.getIntValue("rank", 0);
}
}

18
w12/总代码/src/main/java/com/weibo/hotsearch/StarFilter.java

@ -1,18 +0,0 @@
package com.weibo.hotsearch;
public class StarFilter extends HotSearchFilter {
private static final String[] STAR_KEYWORDS = {
"明星", "演员", "歌手", "爱豆", "艺人", "红毯", "综艺", "新剧",
"恋情", "官宣", "演唱会", "代言", "造型", "封面"
};
public StarFilter() {
super(STAR_KEYWORDS);
}
@Override
public String getFilterName() {
return "明星相关热搜";
}
}

133
w12/总代码/src/main/java/com/weibo/hotsearch/cli/CliHandler.java

@ -1,133 +0,0 @@
package com.weibo.hotsearch.cli;
import com.weibo.hotsearch.controller.HotSearchController;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
public class CliHandler {
private final CliParser parser;
private final HotSearchController controller;
public CliHandler(String[] args) {
this.parser = new CliParser();
this.controller = new HotSearchController();
this.parser.parse(args);
}
public void handle() {
String command = parser.getCommand();
if (command == null || command.isEmpty()) {
parser.printUsage();
return;
}
try {
switch (command.toLowerCase()) {
case "help":
parser.printUsage();
break;
case "fetch":
handleFetch();
break;
case "filter":
handleFilter();
break;
case "output":
handleOutput();
break;
case "save":
handleSave();
break;
case "run":
handleRun();
break;
default:
throw new HotSearchException(ErrorCode.CLI_COMMAND_NOT_FOUND, "未知命令: " + command);
}
} catch (HotSearchException e) {
System.err.println("\n错误 [" + e.getErrorCode().getCode() + "]: " + e.getMessage());
if (e.getCause() != null) {
e.getCause().printStackTrace();
}
}
}
private void handleFetch() throws HotSearchException {
String source = parser.getOption("s");
if (source == null) {
source = parser.getOption("source");
}
if (source == null) {
throw new HotSearchException(ErrorCode.PARAMETER_ERROR, "请指定数据源 (-s 或 --source)");
}
controller.executeFetch(source);
}
private void handleFilter() throws HotSearchException {
String filter = parser.getOption("f");
if (filter == null) {
filter = parser.getOption("filter");
}
if (filter == null) {
throw new HotSearchException(ErrorCode.PARAMETER_ERROR, "请指定过滤器 (-f 或 --filter)");
}
controller.executeFilter(filter);
}
private void handleOutput() throws HotSearchException {
String output = parser.getOption("o");
if (output == null) {
output = parser.getOption("output");
}
if (output == null) {
output = "console";
}
controller.executeOutput(output);
}
private void handleSave() throws HotSearchException {
String path = parser.getOption("p");
if (path == null) {
path = parser.getOption("path");
}
controller.executeSave(path);
}
private void handleRun() throws HotSearchException {
String source = parser.getOption("s");
if (source == null) {
source = parser.getOption("source");
}
if (source == null) {
source = "all";
}
String filter = parser.getOption("f");
if (filter == null) {
filter = parser.getOption("filter");
}
if (filter == null) {
filter = "star";
}
String output = parser.getOption("o");
if (output == null) {
output = parser.getOption("output");
}
if (output == null) {
output = "console";
}
String path = parser.getOption("p");
if (path == null) {
path = parser.getOption("path");
}
controller.executeFetch(source);
controller.executeFilter(filter);
controller.executeOutput(output);
controller.executeSave(path);
}
}

101
w12/总代码/src/main/java/com/weibo/hotsearch/cli/CliParser.java

@ -1,101 +0,0 @@
package com.weibo.hotsearch.cli;
import com.weibo.hotsearch.exception.CliException;
import com.weibo.hotsearch.exception.ErrorCode;
import java.util.*;
public class CliParser {
private final Map<String, String> options = new HashMap<>();
private final List<String> arguments = new ArrayList<>();
private String command;
public void parse(String[] args) {
if (args == null || args.length == 0) {
printUsage();
return;
}
int i = 0;
while (i < args.length) {
String arg = args[i];
if (arg.startsWith("--")) {
String[] parts = arg.substring(2).split("=", 2);
String key = parts[0];
String value = parts.length > 1 ? parts[1] : "true";
options.put(key, value);
i++;
} else if (arg.startsWith("-")) {
String key = arg.substring(1);
if (key.length() == 1) {
String value = "true";
if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
value = args[i + 1];
i++;
}
options.put(key, value);
} else {
for (char c : key.toCharArray()) {
options.put(String.valueOf(c), "true");
}
}
i++;
} else {
if (command == null) {
command = arg;
} else {
arguments.add(arg);
}
i++;
}
}
}
public String getCommand() {
return command;
}
public String getOption(String key) {
return options.get(key);
}
public boolean hasOption(String key) {
return options.containsKey(key);
}
public List<String> getArguments() {
return arguments;
}
public Map<String, String> getAllOptions() {
return new HashMap<>(options);
}
public void printUsage() {
System.out.println("\n===== 热搜数据采集工具 =====");
System.out.println("用法:");
System.out.println(" java -jar weibo-hotsearch-1.0-SNAPSHOT-jar-with-dependencies.jar [命令] [选项]");
System.out.println("\n命令:");
System.out.println(" fetch 获取热搜数据");
System.out.println(" filter 过滤热搜数据");
System.out.println(" output 输出热搜数据");
System.out.println(" save 保存数据到文件");
System.out.println(" run 执行完整流程");
System.out.println(" help 显示帮助信息");
System.out.println("\n选项:");
System.out.println(" -s, --source <数据源> 指定数据源: weibo/tieba/zhihu/all");
System.out.println(" -f, --filter <过滤器> 指定过滤器: star/sports/policy");
System.out.println(" -o, --output <类型> 指定输出类型: console/text");
System.out.println(" -p, --path <路径> 指定保存路径");
System.out.println(" -h, --help 显示帮助信息");
System.out.println("\n示例:");
System.out.println(" java -jar xxx.jar run -s weibo -f star -o console");
System.out.println(" java -jar xxx.jar fetch -s all");
System.out.println(" java -jar xxx.jar filter -f sports");
System.out.println(" java -jar xxx.jar output -o console");
System.out.println(" java -jar xxx.jar save -p ./result.txt");
System.out.println();
}
}

12
w12/总代码/src/main/java/com/weibo/hotsearch/command/Command.java

@ -1,12 +0,0 @@
package com.weibo.hotsearch.command;
import com.weibo.hotsearch.exception.HotSearchException;
public interface Command {
void execute() throws HotSearchException;
String getCommandName();
String getDescription();
}

41
w12/总代码/src/main/java/com/weibo/hotsearch/command/CommandInvoker.java

@ -1,41 +0,0 @@
package com.weibo.hotsearch.command;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
import java.util.HashMap;
import java.util.Map;
public class CommandInvoker {
private final Map<String, Command> commands = new HashMap<>();
public void registerCommand(String name, Command command) {
commands.put(name.toLowerCase(), command);
}
public void executeCommand(String name) throws HotSearchException {
Command command = commands.get(name.toLowerCase());
if (command == null) {
throw new HotSearchException(ErrorCode.CLI_COMMAND_NOT_FOUND, "命令未找到: " + name);
}
command.execute();
}
public boolean hasCommand(String name) {
return commands.containsKey(name.toLowerCase());
}
public void printHelp() {
System.out.println("\n===== 命令帮助 =====");
System.out.println("可用命令:");
for (Map.Entry<String, Command> entry : commands.entrySet()) {
System.out.printf(" %-10s - %s%n", entry.getKey(), entry.getValue().getDescription());
}
System.out.println();
}
public Map<String, Command> getCommands() {
return new HashMap<>(commands);
}
}

47
w12/总代码/src/main/java/com/weibo/hotsearch/command/CommandResult.java

@ -1,47 +0,0 @@
package com.weibo.hotsearch.command;
public class CommandResult {
private boolean success;
private String message;
private Object data;
public CommandResult(boolean success, String message) {
this.success = success;
this.message = message;
}
public CommandResult(boolean success, String message, Object data) {
this.success = success;
this.message = message;
this.data = data;
}
public boolean isSuccess() {
return success;
}
public String getMessage() {
return message;
}
public Object getData() {
return data;
}
public static CommandResult success(String message) {
return new CommandResult(true, message);
}
public static CommandResult success(String message, Object data) {
return new CommandResult(true, message, data);
}
public static CommandResult failure(String message) {
return new CommandResult(false, message);
}
public static CommandResult failure(String message, Object data) {
return new CommandResult(false, message, data);
}
}

34
w12/总代码/src/main/java/com/weibo/hotsearch/command/FetchCommand.java

@ -1,34 +0,0 @@
package com.weibo.hotsearch.command;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.service.DataFetcher;
public class FetchCommand implements Command {
private final DataFetcher dataFetcher;
private final String source;
public FetchCommand(DataFetcher dataFetcher, String source) {
this.dataFetcher = dataFetcher;
this.source = source;
}
@Override
public void execute() throws HotSearchException {
if (source == null || source.isEmpty()) {
throw new HotSearchException(ErrorCode.PARAMETER_ERROR, "数据源不能为空");
}
dataFetcher.fetch(source);
}
@Override
public String getCommandName() {
return "fetch";
}
@Override
public String getDescription() {
return "从指定数据源获取热搜数据";
}
}

35
w12/总代码/src/main/java/com/weibo/hotsearch/command/FilterCommand.java

@ -1,35 +0,0 @@
package com.weibo.hotsearch.command;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.service.FilterService;
import com.weibo.hotsearch.strategy.FilterStrategy;
public class FilterCommand implements Command {
private final FilterService filterService;
private final FilterStrategy strategy;
public FilterCommand(FilterService filterService, FilterStrategy strategy) {
this.filterService = filterService;
this.strategy = strategy;
}
@Override
public void execute() throws HotSearchException {
if (strategy == null) {
throw new HotSearchException(ErrorCode.PARAMETER_ERROR, "过滤策略不能为空");
}
filterService.filter(strategy);
}
@Override
public String getCommandName() {
return "filter";
}
@Override
public String getDescription() {
return "使用指定策略过滤热搜数据";
}
}

27
w12/总代码/src/main/java/com/weibo/hotsearch/command/HelpCommand.java

@ -1,27 +0,0 @@
package com.weibo.hotsearch.command;
import com.weibo.hotsearch.exception.HotSearchException;
public class HelpCommand implements Command {
private final CommandInvoker invoker;
public HelpCommand(CommandInvoker invoker) {
this.invoker = invoker;
}
@Override
public void execute() throws HotSearchException {
invoker.printHelp();
}
@Override
public String getCommandName() {
return "help";
}
@Override
public String getDescription() {
return "显示帮助信息";
}
}

34
w12/总代码/src/main/java/com/weibo/hotsearch/command/OutputCommand.java

@ -1,34 +0,0 @@
package com.weibo.hotsearch.command;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.service.OutputService;
public class OutputCommand implements Command {
private final OutputService outputService;
private final String outputType;
public OutputCommand(OutputService outputService, String outputType) {
this.outputService = outputService;
this.outputType = outputType;
}
@Override
public void execute() throws HotSearchException {
if (outputType == null || outputType.isEmpty()) {
throw new HotSearchException(ErrorCode.PARAMETER_ERROR, "输出类型不能为空");
}
outputService.output(outputType);
}
@Override
public String getCommandName() {
return "output";
}
@Override
public String getDescription() {
return "输出过滤后的热搜数据";
}
}

30
w12/总代码/src/main/java/com/weibo/hotsearch/command/SaveCommand.java

@ -1,30 +0,0 @@
package com.weibo.hotsearch.command;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.service.OutputService;
public class SaveCommand implements Command {
private final OutputService outputService;
private final String filePath;
public SaveCommand(OutputService outputService, String filePath) {
this.outputService = outputService;
this.filePath = filePath;
}
@Override
public void execute() throws HotSearchException {
outputService.saveToFile(filePath);
}
@Override
public String getCommandName() {
return "save";
}
@Override
public String getDescription() {
return "保存数据到文件";
}
}

69
w12/总代码/src/main/java/com/weibo/hotsearch/controller/HotSearchController.java

@ -1,69 +0,0 @@
package com.weibo.hotsearch.controller;
import com.weibo.hotsearch.command.*;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.service.DataFetcher;
import com.weibo.hotsearch.service.FilterService;
import com.weibo.hotsearch.service.OutputService;
import com.weibo.hotsearch.strategy.FilterStrategy;
import com.weibo.hotsearch.strategy.FilterStrategyFactory;
public class HotSearchController {
private final DataFetcher dataFetcher;
private final FilterService filterService;
private final OutputService outputService;
private final CommandInvoker commandInvoker;
public HotSearchController() {
this.dataFetcher = new DataFetcher();
this.filterService = new FilterService();
this.outputService = new OutputService();
this.commandInvoker = new CommandInvoker();
registerCommands();
}
private void registerCommands() {
commandInvoker.registerCommand("help", new HelpCommand(commandInvoker));
}
public void executeFetch(String source) throws HotSearchException {
FetchCommand command = new FetchCommand(dataFetcher, source);
command.execute();
System.out.println("已从 " + source + " 获取数据");
}
public void executeFilter(String filterCode) throws HotSearchException {
FilterStrategy strategy = FilterStrategyFactory.getStrategy(filterCode);
if (strategy == null) {
throw new HotSearchException(com.weibo.hotsearch.exception.ErrorCode.PARAMETER_ERROR,
"未知的过滤策略: " + filterCode);
}
FilterCommand command = new FilterCommand(filterService, strategy);
command.execute();
System.out.println("已应用过滤策略: " + strategy.getFilterName());
}
public void executeOutput(String outputType) throws HotSearchException {
OutputCommand command = new OutputCommand(outputService, outputType);
command.execute();
}
public void executeSave(String filePath) throws HotSearchException {
SaveCommand command = new SaveCommand(outputService, filePath);
command.execute();
}
public void showHelp() throws HotSearchException {
commandInvoker.executeCommand("help");
}
public void processFullPipeline(String source, String filterCode, String outputType, String savePath) throws HotSearchException {
executeFetch(source);
executeFilter(filterCode);
executeOutput(outputType);
if (savePath != null || !savePath.isEmpty()) {
executeSave(savePath);
}
}
}

20
w12/总代码/src/main/java/com/weibo/hotsearch/exception/CliException.java

@ -1,20 +0,0 @@
package com.weibo.hotsearch.exception;
public class CliException extends HotSearchException {
public CliException(ErrorCode errorCode) {
super(errorCode);
}
public CliException(ErrorCode errorCode, Throwable cause) {
super(errorCode, cause);
}
public CliException(ErrorCode errorCode, String detail) {
super(errorCode, detail);
}
public CliException(ErrorCode errorCode, String detail, Throwable cause) {
super(errorCode, detail, cause);
}
}

20
w12/总代码/src/main/java/com/weibo/hotsearch/exception/DataParseException.java

@ -1,20 +0,0 @@
package com.weibo.hotsearch.exception;
public class DataParseException extends HotSearchException {
public DataParseException(ErrorCode errorCode) {
super(errorCode);
}
public DataParseException(ErrorCode errorCode, Throwable cause) {
super(errorCode, cause);
}
public DataParseException(ErrorCode errorCode, String detail) {
super(errorCode, detail);
}
public DataParseException(ErrorCode errorCode, String detail, Throwable cause) {
super(errorCode, detail, cause);
}
}

47
w12/总代码/src/main/java/com/weibo/hotsearch/exception/ErrorCode.java

@ -1,47 +0,0 @@
package com.weibo.hotsearch.exception;
public enum ErrorCode {
// 通用错误
SUCCESS(0, "操作成功"),
UNKNOWN_ERROR(1000, "未知错误"),
PARAMETER_ERROR(1001, "参数错误"),
NOT_FOUND(1002, "资源未找到"),
DUPLICATE_ERROR(1003, "重复操作"),
// CLI错误
CLI_PARSE_ERROR(2001, "命令行参数解析错误"),
CLI_COMMAND_NOT_FOUND(2002, "命令未找到"),
CLI_INVALID_OPTION(2003, "无效的选项"),
// 网络错误
NETWORK_ERROR(3001, "网络请求失败"),
CONNECTION_TIMEOUT(3002, "连接超时"),
HTTP_ERROR(3003, "HTTP请求错误"),
// 数据错误
DATA_PARSE_ERROR(4001, "数据解析失败"),
DATA_FORMAT_ERROR(4002, "数据格式错误"),
DATA_EMPTY(4003, "数据为空"),
// 服务错误
SERVICE_UNAVAILABLE(5001, "服务不可用"),
SERVICE_RATE_LIMITED(5002, "请求被限流"),
AUTHENTICATION_FAILED(5003, "认证失败");
private final int code;
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

30
w12/总代码/src/main/java/com/weibo/hotsearch/exception/HotSearchException.java

@ -1,30 +0,0 @@
package com.weibo.hotsearch.exception;
public class HotSearchException extends Exception {
private final ErrorCode errorCode;
public HotSearchException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
public HotSearchException(ErrorCode errorCode, Throwable cause) {
super(errorCode.getMessage(), cause);
this.errorCode = errorCode;
}
public HotSearchException(ErrorCode errorCode, String detail) {
super(errorCode.getMessage() + ": " + detail);
this.errorCode = errorCode;
}
public HotSearchException(ErrorCode errorCode, String detail, Throwable cause) {
super(errorCode.getMessage() + ": " + detail, cause);
this.errorCode = errorCode;
}
public ErrorCode getErrorCode() {
return errorCode;
}
}

20
w12/总代码/src/main/java/com/weibo/hotsearch/exception/NetworkException.java

@ -1,20 +0,0 @@
package com.weibo.hotsearch.exception;
public class NetworkException extends HotSearchException {
public NetworkException(ErrorCode errorCode) {
super(errorCode);
}
public NetworkException(ErrorCode errorCode, Throwable cause) {
super(errorCode, cause);
}
public NetworkException(ErrorCode errorCode, String detail) {
super(errorCode, detail);
}
public NetworkException(ErrorCode errorCode, String detail, Throwable cause) {
super(errorCode, detail, cause);
}
}

49
w12/总代码/src/main/java/com/weibo/hotsearch/model/AppContext.java

@ -1,49 +0,0 @@
package com.weibo.hotsearch.model;
import java.util.HashMap;
import java.util.Map;
public class AppContext {
private static final AppContext instance = new AppContext();
private final Map<String, Object> attributes = new HashMap<>();
private HotSearchResult currentResult;
private AppContext() {
}
public static AppContext getInstance() {
return instance;
}
public void setAttribute(String key, Object value) {
attributes.put(key, value);
}
public Object getAttribute(String key) {
return attributes.get(key);
}
public void removeAttribute(String key) {
attributes.remove(key);
}
public boolean hasAttribute(String key) {
return attributes.containsKey(key);
}
public HotSearchResult getCurrentResult() {
return currentResult;
}
public void setCurrentResult(HotSearchResult currentResult) {
this.currentResult = currentResult;
}
public void clear() {
attributes.clear();
currentResult = null;
}
}

69
w12/总代码/src/main/java/com/weibo/hotsearch/model/HotSearchItem.java

@ -1,69 +0,0 @@
package com.weibo.hotsearch.model;
import java.time.LocalDateTime;
public class HotSearchItem {
private String title;
private long hotValue;
private int rank;
private String source;
private LocalDateTime fetchTime;
public HotSearchItem() {
}
public HotSearchItem(String title, long hotValue, int rank, String source) {
this.title = title;
this.hotValue = hotValue;
this.rank = rank;
this.source = source;
this.fetchTime = LocalDateTime.now();
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getHotValue() {
return hotValue;
}
public void setHotValue(long hotValue) {
this.hotValue = hotValue;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public LocalDateTime getFetchTime() {
return fetchTime;
}
public void setFetchTime(LocalDateTime fetchTime) {
this.fetchTime = fetchTime;
}
@Override
public String toString() {
return String.format("HotSearchItem{title='%s', hotValue=%d, rank=%d, source='%s'}",
title, hotValue, rank, source);
}
}

75
w12/总代码/src/main/java/com/weibo/hotsearch/model/HotSearchResult.java

@ -1,75 +0,0 @@
package com.weibo.hotsearch.model;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class HotSearchResult {
private List<HotSearchItem> items;
private String filterName;
private String dataSource;
private LocalDateTime fetchTime;
private int totalCount;
public HotSearchResult() {
this.items = new ArrayList<>();
this.fetchTime = LocalDateTime.now();
}
public HotSearchResult(List<HotSearchItem> items, String filterName, String dataSource) {
this.items = items != null ? items : new ArrayList<>();
this.filterName = filterName;
this.dataSource = dataSource;
this.fetchTime = LocalDateTime.now();
this.totalCount = this.items.size();
}
public List<HotSearchItem> getItems() {
return items;
}
public void setItems(List<HotSearchItem> items) {
this.items = items != null ? items : new ArrayList<>();
this.totalCount = this.items.size();
}
public String getFilterName() {
return filterName;
}
public void setFilterName(String filterName) {
this.filterName = filterName;
}
public String getDataSource() {
return dataSource;
}
public void setDataSource(String dataSource) {
this.dataSource = dataSource;
}
public LocalDateTime getFetchTime() {
return fetchTime;
}
public void setFetchTime(LocalDateTime fetchTime) {
this.fetchTime = fetchTime;
}
public int getTotalCount() {
return totalCount;
}
public void addItem(HotSearchItem item) {
if (item != null) {
this.items.add(item);
this.totalCount++;
}
}
public boolean isEmpty() {
return items == null || items.isEmpty();
}
}

307
w12/总代码/src/main/java/com/weibo/hotsearch/service/DataFetcher.java

@ -1,307 +0,0 @@
package com.weibo.hotsearch.service;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.weibo.hotsearch.exception.DataParseException;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.exception.NetworkException;
import com.weibo.hotsearch.model.AppContext;
import com.weibo.hotsearch.model.HotSearchItem;
import com.weibo.hotsearch.model.HotSearchResult;
import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.util.Timeout;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class DataFetcher {
private static final String WEIBO_URL = "https://weibo.com/ajax/side/hotSearch";
private static final String TIEBA_URL = "https://tieba.baidu.com/hottopic/browse/topicList";
private static final String ZHIHU_URL = "https://www.zhihu.com/api/v4/search/top_search";
private static final int CONNECT_TIMEOUT = 10000;
private static final int RESPONSE_TIMEOUT = 10000;
private static final int MAX_RETRIES = 3;
public void fetch(String source) throws HotSearchException {
List<HotSearchItem> items = new ArrayList<>();
switch (source.toLowerCase()) {
case "weibo":
items = fetchWeibo();
break;
case "tieba":
items = fetchTieba();
break;
case "zhihu":
items = fetchZhihu();
break;
case "all":
items.addAll(fetchWeibo());
items.addAll(fetchTieba());
items.addAll(fetchZhihu());
break;
default:
throw new HotSearchException(ErrorCode.PARAMETER_ERROR, "未知数据源: " + source);
}
HotSearchResult result = new HotSearchResult(items, null, source);
AppContext.getInstance().setCurrentResult(result);
}
private List<HotSearchItem> fetchWeibo() throws HotSearchException {
List<HotSearchItem> items = new ArrayList<>();
try {
String json = fetchUrlWithRetry(WEIBO_URL, "https://weibo.com/");
JSONObject root = JSONObject.parseObject(json);
if (!root.containsKey("data")) {
throw new DataParseException(ErrorCode.DATA_FORMAT_ERROR, "微博数据格式错误");
}
JSONObject data = root.getJSONObject("data");
if (!data.containsKey("realtime")) {
throw new DataParseException(ErrorCode.DATA_EMPTY, "微博数据为空");
}
JSONArray realtime = data.getJSONArray("realtime");
for (int i = 0; i < realtime.size(); i++) {
JSONObject item = realtime.getJSONObject(i);
if (item != null) {
HotSearchItem hotItem = parseWeiboItem(item);
if (hotItem != null) {
items.add(hotItem);
}
}
}
} catch (NetworkException e) {
throw e;
} catch (Exception e) {
throw new DataParseException(ErrorCode.DATA_PARSE_ERROR, "微博数据解析失败", e);
}
return items;
}
private HotSearchItem parseWeiboItem(JSONObject item) {
String word = item.getString("word");
if (word == null || word.isEmpty()) {
return null;
}
long num = item.getLongValue("num", 0);
int rank = item.getIntValue("rank", 0);
return new HotSearchItem(word, num, rank, "微博");
}
private List<HotSearchItem> fetchTieba() throws HotSearchException {
List<HotSearchItem> items = new ArrayList<>();
try {
String json = fetchUrlWithRetry(TIEBA_URL, "https://tieba.baidu.com/");
JSONObject root = JSONObject.parseObject(json);
if (!root.containsKey("data")) {
throw new DataParseException(ErrorCode.DATA_FORMAT_ERROR, "贴吧数据格式错误");
}
JSONObject data = root.getJSONObject("data");
if (!data.containsKey("bang_topic")) {
throw new DataParseException(ErrorCode.DATA_EMPTY, "贴吧数据为空");
}
JSONArray topics = data.getJSONArray("bang_topic");
for (int i = 0; i < topics.size(); i++) {
JSONObject item = topics.getJSONObject(i);
if (item != null) {
HotSearchItem hotItem = parseTiebaItem(item, i + 1);
if (hotItem != null) {
items.add(hotItem);
}
}
}
} catch (NetworkException e) {
throw e;
} catch (Exception e) {
throw new DataParseException(ErrorCode.DATA_PARSE_ERROR, "贴吧数据解析失败", e);
}
return items;
}
private HotSearchItem parseTiebaItem(JSONObject item, int index) {
String topicName = item.getString("topic_name");
if (topicName == null || topicName.isEmpty()) {
return null;
}
int readNum = item.getIntValue("read_num", 0);
int discussNum = item.getIntValue("discuss_num", 0);
return new HotSearchItem(topicName, (long) readNum + discussNum, 0, "百度贴吧");
}
private List<HotSearchItem> fetchZhihu() throws HotSearchException {
List<HotSearchItem> items = new ArrayList<>();
try {
String json = fetchUrlWithRetry(ZHIHU_URL, "https://zhuanlan.zhihu.com/");
JSONObject root = JSONObject.parseObject(json);
JSONArray data = findZhihuData(root, json);
if (data == null || data.isEmpty()) {
throw new DataParseException(ErrorCode.DATA_EMPTY, "知乎数据为空");
}
for (int i = 0; i < data.size(); i++) {
JSONObject item = data.getJSONObject(i);
if (item != null) {
HotSearchItem hotItem = parseZhihuItem(item, i + 1);
if (hotItem != null) {
items.add(hotItem);
}
}
}
} catch (NetworkException e) {
throw e;
} catch (Exception e) {
throw new DataParseException(ErrorCode.DATA_PARSE_ERROR, "知乎数据解析失败", e);
}
return items;
}
private JSONArray findZhihuData(JSONObject root, String json) {
if (root.containsKey("data") && root.get("data") instanceof JSONArray) {
return root.getJSONArray("data");
} else if (root.containsKey("data")) {
JSONObject dataObj = root.getJSONObject("data");
if (dataObj != null && dataObj.containsKey("topics")) {
return dataObj.getJSONArray("topics");
}
} else if (root.containsKey("top_search")) {
JSONObject topSearch = root.getJSONObject("top_search");
if (topSearch != null && topSearch.containsKey("words")) {
return topSearch.getJSONArray("words");
}
} else if (json.startsWith("[")) {
return JSONArray.parseArray(json);
}
return null;
}
private HotSearchItem parseZhihuItem(JSONObject item, int index) {
String title = getItemTitle(item);
if (title == null || title.isEmpty()) {
return null;
}
long hotValue = 0;
if (item.containsKey("hot_score")) {
hotValue = item.getLongValue("hot_score", 0);
} else if (item.containsKey("score")) {
hotValue = item.getLongValue("score", 0);
} else if (item.containsKey("detail_text")) {
String detailText = item.getString("detail_text");
if (detailText != null) {
try {
String numStr = detailText.replaceAll("[^0-9]", "");
if (!numStr.isEmpty()) {
hotValue = Long.parseLong(numStr);
}
} catch (Exception e) {
hotValue = 0;
}
}
}
return new HotSearchItem(title, hotValue, index, "知乎");
}
private String getItemTitle(JSONObject item) {
if (item == null) {
return null;
}
String title = item.getString("title");
if (title != null && !title.isEmpty()) {
return title;
}
title = item.getString("topic_title");
if (title != null && !title.isEmpty()) {
return title;
}
title = item.getString("name");
if (title != null && !title.isEmpty()) {
return title;
}
if (item.containsKey("target")) {
JSONObject target = item.getJSONObject("target");
if (target != null) {
title = target.getString("title");
if (title != null && !title.isEmpty()) {
return title;
}
}
}
title = item.getString("display_query");
if (title != null && !title.isEmpty()) {
return title;
}
return item.getString("query");
}
private String fetchUrlWithRetry(String url, String referer) throws NetworkException {
int retryCount = 0;
Exception lastException = null;
while (retryCount < MAX_RETRIES) {
try {
return Request.get(url)
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
.addHeader("Referer", referer)
.addHeader("Accept", "application/json, text/plain, */*;charset=UTF-8")
.addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
.addHeader("Accept-Encoding", "identity")
.addHeader("Connection", "keep-alive")
.addHeader("Content-Type", "application/json;charset=UTF-8")
.connectTimeout(Timeout.ofMilliseconds(CONNECT_TIMEOUT))
.responseTimeout(Timeout.ofMilliseconds(RESPONSE_TIMEOUT))
.execute()
.returnContent()
.asString(StandardCharsets.UTF_8);
} catch (java.net.SocketTimeoutException e) {
lastException = e;
retryCount++;
if (retryCount >= MAX_RETRIES) {
throw new NetworkException(ErrorCode.CONNECTION_TIMEOUT, "连接超时", e);
}
sleep(2000);
} catch (java.net.ConnectException e) {
lastException = e;
retryCount++;
if (retryCount >= MAX_RETRIES) {
throw new NetworkException(ErrorCode.NETWORK_ERROR, "连接失败", e);
}
sleep(2000);
} catch (Exception e) {
lastException = e;
retryCount++;
if (retryCount >= MAX_RETRIES) {
throw new NetworkException(ErrorCode.NETWORK_ERROR, "网络请求失败", e);
}
sleep(2000);
}
}
throw new NetworkException(ErrorCode.NETWORK_ERROR, "网络请求失败", lastException);
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

44
w12/总代码/src/main/java/com/weibo/hotsearch/service/FilterService.java

@ -1,44 +0,0 @@
package com.weibo.hotsearch.service;
import com.alibaba.fastjson2.JSONObject;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.model.AppContext;
import com.weibo.hotsearch.model.HotSearchItem;
import com.weibo.hotsearch.model.HotSearchResult;
import com.weibo.hotsearch.strategy.FilterStrategy;
import java.util.ArrayList;
import java.util.List;
public class FilterService {
public void filter(FilterStrategy strategy) throws HotSearchException {
HotSearchResult currentResult = AppContext.getInstance().getCurrentResult();
if (currentResult == null || currentResult.isEmpty()) {
throw new HotSearchException(ErrorCode.DATA_EMPTY, "没有可过滤的数据,请先获取数据");
}
List<HotSearchItem> filteredItems = new ArrayList<>();
for (HotSearchItem item : currentResult.getItems()) {
JSONObject jsonItem = convertToJson(item);
if (strategy.match(jsonItem)) {
filteredItems.add(item);
}
}
HotSearchResult filteredResult = new HotSearchResult(filteredItems, strategy.getFilterName(), currentResult.getDataSource());
AppContext.getInstance().setCurrentResult(filteredResult);
}
private JSONObject convertToJson(HotSearchItem item) {
JSONObject json = new JSONObject();
json.put("word", item.getTitle());
json.put("title", item.getTitle());
json.put("num", item.getHotValue());
json.put("rank", item.getRank());
return json;
}
}

66
w12/总代码/src/main/java/com/weibo/hotsearch/service/OutputService.java

@ -1,66 +0,0 @@
package com.weibo.hotsearch.service;
import com.weibo.hotsearch.exception.ErrorCode;
import com.weibo.hotsearch.exception.HotSearchException;
import com.weibo.hotsearch.model.AppContext;
import com.weibo.hotsearch.model.HotSearchResult;
import com.weibo.hotsearch.view.TextView;
import com.weibo.hotsearch.view.View;
import com.weibo.hotsearch.view.ViewFactory;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class OutputService {
private static final DateTimeFormatter FILE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
private static final String OUTPUT_DIR = "hotsearch_results";
public void output(String outputType) throws HotSearchException {
HotSearchResult result = AppContext.getInstance().getCurrentResult();
if (result == null) {
throw new HotSearchException(ErrorCode.DATA_EMPTY, "没有可输出的数据");
}
View view = ViewFactory.getView(outputType);
view.render(result);
}
public void saveToFile(String filePath) throws HotSearchException {
HotSearchResult result = AppContext.getInstance().getCurrentResult();
if (result == null) {
throw new HotSearchException(ErrorCode.DATA_EMPTY, "没有可保存的数据");
}
try {
File dir = new File(OUTPUT_DIR);
if (!dir.exists()) {
dir.mkdirs();
}
String actualPath = filePath;
if (filePath == null || filePath.isEmpty()) {
String timestamp = LocalDateTime.now().format(FILE_FORMATTER);
actualPath = OUTPUT_DIR + File.separator + "hotsearch_" + timestamp + ".txt";
}
TextView textView = (TextView) ViewFactory.getView("text");
String content = textView.renderToString(result);
try (BufferedWriter writer = new BufferedWriter(new FileWriter(actualPath))) {
writer.write(content);
}
System.out.println("\n结果已保存到文件: " + actualPath);
} catch (IOException e) {
throw new HotSearchException(ErrorCode.UNKNOWN_ERROR, "保存文件失败", e);
}
}
}

12
w12/总代码/src/main/java/com/weibo/hotsearch/strategy/FilterStrategy.java

@ -1,12 +0,0 @@
package com.weibo.hotsearch.strategy;
import com.alibaba.fastjson2.JSONObject;
public interface FilterStrategy {
boolean match(JSONObject item);
String getFilterName();
String getFilterCode();
}

30
w12/总代码/src/main/java/com/weibo/hotsearch/strategy/FilterStrategyFactory.java

@ -1,30 +0,0 @@
package com.weibo.hotsearch.strategy;
import java.util.HashMap;
import java.util.Map;
public class FilterStrategyFactory {
private static final Map<String, FilterStrategy> strategies = new HashMap<>();
static {
strategies.put("star", new StarFilterStrategy());
strategies.put("sports", new SportsFilterStrategy());
strategies.put("policy", new PolicyFilterStrategy());
}
public static FilterStrategy getStrategy(String code) {
if (code == null || code.isEmpty()) {
return null;
}
return strategies.get(code.toLowerCase());
}
public static Map<String, FilterStrategy> getAllStrategies() {
return new HashMap<>(strategies);
}
public static boolean hasStrategy(String code) {
return code != null && strategies.containsKey(code.toLowerCase());
}
}

55
w12/总代码/src/main/java/com/weibo/hotsearch/strategy/PolicyFilterStrategy.java

@ -1,55 +0,0 @@
package com.weibo.hotsearch.strategy;
import com.alibaba.fastjson2.JSONObject;
public class PolicyFilterStrategy implements FilterStrategy {
private static final String[] KEYWORDS = {
"政策", "新规", "条例", "法规", "通知", "公告", "发布",
"国务院", "发改委", "财政部", "教育部", "工信部", "科技部",
"税收", "补贴", "优惠", "扶持", "改革", "开放", "创新",
"十四五", "计划", "规划", "方案", "意见", "办法", "细则",
"经济", "金融", "市场", "监管", "安全", "环保", "绿色"
};
@Override
public boolean match(JSONObject item) {
if (item == null) {
return false;
}
String word = getItemTitle(item);
if (word == null || word.isEmpty()) {
return false;
}
for (String keyword : KEYWORDS) {
if (word.contains(keyword)) {
return true;
}
}
return false;
}
@Override
public String getFilterName() {
return "国家政策相关热搜";
}
@Override
public String getFilterCode() {
return "policy";
}
private String getItemTitle(JSONObject item) {
String title = item.getString("word");
if (title == null || title.isEmpty()) {
title = item.getString("topic_name");
}
if (title == null || title.isEmpty()) {
title = item.getString("title");
}
if (title == null || title.isEmpty()) {
title = item.getString("name");
}
return title;
}
}

54
w12/总代码/src/main/java/com/weibo/hotsearch/strategy/SportsFilterStrategy.java

@ -1,54 +0,0 @@
package com.weibo.hotsearch.strategy;
import com.alibaba.fastjson2.JSONObject;
public class SportsFilterStrategy implements FilterStrategy {
private static final String[] KEYWORDS = {
"足球", "篮球", "世界杯", "NBA", "CBA", "奥运会", "世锦赛",
"冠军", "比赛", "夺冠", "进球", "比分", "运动员", "国足",
"乒乓", "排球", "羽毛球", "游泳", "田径", "体操", "跳水",
"MVP", "转会", "联赛", "中超", "英超", "西甲", "欧冠"
};
@Override
public boolean match(JSONObject item) {
if (item == null) {
return false;
}
String word = getItemTitle(item);
if (word == null || word.isEmpty()) {
return false;
}
for (String keyword : KEYWORDS) {
if (word.contains(keyword)) {
return true;
}
}
return false;
}
@Override
public String getFilterName() {
return "体育相关热搜";
}
@Override
public String getFilterCode() {
return "sports";
}
private String getItemTitle(JSONObject item) {
String title = item.getString("word");
if (title == null || title.isEmpty()) {
title = item.getString("topic_name");
}
if (title == null || title.isEmpty()) {
title = item.getString("title");
}
if (title == null || title.isEmpty()) {
title = item.getString("name");
}
return title;
}
}

76
w12/总代码/src/main/java/com/weibo/hotsearch/strategy/StarFilterStrategy.java

@ -1,76 +0,0 @@
package com.weibo.hotsearch.strategy;
import com.alibaba.fastjson2.JSONObject;
public class StarFilterStrategy implements FilterStrategy {
private static final String[] KEYWORDS = {
"明星", "演员", "歌手", "爱豆", "艺人", "红毯", "综艺", "新剧",
"恋情", "官宣", "演唱会", "代言", "造型", "封面"
};
@Override
public boolean match(JSONObject item) {
if (item == null) {
return false;
}
String word = getItemTitle(item);
if (word == null || word.isEmpty()) {
return false;
}
for (String keyword : KEYWORDS) {
if (word.contains(keyword)) {
return true;
}
}
return false;
}
@Override
public String getFilterName() {
return "明星相关热搜";
}
@Override
public String getFilterCode() {
return "star";
}
private String getItemTitle(JSONObject item) {
if (item == null) {
return null;
}
String title = item.getString("word");
if (title != null && !title.isEmpty()) {
return title;
}
title = item.getString("topic_name");
if (title != null && !title.isEmpty()) {
return title;
}
title = item.getString("title");
if (title != null && !title.isEmpty()) {
return title;
}
title = item.getString("name");
if (title != null && !title.isEmpty()) {
return title;
}
if (item.containsKey("target")) {
JSONObject target = item.getJSONObject("target");
if (target != null) {
title = target.getString("title");
if (title != null && !title.isEmpty()) {
return title;
}
}
}
return title;
}
}

51
w12/总代码/src/main/java/com/weibo/hotsearch/view/ConsoleView.java

@ -1,51 +0,0 @@
package com.weibo.hotsearch.view;
import com.weibo.hotsearch.model.HotSearchItem;
import com.weibo.hotsearch.model.HotSearchResult;
import java.time.format.DateTimeFormatter;
public class ConsoleView implements View {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void render(HotSearchResult result) {
if (result == null) {
System.out.println("没有数据可显示");
return;
}
System.out.println("\n===== " + (result.getFilterName() != null ? result.getFilterName() : "热搜结果") + " =====");
System.out.println("数据源: " + result.getDataSource());
System.out.println("采集时间: " + result.getFetchTime().format(FORMATTER));
System.out.println("----------------------------------------");
if (result.isEmpty()) {
System.out.println("当前暂无符合条件的热搜内容");
} else {
for (int i = 0; i < result.getItems().size(); i++) {
HotSearchItem item = result.getItems().get(i);
String line = formatItem(item, i);
System.out.println(line);
}
}
System.out.println("\n===== 热搜总数:" + result.getTotalCount() + " 条 =====");
}
private String formatItem(HotSearchItem item, int index) {
if (item.getRank() > 0) {
return String.format("排名:%d\t热度:%d\t来源:%s\t热搜:%s",
item.getRank(), item.getHotValue(), item.getSource(), item.getTitle());
} else {
return String.format("序号:%d\t热度:%d\t来源:%s\t热搜:%s",
index + 1, item.getHotValue(), item.getSource(), item.getTitle());
}
}
@Override
public String getViewType() {
return "console";
}
}

83
w12/总代码/src/main/java/com/weibo/hotsearch/view/TextView.java

@ -1,83 +0,0 @@
package com.weibo.hotsearch.view;
import com.weibo.hotsearch.model.HotSearchItem;
import com.weibo.hotsearch.model.HotSearchResult;
import java.time.format.DateTimeFormatter;
import java.util.StringJoiner;
public class TextView implements View {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void render(HotSearchResult result) {
if (result == null) {
System.out.println("没有数据可显示");
return;
}
StringJoiner sj = new StringJoiner("\n");
sj.add("===== " + (result.getFilterName() != null ? result.getFilterName() : "热搜结果") + " =====");
sj.add("数据源: " + result.getDataSource());
sj.add("采集时间: " + result.getFetchTime().format(FORMATTER));
sj.add("----------------------------------------");
if (result.isEmpty()) {
sj.add("当前暂无符合条件的热搜内容");
} else {
for (int i = 0; i < result.getItems().size(); i++) {
HotSearchItem item = result.getItems().get(i);
sj.add(formatItem(item, i));
}
}
sj.add("");
sj.add("===== 热搜总数:" + result.getTotalCount() + " 条 =====");
System.out.println(sj.toString());
}
private String formatItem(HotSearchItem item, int index) {
if (item.getRank() > 0) {
return String.format("排名:%d\t热度:%d\t来源:%s\t热搜:%s",
item.getRank(), item.getHotValue(), item.getSource(), item.getTitle());
} else {
return String.format("序号:%d\t热度:%d\t来源:%s\t热搜:%s",
index + 1, item.getHotValue(), item.getSource(), item.getTitle());
}
}
public String renderToString(HotSearchResult result) {
if (result == null) {
return "没有数据可显示";
}
StringJoiner sj = new StringJoiner("\n");
sj.add("===== " + (result.getFilterName() != null ? result.getFilterName() : "热搜结果") + " =====");
sj.add("数据源: " + result.getDataSource());
sj.add("采集时间: " + result.getFetchTime().format(FORMATTER));
sj.add("----------------------------------------");
if (result.isEmpty()) {
sj.add("当前暂无符合条件的热搜内容");
} else {
for (int i = 0; i < result.getItems().size(); i++) {
HotSearchItem item = result.getItems().get(i);
sj.add(formatItem(item, i));
}
}
sj.add("");
sj.add("===== 热搜总数:" + result.getTotalCount() + " 条 =====");
return sj.toString();
}
@Override
public String getViewType() {
return "text";
}
}

10
w12/总代码/src/main/java/com/weibo/hotsearch/view/View.java

@ -1,10 +0,0 @@
package com.weibo.hotsearch.view;
import com.weibo.hotsearch.model.HotSearchResult;
public interface View {
void render(HotSearchResult result);
String getViewType();
}

29
w12/总代码/src/main/java/com/weibo/hotsearch/view/ViewFactory.java

@ -1,29 +0,0 @@
package com.weibo.hotsearch.view;
import java.util.HashMap;
import java.util.Map;
public class ViewFactory {
private static final Map<String, View> views = new HashMap<>();
static {
views.put("console", new ConsoleView());
views.put("text", new TextView());
}
public static View getView(String type) {
if (type == null || type.isEmpty()) {
return views.get("console");
}
return views.getOrDefault(type.toLowerCase(), views.get("console"));
}
public static boolean hasView(String type) {
return type != null && views.containsKey(type.toLowerCase());
}
public static Map<String, View> getAllViews() {
return new HashMap<>(views);
}
}

4
w12/总代码/src/run.bat

@ -1,4 +0,0 @@
@echo off
set CLASSPATH=target\classes;C:\Users\ruiruirui\.m2\repository\org\jsoup\jsoup\1.17.2\jsoup-1.17.2.jar
java WeiboHotSearcha
pause

BIN
w12/总代码/target/classes/WeiboStarHotSearcha.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/ConsoleOutputHandler.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/HotSearchFilter.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/Main.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/OutputHandler.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/StarFilter.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/cli/CliHandler.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/cli/CliParser.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/Command.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/CommandInvoker.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/CommandResult.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/FetchCommand.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/FilterCommand.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/HelpCommand.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/OutputCommand.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/command/SaveCommand.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/controller/HotSearchController.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/exception/CliException.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/exception/DataParseException.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/exception/ErrorCode.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/exception/HotSearchException.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/exception/NetworkException.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/model/AppContext.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/model/HotSearchItem.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/model/HotSearchResult.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/service/DataFetcher.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/service/FilterService.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/service/OutputService.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/strategy/FilterStrategy.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/strategy/FilterStrategyFactory.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/strategy/PolicyFilterStrategy.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/strategy/SportsFilterStrategy.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/strategy/StarFilterStrategy.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/view/ConsoleView.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/view/TextView.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/view/View.class

Binary file not shown.

BIN
w12/总代码/target/classes/com/weibo/hotsearch/view/ViewFactory.class

Binary file not shown.

BIN
w12/总代码/target/hotsearch-1.0.0-jar-with-dependencies.jar

Binary file not shown.

BIN
w12/总代码/target/hotsearch-1.0.0.jar

Binary file not shown.

3
w12/总代码/target/maven-archiver/pom.properties

@ -1,3 +0,0 @@
artifactId=hotsearch
groupId=com.weibo
version=1.0.0

37
w12/总代码/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst

@ -1,37 +0,0 @@
com\weibo\hotsearch\model\AppContext.class
com\weibo\hotsearch\strategy\PolicyFilterStrategy.class
com\weibo\hotsearch\view\View.class
com\weibo\hotsearch\strategy\SportsFilterStrategy.class
com\weibo\hotsearch\model\HotSearchResult.class
com\weibo\hotsearch\service\FilterService.class
com\weibo\hotsearch\view\TextView.class
com\weibo\hotsearch\HotSearchFilter.class
com\weibo\hotsearch\strategy\FilterStrategyFactory.class
com\weibo\hotsearch\exception\HotSearchException.class
com\weibo\hotsearch\command\SaveCommand.class
com\weibo\hotsearch\StarFilter.class
com\weibo\hotsearch\strategy\FilterStrategy.class
com\weibo\hotsearch\exception\ErrorCode.class
com\weibo\hotsearch\command\HelpCommand.class
com\weibo\hotsearch\command\FilterCommand.class
com\weibo\hotsearch\exception\NetworkException.class
com\weibo\hotsearch\OutputHandler.class
com\weibo\hotsearch\command\CommandResult.class
com\weibo\hotsearch\cli\CliHandler.class
com\weibo\hotsearch\model\HotSearchItem.class
com\weibo\hotsearch\controller\HotSearchController.class
com\weibo\hotsearch\strategy\StarFilterStrategy.class
com\weibo\hotsearch\service\DataFetcher.class
com\weibo\hotsearch\command\Command.class
com\weibo\hotsearch\ConsoleOutputHandler.class
com\weibo\hotsearch\view\ConsoleView.class
com\weibo\hotsearch\Main.class
WeiboStarHotSearcha.class
com\weibo\hotsearch\command\CommandInvoker.class
com\weibo\hotsearch\cli\CliParser.class
com\weibo\hotsearch\command\OutputCommand.class
com\weibo\hotsearch\command\FetchCommand.class
com\weibo\hotsearch\exception\CliException.class
com\weibo\hotsearch\service\OutputService.class
com\weibo\hotsearch\view\ViewFactory.class
com\weibo\hotsearch\exception\DataParseException.class

37
w12/总代码/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@ -1,37 +0,0 @@
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\OutputCommand.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\WeiboStarHotSearcha.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\Command.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\model\AppContext.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\SaveCommand.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\CommandInvoker.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\service\OutputService.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\service\DataFetcher.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\OutputHandler.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\cli\CliParser.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\CommandResult.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\cli\CliHandler.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\FetchCommand.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\strategy\FilterStrategyFactory.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\Main.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\exception\ErrorCode.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\exception\CliException.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\StarFilter.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\view\View.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\strategy\FilterStrategy.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\view\TextView.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\strategy\PolicyFilterStrategy.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\model\HotSearchResult.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\ConsoleOutputHandler.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\HelpCommand.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\exception\DataParseException.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\service\FilterService.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\command\FilterCommand.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\exception\NetworkException.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\controller\HotSearchController.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\HotSearchFilter.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\view\ViewFactory.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\strategy\StarFilterStrategy.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\model\HotSearchItem.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\view\ConsoleView.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\exception\HotSearchException.java
C:\Users\ruiruirui\java\w11\总代码\src\main\java\com\weibo\hotsearch\strategy\SportsFilterStrategy.java
Loading…
Cancel
Save