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