Compare commits
33 Commits
a7ac3da214
...
c2fdcd14e2
17 changed files with 583 additions and 0 deletions
@ -0,0 +1,27 @@ |
|||||
|
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; |
||||
|
} |
||||
|
// 其他情况(如>100)不处理
|
||||
|
} |
||||
|
|
||||
|
if (validCount > 0) { |
||||
|
double average = validSum / validCount; |
||||
|
System.out.printf("有效数据个数:%d,平均值:%.2f\n", validCount, average); |
||||
|
} else { |
||||
|
System.out.println("没有收集到有效数据,打印初始状态"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
After Width: | Height: | Size: 146 KiB |
@ -0,0 +1,53 @@ |
|||||
|
import java.util.Scanner; |
||||
|
|
||||
|
/** |
||||
|
* 温度转换程序(与Python版本功能完全等效) |
||||
|
* 输入格式:温度值 + 空格 + 单位(C/F),例如 36.6 C 或 97 F |
||||
|
* 功能:实现摄氏温度↔华氏温度的相互转换 |
||||
|
*/ |
||||
|
public class TemperatureConverter { |
||||
|
// 摄氏温度转换为华氏温度的核心方法 |
||||
|
public static double celsiusToFahrenheit(double celsius) { |
||||
|
return celsius * 9.0 / 5.0 + 32; |
||||
|
} |
||||
|
|
||||
|
// 华氏温度转换为摄氏温度的核心方法 |
||||
|
public static double fahrenheitToCelsius(double fahrenheit) { |
||||
|
return (fahrenheit - 32) * 5.0 / 9.0; |
||||
|
} |
||||
|
|
||||
|
// 程序主入口,处理输入和输出逻辑 |
||||
|
public static void main(String[] args) { |
||||
|
// 创建Scanner对象接收用户输入 |
||||
|
Scanner scanner = new Scanner(System.in); |
||||
|
|
||||
|
// 提示语与你的Python程序完全一致 |
||||
|
System.out.print("请输入要转换的温度与单位(例如 36.6 C 或 97 F):"); |
||||
|
|
||||
|
// 读取温度值和单位(兼容空格分隔的输入格式) |
||||
|
double temperature; |
||||
|
String unit; |
||||
|
try { |
||||
|
temperature = scanner.nextDouble(); // 读取温度数值 |
||||
|
unit = scanner.next().toUpperCase(); // 读取单位并统一转为大写(兼容小写输入) |
||||
|
} catch (Exception e) { |
||||
|
System.out.println("输入格式错误!请按示例格式输入(如:36.6 C)"); |
||||
|
scanner.close(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 根据单位执行转换并输出结果 |
||||
|
if (unit.equals("C")) { |
||||
|
double result = celsiusToFahrenheit(temperature); |
||||
|
System.out.printf("%.2f C = %.2f F%n", temperature, result); |
||||
|
} else if (unit.equals("F")) { |
||||
|
double result = fahrenheitToCelsius(temperature); |
||||
|
System.out.printf("%.2f F = %.2f C%n", temperature, result); |
||||
|
} else { |
||||
|
System.out.println("单位错误!仅支持 C(摄氏)或 F(华氏)"); |
||||
|
} |
||||
|
|
||||
|
// 关闭Scanner,释放资源 |
||||
|
scanner.close(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
import java.util.Scanner; |
||||
|
|
||||
|
/** |
||||
|
* 温度转换程序(与Python版本功能完全等效) |
||||
|
* 输入格式:温度值 + 空格 + 单位(C/F),例如 36.6 C 或 97 F |
||||
|
* 功能:实现摄氏温度↔华氏温度的相互转换 |
||||
|
*/ |
||||
|
public class TemperatureConverter { |
||||
|
// 摄氏温度转换为华氏温度的核心方法
|
||||
|
public static double celsiusToFahrenheit(double celsius) { |
||||
|
return celsius * 9.0 / 5.0 + 32; |
||||
|
} |
||||
|
|
||||
|
// 华氏温度转换为摄氏温度的核心方法
|
||||
|
public static double fahrenheitToCelsius(double fahrenheit) { |
||||
|
return (fahrenheit - 32) * 5.0 / 9.0; |
||||
|
} |
||||
|
|
||||
|
// 程序主入口,处理输入和输出逻辑
|
||||
|
public static void main(String[] args) { |
||||
|
// 创建Scanner对象接收用户输入
|
||||
|
Scanner scanner = new Scanner(System.in); |
||||
|
|
||||
|
// 提示语与你的Python程序完全一致
|
||||
|
System.out.print("请输入要转换的温度与单位(例如 36.6 C 或 97 F):"); |
||||
|
|
||||
|
// 读取温度值和单位(兼容空格分隔的输入格式)
|
||||
|
double temperature; |
||||
|
String unit; |
||||
|
try { |
||||
|
temperature = scanner.nextDouble(); // 读取温度数值
|
||||
|
unit = scanner.next().toUpperCase(); // 读取单位并统一转为大写(兼容小写输入)
|
||||
|
} catch (Exception e) { |
||||
|
System.out.println("输入格式错误!请按示例格式输入(如:36.6 C)"); |
||||
|
scanner.close(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 根据单位执行转换并输出结果
|
||||
|
if (unit.equals("C")) { |
||||
|
double result = celsiusToFahrenheit(temperature); |
||||
|
System.out.printf("%.2f C = %.2f F%n", temperature, result); |
||||
|
} else if (unit.equals("F")) { |
||||
|
double result = fahrenheitToCelsius(temperature); |
||||
|
System.out.printf("%.2f F = %.2f C%n", temperature, result); |
||||
|
} else { |
||||
|
System.out.println("单位错误!仅支持 C(摄氏)或 F(华氏)"); |
||||
|
} |
||||
|
|
||||
|
// 关闭Scanner,释放资源
|
||||
|
scanner.close(); |
||||
|
} |
||||
|
} |
||||
Binary file not shown.
@ -0,0 +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) { |
||||
|
try { |
||||
|
// 1. 爬取电影数据
|
||||
|
MovieCrawler crawler = new MovieCrawler(); |
||||
|
List<Movie> movies = crawler.crawlTopMovies(50); // 爬取50部电影
|
||||
|
|
||||
|
// 2. 数据清洗
|
||||
|
List<Movie> 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<Movie> cleanData(List<Movie> 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<Movie> 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<Movie> movies) { |
||||
|
System.out.println("\n=== 数据分析结果 ==="); |
||||
|
|
||||
|
// 1. 评分分布
|
||||
|
System.out.println("\n1. 评分分布:"); |
||||
|
Map<Double, Long> 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<Integer, Long> 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<String, Long> directorCount = movies.stream() |
||||
|
.collect(Collectors.groupingBy(Movie::getDirector, Collectors.counting())); |
||||
|
directorCount.entrySet().stream() |
||||
|
.sorted(Map.Entry.<String, Long>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<Movie> 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<Movie> movies) throws IOException { |
||||
|
// 1. 评分分布饼图
|
||||
|
DefaultPieDataset ratingDataset = new DefaultPieDataset(); |
||||
|
Map<Double, Long> 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<Integer, Double> 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"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +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 + '\'' + |
||||
|
"}"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,141 @@ |
|||||
|
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 MovieCrawler { |
||||
|
private static final String BASE_URL = "https://movie.douban.com/top250"; |
||||
|
private static final int DELAY_MS = 1000; // 控制请求频率
|
||||
|
|
||||
|
public List<Movie> crawlTopMovies(int limit) throws IOException { |
||||
|
List<Movie> movies = new ArrayList<>(); |
||||
|
int page = 0; |
||||
|
|
||||
|
System.out.println("Starting to crawl movies..."); |
||||
|
|
||||
|
while (movies.size() < limit) { |
||||
|
String url = BASE_URL + "?start=" + page * 25; |
||||
|
System.out.println("Crawling page: " + url); |
||||
|
|
||||
|
try { |
||||
|
Document doc = Jsoup.connect(url) |
||||
|
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") |
||||
|
.timeout(10000) |
||||
|
.get(); |
||||
|
|
||||
|
// 打印页面标题,确认是否成功获取页面
|
||||
|
System.out.println("Page title: " + doc.title()); |
||||
|
|
||||
|
// 选择电影元素
|
||||
|
Elements movieElements = doc.select(".item"); |
||||
|
System.out.println("Found " + movieElements.size() + " movie elements"); |
||||
|
|
||||
|
for (Element element : movieElements) { |
||||
|
if (movies.size() >= limit) break; |
||||
|
|
||||
|
int currentCount = movies.size() + 1; |
||||
|
System.out.println("Processing movie " + currentCount + "..."); |
||||
|
|
||||
|
try { |
||||
|
Movie movie = parseMovie(element); |
||||
|
if (movie != null) { |
||||
|
movies.add(movie); |
||||
|
System.out.println("Added movie: " + movie.getTitle()); |
||||
|
} else { |
||||
|
System.out.println("Skipping movie, parsing failed"); |
||||
|
} |
||||
|
|
||||
|
// 控制请求频率
|
||||
|
Thread.sleep(DELAY_MS); |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error parsing movie: " + e.getMessage()); |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
page++; |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error crawling page: " + e.getMessage()); |
||||
|
e.printStackTrace(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
System.out.println("Crawling finished. Found " + movies.size() + " movies."); |
||||
|
return movies; |
||||
|
} |
||||
|
|
||||
|
private Movie parseMovie(Element element) { |
||||
|
try { |
||||
|
// 提取标题
|
||||
|
Element titleElement = element.selectFirst(".hd .title"); |
||||
|
if (titleElement == null) { |
||||
|
System.err.println("Title element not found"); |
||||
|
return null; |
||||
|
} |
||||
|
String title = titleElement.text(); |
||||
|
System.out.println("Title: " + title); |
||||
|
|
||||
|
// 提取年份
|
||||
|
Element yearElement = element.selectFirst(".bd p:first-child"); |
||||
|
if (yearElement == null) { |
||||
|
System.err.println("Year element not found"); |
||||
|
return null; |
||||
|
} |
||||
|
String yearText = yearElement.text().trim(); |
||||
|
System.out.println("Year text: " + yearText); |
||||
|
|
||||
|
// 从字符串中提取年份
|
||||
|
int year = 0; |
||||
|
// 使用正则表达式提取年份
|
||||
|
java.util.regex.Matcher matcher = java.util.regex.Pattern.compile("(\\d{4})").matcher(yearText); |
||||
|
if (matcher.find()) { |
||||
|
year = Integer.parseInt(matcher.group(1)); |
||||
|
} |
||||
|
if (year == 0) { |
||||
|
System.err.println("Year not found in text: " + yearText); |
||||
|
return null; |
||||
|
} |
||||
|
System.out.println("Year: " + year); |
||||
|
|
||||
|
// 提取评分
|
||||
|
Element ratingElement = element.selectFirst(".rating_num"); |
||||
|
if (ratingElement == null) { |
||||
|
System.err.println("Rating element not found"); |
||||
|
return null; |
||||
|
} |
||||
|
String ratingText = ratingElement.text(); |
||||
|
System.out.println("Rating text: " + ratingText); |
||||
|
|
||||
|
double rating = Double.parseDouble(ratingText); |
||||
|
System.out.println("Rating: " + rating); |
||||
|
|
||||
|
// 提取类型
|
||||
|
String genre = ""; |
||||
|
String infoText = yearElement.text(); |
||||
|
if (infoText.contains("/")) { |
||||
|
String[] parts = infoText.split("/"); |
||||
|
if (parts.length > 2) { |
||||
|
genre = parts[2].trim(); |
||||
|
} |
||||
|
} |
||||
|
System.out.println("Genre: " + genre); |
||||
|
|
||||
|
// 简化处理,不进入详情页
|
||||
|
String director = ""; |
||||
|
String actors = ""; |
||||
|
String synopsis = ""; |
||||
|
|
||||
|
System.out.println("Parsed movie: " + title + " (" + year + ") - " + rating + " - " + genre); |
||||
|
return new Movie(title, year, rating, genre, director, actors, synopsis); |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error parsing movie: " + e.getMessage()); |
||||
|
e.printStackTrace(); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 37 KiB |
Loading…
Reference in new issue