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 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); } }