You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
5.2 KiB

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.io.IOException;
import org.knowm.xchart.*;
public class WeatherMain {
public static void main(String[] args) {
// 西部城市列表:[城市名, 纬度, 经度]
String[][] westernCities = {
{"西安", "34.2644", "108.9494"},
{"成都", "30.5723", "104.0665"},
{"兰州", "36.0614", "103.8343"},
{"乌鲁木齐", "43.8256", "87.6168"}
};
try {
// 1. 创建 HTTP 客户端
HttpClient httpClient = HttpClient.newHttpClient();
// 2. 遍历所有城市
for (String[] city : westernCities) {
String cityName = city[0];
String latitude = city[1];
String longitude = city[2];
// 拼接 API 地址
String apiUrl = "https://api.open-meteo.com/v1/forecast"
+ "?latitude=" + latitude
+ "&longitude=" + longitude
+ "&hourly=temperature_2m"
+ "&timezone=Asia/Shanghai";
// 构建 HTTP 请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(apiUrl))
.GET()
.build();
// 发送请求并获取响应
HttpResponse<String> response = httpClient.send(
request,
HttpResponse.BodyHandlers.ofString()
);
// 打印温度表格
printTemperatureTable(response.body(), cityName);
// ✅ 新增:绘制温度折线图
drawTemperatureChart(response.body(), cityName);
System.out.println("✅ " + cityName + " 天气数据获取完成!\n");
}
System.out.println("==================================");
System.out.println("🎉 所有西部城市天气数据爬取完毕!");
} catch (Exception e) {
System.err.println("❌ 爬取过程中发生错误:");
e.printStackTrace();
}
}
// 打印温度表格
private static void printTemperatureTable(String jsonData, String cityName) {
try {
// 提取时间数组
int timeStart = jsonData.indexOf("\"time\":");
int timeEnd = jsonData.indexOf("],", timeStart);
String timePart = jsonData.substring(timeStart + 7, timeEnd + 1);
String[] times = timePart.replace("\"", "").replace("[", "").replace("]", "").split(",");
// 提取温度数组
int tempStart = jsonData.indexOf("\"temperature_2m\":");
int tempEnd = jsonData.indexOf("]", tempStart);
String tempPart = jsonData.substring(tempStart + 18, tempEnd + 1);
String[] temps = tempPart.replace("[", "").replace("]", "").split(",");
// 打印表头
System.out.println("==================================");
System.out.println("城市:" + cityName);
System.out.println("----------------------------------");
System.out.printf("%-20s %-10s%n", "时间", "温度(°C)");
System.out.println("----------------------------------");
// 只打印前24小时数据
int maxShow = Math.min(24, Math.min(times.length, temps.length));
for (int i = 0; i < maxShow; i++) {
System.out.printf("%-20s %-10s%n", times[i], temps[i]);
}
System.out.println("----------------------------------\n");
} catch (Exception e) {
System.out.println("⚠️ " + cityName + " 数据解析失败");
e.printStackTrace();
}
}
// ✅ 新增:绘制温度折线图并保存为 PNG
private static void drawTemperatureChart(String jsonData, String cityName) throws IOException {
// 提取温度数组
int tempStart = jsonData.indexOf("\"temperature_2m\":");
int tempEnd = jsonData.indexOf("]", tempStart);
String tempPart = jsonData.substring(tempStart + 18, tempEnd + 1);
String[] temps = tempPart.replace("[", "").replace("]", "").split(",");
// 准备绘图数据(取前24小时)
double[] hours = new double[24];
double[] temperatures = new double[24];
for (int i = 0; i < 24; i++) {
hours[i] = i; // 用 0~23 代表一天中的小时
temperatures[i] = Double.parseDouble(temps[i].trim());
}
// 创建图表
XYChart chart = new XYChartBuilder()
.width(800) // 图片宽度
.height(600) // 图片高度
.title(cityName + " 逐小时温度变化")
.xAxisTitle("小时(0~23)")
.yAxisTitle("温度 (°C)")
.build();
// 添加数据系列
chart.addSeries("温度", hours, temperatures);
// 保存为 PNG 图片(项目根目录下)
String fileName = cityName + "_温度折线图.png";
BitmapEncoder.saveBitmap(chart, fileName, BitmapEncoder.BitmapFormat.PNG);
System.out.println("📊 图表已保存:" + fileName);
}
}