diff --git a/W3/Main.class b/Main.class similarity index 100% rename from W3/Main.class rename to Main.class diff --git a/Main.java b/Main.java index 28d2ed2..51537f5 100644 --- a/Main.java +++ b/Main.java @@ -1,27 +1,169 @@ +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartUtils; +import org.jfree.chart.JFreeChart; +import org.jfree.data.category.DefaultCategoryDataset; +import org.jfree.data.general.DefaultPieDataset; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + public class Main { public static void main(String[] args) { - int[] voltages = {10, -5, 7, 105, 999, 89, 76, 74}; - int validCount = 0; // 有效数据个数 - double validSum = 0; // 有效数据总和 - - for (int voltage : voltages) { - if (voltage == 999) { - System.out.println("程序终止,传感器离线"); - break; // 遇到999,终止程序 - } else if (voltage < 0) { - System.out.println("警告:发现负数,数据已跳过"); - } else if (voltage >= 1 && voltage <= 100) { - validCount++; - validSum += voltage; + try { + // 1. 爬取电影数据 + MovieCrawler crawler = new MovieCrawler(); + List movies = crawler.crawlTopMovies(50); // 爬取50部电影 + + // 2. 数据清洗 + List cleanedMovies = cleanData(movies); + + // 3. 数据存储 + saveToCSV(cleanedMovies, "movies.csv"); + + // 4. 数据分析 + analyzeData(cleanedMovies); + + // 5. 结果展示 + displayResults(cleanedMovies); + generateCharts(cleanedMovies); + + System.out.println("爬取完成!共获取了 " + cleanedMovies.size() + " 部电影数据。"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static List cleanData(List movies) { + return movies.stream() + .map(movie -> { + // 去空格 + movie.setTitle(movie.getTitle().trim()); + movie.setGenre(movie.getGenre().trim()); + movie.setDirector(movie.getDirector().trim()); + movie.setActors(movie.getActors().trim()); + movie.setSynopsis(movie.getSynopsis().trim()); + return movie; + }) + .collect(Collectors.toList()); + } + + private static void saveToCSV(List movies, String fileName) throws IOException { + try (FileWriter writer = new FileWriter(fileName)) { + // 写入表头 + writer.write("Title,Year,Rating,Genre,Director,Actors,Synopsis\n"); + + // 写入数据 + for (Movie movie : movies) { + writer.write(String.format("%s,%d,%.1f,%s,%s,%s,%s\n", + escapeCSV(movie.getTitle()), + movie.getYear(), + movie.getRating(), + escapeCSV(movie.getGenre()), + escapeCSV(movie.getDirector()), + escapeCSV(movie.getActors()), + escapeCSV(movie.getSynopsis()))); } - // 其他情况(如>100)不处理 } + } - if (validCount > 0) { - double average = validSum / validCount; - System.out.printf("有效数据个数:%d,平均值:%.2f\n", validCount, average); - } else { - System.out.println("没有收集到有效数据,打印初始状态"); + private static String escapeCSV(String value) { + if (value == null) return ""; + if (value.contains(",") || value.contains("\n") || value.contains("\"")) { + value = value.replace("\"", "\"\""); + return "\"" + value + "\""; } + return value; + } + + private static void analyzeData(List movies) { + System.out.println("\n=== 数据分析结果 ==="); + + // 1. 评分分布 + System.out.println("\n1. 评分分布:"); + Map ratingDistribution = movies.stream() + .collect(Collectors.groupingBy(Movie::getRating, Collectors.counting())); + ratingDistribution.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> System.out.printf("评分 %.1f: %d 部\n", entry.getKey(), entry.getValue())); + + // 2. 年份分布 + System.out.println("\n2. 年份分布:"); + Map yearDistribution = movies.stream() + .collect(Collectors.groupingBy(Movie::getYear, Collectors.counting())); + yearDistribution.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> System.out.printf("年份 %d: %d 部\n", entry.getKey(), entry.getValue())); + + // 3. 导演作品数排行 + System.out.println("\n3. 导演作品数排行:"); + Map directorCount = movies.stream() + .collect(Collectors.groupingBy(Movie::getDirector, Collectors.counting())); + directorCount.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(10) + .forEach(entry -> System.out.printf("%s: %d 部\n", entry.getKey(), entry.getValue())); + + // 4. 平均评分 + double averageRating = movies.stream() + .mapToDouble(Movie::getRating) + .average() + .orElse(0); + System.out.printf("\n4. 平均评分:%.2f\n", averageRating); + } + + private static void displayResults(List movies) { + System.out.println("\n=== 电影数据列表 ==="); + System.out.printf("%-50s %-10s %-10s %-30s %-30s\n", "Title", "Year", "Rating", "Genre", "Director"); + System.out.println("-------------------------------------------------------------------------------------------------------------------------------"); + + for (Movie movie : movies) { + System.out.printf("%-50s %-10d %-10.1f %-30s %-30s\n", + truncate(movie.getTitle(), 50), + movie.getYear(), + movie.getRating(), + truncate(movie.getGenre(), 30), + truncate(movie.getDirector(), 30)); + } + } + + private static String truncate(String text, int maxLength) { + return text.length() > maxLength ? text.substring(0, maxLength - 3) + "..." : text; + } + + private static void generateCharts(List movies) throws IOException { + // 1. 评分分布饼图 + DefaultPieDataset ratingDataset = new DefaultPieDataset(); + Map ratingDistribution = movies.stream() + .collect(Collectors.groupingBy(Movie::getRating, Collectors.counting())); + ratingDistribution.forEach((rating, count) -> ratingDataset.setValue(String.valueOf(rating), count)); + + JFreeChart ratingChart = ChartFactory.createPieChart( + "电影评分分布", + ratingDataset, + true, + true, + false + ); + ChartUtils.saveChartAsPNG(new File("rating_distribution.png"), ratingChart, 800, 600); + + // 2. 年份与评分关系图 + DefaultCategoryDataset yearRatingDataset = new DefaultCategoryDataset(); + Map yearAverageRating = movies.stream() + .collect(Collectors.groupingBy(Movie::getYear, + Collectors.averagingDouble(Movie::getRating))); + yearAverageRating.forEach((year, avgRating) -> yearRatingDataset.addValue(avgRating, "评分", String.valueOf(year))); + + JFreeChart yearRatingChart = ChartFactory.createBarChart( + "年份与平均评分关系", + "年份", + "平均评分", + yearRatingDataset + ); + ChartUtils.saveChartAsPNG(new File("year_rating_relation.png"), yearRatingChart, 800, 600); + + System.out.println("\n图表已生成:rating_distribution.png 和 year_rating_relation.png"); } } diff --git a/W3/Movie.java b/Movie.java similarity index 95% rename from W3/Movie.java rename to Movie.java index 2e4dc55..f3d55da 100644 --- a/W3/Movie.java +++ b/Movie.java @@ -1,89 +1,89 @@ -public class Movie { - private String title; - private int year; - private double rating; - private String genre; - private String director; - private String actors; - private String synopsis; - - public Movie() { - } - - public Movie(String title, int year, double rating, String genre, String director, String actors, String synopsis) { - this.title = title; - this.year = year; - this.rating = rating; - this.genre = genre; - this.director = director; - this.actors = actors; - this.synopsis = synopsis; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } - - public double getRating() { - return rating; - } - - public void setRating(double rating) { - this.rating = rating; - } - - public String getGenre() { - return genre; - } - - public void setGenre(String genre) { - this.genre = genre; - } - - public String getDirector() { - return director; - } - - public void setDirector(String director) { - this.director = director; - } - - public String getActors() { - return actors; - } - - public void setActors(String actors) { - this.actors = actors; - } - - public String getSynopsis() { - return synopsis; - } - - public void setSynopsis(String synopsis) { - this.synopsis = synopsis; - } - - @Override - public String toString() { - return "Movie{" + - "title='" + title + '\'' + - ", year=" + year + - ", rating=" + rating + - ", genre='" + genre + '\'' + - ", director='" + director + '\'' + - "}"; - } -} +public class Movie { + private String title; + private int year; + private double rating; + private String genre; + private String director; + private String actors; + private String synopsis; + + public Movie() { + } + + public Movie(String title, int year, double rating, String genre, String director, String actors, String synopsis) { + this.title = title; + this.year = year; + this.rating = rating; + this.genre = genre; + this.director = director; + this.actors = actors; + this.synopsis = synopsis; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + + public double getRating() { + return rating; + } + + public void setRating(double rating) { + this.rating = rating; + } + + public String getGenre() { + return genre; + } + + public void setGenre(String genre) { + this.genre = genre; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getActors() { + return actors; + } + + public void setActors(String actors) { + this.actors = actors; + } + + public String getSynopsis() { + return synopsis; + } + + public void setSynopsis(String synopsis) { + this.synopsis = synopsis; + } + + @Override + public String toString() { + return "Movie{" + + "title='" + title + '\'' + + ", year=" + year + + ", rating=" + rating + + ", genre='" + genre + '\'' + + ", director='" + director + '\'' + + "}"; + } +} diff --git a/W3/MovieCrawler.java b/MovieCrawler.java similarity index 100% rename from W3/MovieCrawler.java rename to MovieCrawler.java diff --git a/W3/Main.java b/W3/Main.java deleted file mode 100644 index 51537f5..0000000 --- a/W3/Main.java +++ /dev/null @@ -1,169 +0,0 @@ -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartUtils; -import org.jfree.chart.JFreeChart; -import org.jfree.data.category.DefaultCategoryDataset; -import org.jfree.data.general.DefaultPieDataset; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -public class Main { - public static void main(String[] args) { - try { - // 1. 爬取电影数据 - MovieCrawler crawler = new MovieCrawler(); - List movies = crawler.crawlTopMovies(50); // 爬取50部电影 - - // 2. 数据清洗 - List cleanedMovies = cleanData(movies); - - // 3. 数据存储 - saveToCSV(cleanedMovies, "movies.csv"); - - // 4. 数据分析 - analyzeData(cleanedMovies); - - // 5. 结果展示 - displayResults(cleanedMovies); - generateCharts(cleanedMovies); - - System.out.println("爬取完成!共获取了 " + cleanedMovies.size() + " 部电影数据。"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static List cleanData(List movies) { - return movies.stream() - .map(movie -> { - // 去空格 - movie.setTitle(movie.getTitle().trim()); - movie.setGenre(movie.getGenre().trim()); - movie.setDirector(movie.getDirector().trim()); - movie.setActors(movie.getActors().trim()); - movie.setSynopsis(movie.getSynopsis().trim()); - return movie; - }) - .collect(Collectors.toList()); - } - - private static void saveToCSV(List movies, String fileName) throws IOException { - try (FileWriter writer = new FileWriter(fileName)) { - // 写入表头 - writer.write("Title,Year,Rating,Genre,Director,Actors,Synopsis\n"); - - // 写入数据 - for (Movie movie : movies) { - writer.write(String.format("%s,%d,%.1f,%s,%s,%s,%s\n", - escapeCSV(movie.getTitle()), - movie.getYear(), - movie.getRating(), - escapeCSV(movie.getGenre()), - escapeCSV(movie.getDirector()), - escapeCSV(movie.getActors()), - escapeCSV(movie.getSynopsis()))); - } - } - } - - private static String escapeCSV(String value) { - if (value == null) return ""; - if (value.contains(",") || value.contains("\n") || value.contains("\"")) { - value = value.replace("\"", "\"\""); - return "\"" + value + "\""; - } - return value; - } - - private static void analyzeData(List movies) { - System.out.println("\n=== 数据分析结果 ==="); - - // 1. 评分分布 - System.out.println("\n1. 评分分布:"); - Map ratingDistribution = movies.stream() - .collect(Collectors.groupingBy(Movie::getRating, Collectors.counting())); - ratingDistribution.entrySet().stream() - .sorted(Map.Entry.comparingByKey()) - .forEach(entry -> System.out.printf("评分 %.1f: %d 部\n", entry.getKey(), entry.getValue())); - - // 2. 年份分布 - System.out.println("\n2. 年份分布:"); - Map yearDistribution = movies.stream() - .collect(Collectors.groupingBy(Movie::getYear, Collectors.counting())); - yearDistribution.entrySet().stream() - .sorted(Map.Entry.comparingByKey()) - .forEach(entry -> System.out.printf("年份 %d: %d 部\n", entry.getKey(), entry.getValue())); - - // 3. 导演作品数排行 - System.out.println("\n3. 导演作品数排行:"); - Map directorCount = movies.stream() - .collect(Collectors.groupingBy(Movie::getDirector, Collectors.counting())); - directorCount.entrySet().stream() - .sorted(Map.Entry.comparingByValue().reversed()) - .limit(10) - .forEach(entry -> System.out.printf("%s: %d 部\n", entry.getKey(), entry.getValue())); - - // 4. 平均评分 - double averageRating = movies.stream() - .mapToDouble(Movie::getRating) - .average() - .orElse(0); - System.out.printf("\n4. 平均评分:%.2f\n", averageRating); - } - - private static void displayResults(List movies) { - System.out.println("\n=== 电影数据列表 ==="); - System.out.printf("%-50s %-10s %-10s %-30s %-30s\n", "Title", "Year", "Rating", "Genre", "Director"); - System.out.println("-------------------------------------------------------------------------------------------------------------------------------"); - - for (Movie movie : movies) { - System.out.printf("%-50s %-10d %-10.1f %-30s %-30s\n", - truncate(movie.getTitle(), 50), - movie.getYear(), - movie.getRating(), - truncate(movie.getGenre(), 30), - truncate(movie.getDirector(), 30)); - } - } - - private static String truncate(String text, int maxLength) { - return text.length() > maxLength ? text.substring(0, maxLength - 3) + "..." : text; - } - - private static void generateCharts(List movies) throws IOException { - // 1. 评分分布饼图 - DefaultPieDataset ratingDataset = new DefaultPieDataset(); - Map ratingDistribution = movies.stream() - .collect(Collectors.groupingBy(Movie::getRating, Collectors.counting())); - ratingDistribution.forEach((rating, count) -> ratingDataset.setValue(String.valueOf(rating), count)); - - JFreeChart ratingChart = ChartFactory.createPieChart( - "电影评分分布", - ratingDataset, - true, - true, - false - ); - ChartUtils.saveChartAsPNG(new File("rating_distribution.png"), ratingChart, 800, 600); - - // 2. 年份与评分关系图 - DefaultCategoryDataset yearRatingDataset = new DefaultCategoryDataset(); - Map yearAverageRating = movies.stream() - .collect(Collectors.groupingBy(Movie::getYear, - Collectors.averagingDouble(Movie::getRating))); - yearAverageRating.forEach((year, avgRating) -> yearRatingDataset.addValue(avgRating, "评分", String.valueOf(year))); - - JFreeChart yearRatingChart = ChartFactory.createBarChart( - "年份与平均评分关系", - "年份", - "平均评分", - yearRatingDataset - ); - ChartUtils.saveChartAsPNG(new File("year_rating_relation.png"), yearRatingChart, 800, 600); - - System.out.println("\n图表已生成:rating_distribution.png 和 year_rating_relation.png"); - } -} diff --git a/W3/Circle.java b/W4/Circle.java similarity index 100% rename from W3/Circle.java rename to W4/Circle.java diff --git a/W3/QQ20260327-221432.png b/W4/QQ20260327-221432.png similarity index 100% rename from W3/QQ20260327-221432.png rename to W4/QQ20260327-221432.png diff --git a/W3/Rectangle.java b/W4/Rectangle.java similarity index 100% rename from W3/Rectangle.java rename to W4/Rectangle.java diff --git a/W3/Shape.java b/W4/Shape.java similarity index 100% rename from W3/Shape.java rename to W4/Shape.java diff --git a/W3/ShapeUtil.java b/W4/ShapeUtil.java similarity index 100% rename from W3/ShapeUtil.java rename to W4/ShapeUtil.java diff --git a/W3/Test.java b/W4/Test.java similarity index 100% rename from W3/Test.java rename to W4/Test.java diff --git a/W3/Triangle.java b/W4/Triangle.java similarity index 100% rename from W3/Triangle.java rename to W4/Triangle.java diff --git a/W3/W3.txt b/W4/W3.txt similarity index 100% rename from W3/W3.txt rename to W4/W3.txt diff --git a/W3/jcommon-1.0.24.jar b/jcommon-1.0.24.jar similarity index 100% rename from W3/jcommon-1.0.24.jar rename to jcommon-1.0.24.jar diff --git a/W3/jfreechart-1.5.4.jar b/jfreechart-1.5.4.jar similarity index 100% rename from W3/jfreechart-1.5.4.jar rename to jfreechart-1.5.4.jar diff --git a/W3/jsoup-1.17.2.jar b/jsoup-1.17.2.jar similarity index 100% rename from W3/jsoup-1.17.2.jar rename to jsoup-1.17.2.jar diff --git a/W3/movies.csv b/movies.csv similarity index 100% rename from W3/movies.csv rename to movies.csv diff --git a/W3/rating_distribution.png b/rating_distribution.png similarity index 100% rename from W3/rating_distribution.png rename to rating_distribution.png diff --git a/W3/year_rating_relation.png b/year_rating_relation.png similarity index 100% rename from W3/year_rating_relation.png rename to year_rating_relation.png