From d02a5c23ff1b9a1de8ef21f0e3a689d808afb01b Mon Sep 17 00:00:00 2001 From: GwinPlace0408 <2260378191@qq.com> Date: Tue, 24 Mar 2026 17:28:01 +0800 Subject: [PATCH] Add project subdirectory --- project/douban-movie-analyzer/.gitignore | 39 + .../douban-movie-analyzer/.idea/.gitignore | 3 + .../douban-movie-analyzer/.idea/encodings.xml | 7 + project/douban-movie-analyzer/.idea/misc.xml | 14 + .../data/country_chart.png | Bin 0 -> 26795 bytes project/douban-movie-analyzer/data/movies.csv | 251 +++ .../douban-movie-analyzer/data/movies.json | 2002 +++++++++++++++++ .../douban-movie-analyzer/data/rating_pie.png | Bin 0 -> 22781 bytes project/douban-movie-analyzer/pom.xml | 47 + .../main/java/com/crawler/ChartGenerator.java | 30 + .../main/java/com/crawler/DataAnalyzer.java | 65 + .../main/java/com/crawler/DataStorage.java | 27 + .../main/java/com/crawler/DoubanCrawler.java | 39 + .../src/main/java/com/crawler/Main.java | 23 + .../src/main/java/com/crawler/Movie.java | 36 + 15 files changed, 2583 insertions(+) create mode 100644 project/douban-movie-analyzer/.gitignore create mode 100644 project/douban-movie-analyzer/.idea/.gitignore create mode 100644 project/douban-movie-analyzer/.idea/encodings.xml create mode 100644 project/douban-movie-analyzer/.idea/misc.xml create mode 100644 project/douban-movie-analyzer/data/country_chart.png create mode 100644 project/douban-movie-analyzer/data/movies.csv create mode 100644 project/douban-movie-analyzer/data/movies.json create mode 100644 project/douban-movie-analyzer/data/rating_pie.png create mode 100644 project/douban-movie-analyzer/pom.xml create mode 100644 project/douban-movie-analyzer/src/main/java/com/crawler/ChartGenerator.java create mode 100644 project/douban-movie-analyzer/src/main/java/com/crawler/DataAnalyzer.java create mode 100644 project/douban-movie-analyzer/src/main/java/com/crawler/DataStorage.java create mode 100644 project/douban-movie-analyzer/src/main/java/com/crawler/DoubanCrawler.java create mode 100644 project/douban-movie-analyzer/src/main/java/com/crawler/Main.java create mode 100644 project/douban-movie-analyzer/src/main/java/com/crawler/Movie.java diff --git a/project/douban-movie-analyzer/.gitignore b/project/douban-movie-analyzer/.gitignore new file mode 100644 index 0000000..480bdf5 --- /dev/null +++ b/project/douban-movie-analyzer/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/project/douban-movie-analyzer/.idea/.gitignore b/project/douban-movie-analyzer/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/project/douban-movie-analyzer/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/project/douban-movie-analyzer/.idea/encodings.xml b/project/douban-movie-analyzer/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/project/douban-movie-analyzer/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/project/douban-movie-analyzer/.idea/misc.xml b/project/douban-movie-analyzer/.idea/misc.xml new file mode 100644 index 0000000..4878ef2 --- /dev/null +++ b/project/douban-movie-analyzer/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/project/douban-movie-analyzer/data/country_chart.png b/project/douban-movie-analyzer/data/country_chart.png new file mode 100644 index 0000000000000000000000000000000000000000..25b1b85bf92dea10e2337d7bd4c042579986573d GIT binary patch literal 26795 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 + + 4.0.0 + + com.crawler + douban-movie-analyzer + 1.0-SNAPSHOT + + + 25 + 25 + UTF-8 + + + + + + org.jsoup + jsoup + 1.18.1 + + + + com.google.code.gson + gson + 2.11.0 + + + + org.knowm.xchart + xchart + 3.8.8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + + + \ No newline at end of file diff --git a/project/douban-movie-analyzer/src/main/java/com/crawler/ChartGenerator.java b/project/douban-movie-analyzer/src/main/java/com/crawler/ChartGenerator.java new file mode 100644 index 0000000..530bc33 --- /dev/null +++ b/project/douban-movie-analyzer/src/main/java/com/crawler/ChartGenerator.java @@ -0,0 +1,30 @@ +package com.crawler; + +import org.knowm.xchart.*; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +public class ChartGenerator { + public static void generateCountryBarChart(List movies, String savePath) throws IOException { + Map map = movies.stream().collect(Collectors.groupingBy(Movie::getCountry, Collectors.counting())); + List x = new ArrayList<>(); + List y = new ArrayList<>(); + map.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed()).limit(8) + .forEach(e -> { x.add(e.getKey()); y.add(e.getValue()); }); + + CategoryChart chart = new CategoryChartBuilder().width(900).height(600) + .title("豆瓣Top250 电影国家分布 (Top 8)").xAxisTitle("国家").yAxisTitle("数量").build(); + chart.addSeries("数量", x, y); + BitmapEncoder.saveBitmap(chart, savePath, BitmapEncoder.BitmapFormat.PNG); + System.out.println("📈 柱状图已保存 → " + savePath); + } + + public static void generateRatingPieChart(List movies, String savePath) throws IOException { + Map map = movies.stream().collect(Collectors.groupingBy(m -> m.getRating() >= 9.0 ? "9.0+" : "8.0-8.9", Collectors.counting())); + PieChart chart = new PieChartBuilder().width(800).height(600).title("评分分布").build(); + map.forEach(chart::addSeries); + BitmapEncoder.saveBitmap(chart, savePath, BitmapEncoder.BitmapFormat.PNG); + System.out.println("🥧 饼图已保存 → " + savePath); + } +} \ No newline at end of file diff --git a/project/douban-movie-analyzer/src/main/java/com/crawler/DataAnalyzer.java b/project/douban-movie-analyzer/src/main/java/com/crawler/DataAnalyzer.java new file mode 100644 index 0000000..9dce6e1 --- /dev/null +++ b/project/douban-movie-analyzer/src/main/java/com/crawler/DataAnalyzer.java @@ -0,0 +1,65 @@ +package com.crawler; + +import java.util.*; +import java.util.stream.Collectors; + +public class DataAnalyzer { + + public static void analyze(List movies) { + System.out.println("\n" + "=".repeat(70)); + System.out.println(" 📊 豆瓣电影 Top250 数据分析报告"); + System.out.println("=".repeat(70)); + + // 1. 基础统计(格式化表格) + double avgRating = movies.stream().mapToDouble(Movie::getRating).average().orElse(0.0); + System.out.printf("%-20s : %d 部%n", "总电影数量", movies.size()); + System.out.printf("%-20s : %.2f 分%n", "平均评分", avgRating); + System.out.println("-".repeat(70)); + + // 2. Top 5 高分电影(表格) + System.out.println("\n🏆 Top 5 最高分电影:"); + System.out.printf("%-4s %-45s %s%n", "排名", "电影标题", "评分"); + System.out.println("-".repeat(70)); + + List top5 = movies.stream() + .sorted(Comparator.comparingDouble(Movie::getRating).reversed()) + .limit(5) + .toList(); + + for (int i = 0; i < top5.size(); i++) { + Movie m = top5.get(i); + System.out.printf("%-4d %-45s %.1f%n", i + 1, m.getTitle(), m.getRating()); + } + System.out.println("-".repeat(70)); + + // 3. 国家/地区分布 Top 8(表格) + Map countryCount = movies.stream() + .collect(Collectors.groupingBy(Movie::getCountry, Collectors.counting())); + + System.out.println("\n🌍 国家/地区电影数量(Top 8):"); + System.out.printf("%-18s %s%n", "国家/地区", "数量"); + System.out.println("-".repeat(30)); + + countryCount.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(8) + .forEach(e -> System.out.printf("%-18s %d 部%n", e.getKey(), e.getValue())); + System.out.println("-".repeat(30)); + + // 4. 评分分布(表格) + Map ratingGroup = movies.stream() + .collect(Collectors.groupingBy(m -> { + if (m.getRating() >= 9.0) return "9.0+"; + else if (m.getRating() >= 8.5) return "8.5-8.9"; + else return "8.0-8.4"; + }, Collectors.counting())); + + System.out.println("\n📈 评分分布:"); + System.out.printf("%-12s %s%n", "评分区间", "电影数量"); + System.out.println("-".repeat(30)); + ratingGroup.forEach((k, v) -> System.out.printf("%-12s %d 部%n", k, v)); + + System.out.println("\n" + "=".repeat(70)); + System.out.println("🎉 分析完成!图表已保存至 data/ 目录"); + } +} \ No newline at end of file diff --git a/project/douban-movie-analyzer/src/main/java/com/crawler/DataStorage.java b/project/douban-movie-analyzer/src/main/java/com/crawler/DataStorage.java new file mode 100644 index 0000000..401d5b8 --- /dev/null +++ b/project/douban-movie-analyzer/src/main/java/com/crawler/DataStorage.java @@ -0,0 +1,27 @@ +package com.crawler; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class DataStorage { + public static void saveToCSV(List movies, String filePath) throws IOException { + try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(filePath), StandardCharsets.UTF_8))) { + pw.println("标题,评分,年份,国家,简介"); + for (Movie m : movies) { + pw.printf("\"%s\",%.1f,%s,%s,\"%s\"%n", m.getTitle().replace("\"","\"\""), m.getRating(), m.getYear(), m.getCountry(), m.getQuote().replace("\"","\"\"")); + } + } + System.out.println("📄 CSV 已保存 → " + filePath); + } + + public static void saveToJSON(List movies, String filePath) throws IOException { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + try (Writer writer = new OutputStreamWriter(new FileOutputStream(filePath), StandardCharsets.UTF_8)) { + gson.toJson(movies, writer); + } + System.out.println("📜 JSON 已保存 → " + filePath); + } +} \ No newline at end of file diff --git a/project/douban-movie-analyzer/src/main/java/com/crawler/DoubanCrawler.java b/project/douban-movie-analyzer/src/main/java/com/crawler/DoubanCrawler.java new file mode 100644 index 0000000..e7de106 --- /dev/null +++ b/project/douban-movie-analyzer/src/main/java/com/crawler/DoubanCrawler.java @@ -0,0 +1,39 @@ +package com.crawler; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class DoubanCrawler { + private static final String BASE_URL = "https://movie.douban.com/top250?start="; + private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"; + + public List crawlAll() throws IOException, InterruptedException { + List movies = new ArrayList<>(); + System.out.println("🚀 开始爬取豆瓣电影 Top250..."); + + for (int i = 0; i < 250; i += 25) { + String url = BASE_URL + i + "&filter="; + System.out.println("正在爬取第 " + (i/25 + 1) + " 页"); + + Document doc = Jsoup.connect(url).userAgent(USER_AGENT).timeout(10000).get(); + + Elements items = doc.select("div.item"); + for (Element item : items) { + String title = item.select("div.hd a").first().text().trim(); + double rating = Double.parseDouble(item.select("span.rating_num").first().text()); + String info = item.select("div.bd p").first().text().trim(); + String quote = item.select("span.inq").first() != null ? item.select("span.inq").first().text().trim() : ""; + + movies.add(new Movie(title, rating, info, quote)); + } + Thread.sleep(1200); + } + System.out.println("✅ 爬取完成!共 " + movies.size() + " 部电影"); + return movies; + } +} \ No newline at end of file diff --git a/project/douban-movie-analyzer/src/main/java/com/crawler/Main.java b/project/douban-movie-analyzer/src/main/java/com/crawler/Main.java new file mode 100644 index 0000000..ad87cc3 --- /dev/null +++ b/project/douban-movie-analyzer/src/main/java/com/crawler/Main.java @@ -0,0 +1,23 @@ +package com.crawler; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + try { + DoubanCrawler crawler = new DoubanCrawler(); + List movies = crawler.crawlAll(); + + DataStorage.saveToCSV(movies, "data/movies.csv"); + DataStorage.saveToJSON(movies, "data/movies.json"); + + DataAnalyzer.analyze(movies); + + ChartGenerator.generateCountryBarChart(movies, "data/country_chart.png"); + ChartGenerator.generateRatingPieChart(movies, "data/rating_pie.png"); + System.out.println("\n🎉 项目全部执行完成!所有文件已保存至 data/ 目录"); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/project/douban-movie-analyzer/src/main/java/com/crawler/Movie.java b/project/douban-movie-analyzer/src/main/java/com/crawler/Movie.java new file mode 100644 index 0000000..d5e155e --- /dev/null +++ b/project/douban-movie-analyzer/src/main/java/com/crawler/Movie.java @@ -0,0 +1,36 @@ +package com.crawler; + +public class Movie { + private String title; + private double rating; + private String info; + private String quote; + private String year; + private String country; + + public Movie(String title, double rating, String info, String quote) { + this.title = title; + this.rating = rating; + this.info = info; + this.quote = quote != null ? quote : "暂无"; + parseInfo(); + } + + private void parseInfo() { + String[] parts = info.split("/\\s*"); + if (parts.length >= 3) { + this.year = parts[parts.length - 3].trim(); + this.country = parts[parts.length - 2].trim(); + } else { + this.year = "未知"; + this.country = "未知"; + } + } + + // Getter + public String getTitle() { return title; } + public double getRating() { return rating; } + public String getYear() { return year; } + public String getCountry() { return country; } + public String getQuote() { return quote; } +} \ No newline at end of file