diff --git a/W5/NeteaseCommentCrawler.java b/W5/NeteaseCommentCrawler.java new file mode 100644 index 0000000..441da75 --- /dev/null +++ b/W5/NeteaseCommentCrawler.java @@ -0,0 +1,148 @@ +package com.example; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +public class NeteaseCommentCrawler { + private static final String 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"; + + public static JSONArray getHotComments(String songId) { + String apiUrl = "https://music.163.com/api/v1/resource/comments/R_SO_4_" + songId + + "?rid=R_SO_4_" + songId + + "&offset=0&total=true&limit=20"; + + try { + System.out.println("正在请求网易云音乐评论接口..."); + + URL url = new URL(apiUrl); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setConnectTimeout(15000); + conn.setReadTimeout(15000); + conn.setRequestProperty("User-Agent", USER_AGENT); + conn.setRequestProperty("Referer", "https://music.163.com/song?id=" + songId); + conn.setRequestProperty("Accept", "*/*"); + conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8"); + + int statusCode = conn.getResponseCode(); + System.out.println("HTTP状态码:" + statusCode); + + if (statusCode != 200) { + System.err.println("请求失败,HTTP状态码:" + statusCode); + return new JSONArray(); + } + + String responseStr = readStream(conn.getInputStream()); + System.out.println("响应长度:" + responseStr.length() + " 字符"); + + if (responseStr == null || responseStr.trim().isEmpty()) { + System.err.println("响应内容为空"); + return new JSONArray(); + } + + JSONObject responseJson = JSON.parseObject(responseStr); + + if (responseJson == null) { + System.err.println("JSON解析失败"); + return new JSONArray(); + } + + int code = responseJson.getIntValue("code"); + if (code != 200) { + System.err.println("接口返回错误码:" + code + ",消息:" + responseJson.getString("message")); + return new JSONArray(); + } + + JSONArray hotComments = responseJson.getJSONArray("hotComments"); + if (hotComments == null || hotComments.isEmpty()) { + System.out.println("该歌曲暂无热门评论"); + return new JSONArray(); + } + + return hotComments; + + } catch (Exception e) { + System.err.println("爬取失败:" + e.getMessage()); + e.printStackTrace(); + } + return new JSONArray(); + } + + private static String readStream(InputStream is) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + return sb.toString(); + } + + public static void printComments(JSONArray hotComments) { + System.out.println("\n===== 网易云音乐热门评论 ====="); + System.out.println("共获取到 " + hotComments.size() + " 条热门评论\n"); + for (int i = 0; i < hotComments.size(); i++) { + JSONObject comment = hotComments.getJSONObject(i); + JSONObject user = comment.getJSONObject("user"); + String nickname = user.getString("nickname"); + String content = comment.getString("content").replace("\n", " "); + int likedCount = comment.getInteger("likedCount"); + Long time = comment.getLong("time"); + String timeStr = formatTime(time); + + System.out.printf("%d. [%s]:%s(%d赞)%s%n", + i + 1, nickname, content, likedCount, timeStr); + } + } + + private static String formatTime(Long timestamp) { + if (timestamp == null) return ""; + java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return sdf.format(new java.util.Date(timestamp)); + } + + public static void saveToCSV(JSONArray hotComments) { + String filePath = "netease_hot_comments.csv"; + try (FileWriter writer = new FileWriter(filePath, StandardCharsets.UTF_8)) { + writer.write("序号,用户,评论,点赞数,时间\n"); + for (int i = 0; i < hotComments.size(); i++) { + JSONObject comment = hotComments.getJSONObject(i); + JSONObject user = comment.getJSONObject("user"); + String nickname = user.getString("nickname"); + String content = comment.getString("content").replace("\n", " ").replace(",", ","); + int likedCount = comment.getInteger("likedCount"); + Long time = comment.getLong("time"); + String timeStr = formatTime(time); + + writer.write(String.format("%d,%s,%s,%d,%s%n", + i + 1, nickname, content, likedCount, timeStr)); + } + System.out.println("\n评论已保存到 " + filePath); + } catch (Exception e) { + System.err.println("保存CSV失败:" + e.getMessage()); + } + } + + public static void main(String[] args) { + String songId = "186016"; + System.out.println("歌曲ID:" + songId + "(周杰伦 - 晴天)"); + System.out.println("================================"); + + JSONArray hotComments = getHotComments(songId); + if (!hotComments.isEmpty()) { + printComments(hotComments); + saveToCSV(hotComments); + } else { + System.out.println("未获取到评论,请检查:"); + System.out.println(" 1. 歌曲ID是否正确"); + System.out.println(" 2. 网络是否能访问 music.163.com"); + } + } +} diff --git a/W5/屏幕截图 2026-04-06 201413.png b/W5/屏幕截图 2026-04-06 201413.png new file mode 100644 index 0000000..3767dc5 Binary files /dev/null and b/W5/屏幕截图 2026-04-06 201413.png differ