通过百度api处理交通数据
通过百度api处理交通数据
1、读取excel获取道路数据
-
//道路名称 @Data @EqualsAndHashCode public class RoadName { @ExcelProperty("Name") private String name; }
-
/** * 获取excel中的道路名称 */ private static List<String> getRoadName() { // 定义文件路径,指向包含道路名称的Excel文件 String fileName = "src\\main\\resources\\static\\cd_road_name.xlsx"; // 创建一个RoadName对象的列表,用于存储从Excel文件中读取的数据 List<RoadName> nameDataList = new ArrayList<>(); // 使用EasyExcel库读取Excel文件 EasyExcel.read(fileName, RoadName.class, new AnalysisEventListener<RoadName>() { // 重写invoke方法,该方法会在读取每一行数据时被调用 @Override public void invoke(RoadName data, AnalysisContext context) { // 将读取到的每一行数据添加到nameDataList列表中 nameDataList.add(data); } // 重写doAfterAllAnalysed方法,该方法会在所有数据读取完成后被调用 @Override public void doAfterAllAnalysed(AnalysisContext context) { // 所有数据解析完成后的操作,这里只是打印一条消息 System.out.println("所有数据解析完成!"); } }).sheet().doRead(); // 指定读取第一个sheet并开始读取 // 创建一个字符串列表,用于存储道路名称 List<String> RoadNameList = new ArrayList<>(); // 遍历nameDataList列表,提取每条记录的道路名称 for (RoadName roadName : nameDataList) { // 将每条记录的道路名称添加到RoadNameList列表中 RoadNameList.add(roadName.getName()); } // 返回包含所有道路名称的列表 return RoadNameList; }
2、获取百度api数据
-
代码官网有:https://lbsyun.baidu.com/faq/api?title=webapi/traffic-roadseek
-
package xyz.zzj.traffic_zzj.utils; import org.springframework.web.util.UriUtils; import xyz.zzj.traffic_zzj.constant.BaiduConstant; import java.net.URL; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URLConnection; import java.util.Map; //用于获取百度api public class BaiduApi { public static String URL = BaiduConstant.BAIDU_URL; public static String AK = BaiduConstant.BAIDU_AK; public String requestGetAK(String strUrl, Map<String, String> param) throws Exception { if (strUrl == null || strUrl.length() <= 0 || param == null || param.size() <= 0) { return null; } StringBuffer queryString = new StringBuffer(); queryString.append(strUrl); for (Map.Entry<?, ?> pair : param.entrySet()) { queryString.append(pair.getKey() + "="); // 第一种方式使用的 jdk 自带的转码方式 第二种方式使用的 spring 的转码方法 两种均可 // queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&"); queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8") + "&"); } if (queryString.length() > 0) { queryString.deleteCharAt(queryString.length() - 1); } java.net.URL url = new URL(queryString.toString()); System.out.println(queryString.toString()); URLConnection httpConnection = (HttpURLConnection) url.openConnection(); httpConnection.connect(); InputStreamReader isr = new InputStreamReader(httpConnection.getInputStream()); BufferedReader reader = new BufferedReader(isr); StringBuffer buffer = new StringBuffer(); String line; while ((line = reader.readLine()) != null) { buffer.append(line); } reader.close(); isr.close(); //数据类型为json字符串 return buffer.toString(); } }
3、使用获取的道路信息,请求百度api获取每条道路的拥堵信息,并设置定时任务,没半小时请求一次
-
//启动类和定时任务上都得加上 @EnableScheduling //提供给spring管理 @Component public class Baidu {
定时任务主方法代码
-
将json映射Java实体类:实体类如下
-
//接收返回的百度api数据的总实体类 @Data public class BaiduReturn { private int status; private String message; private String description; private Evaluation evaluation; private List<RoadTraffic> road_traffic; }
-
//拥堵数据 @Data public class CongestionSection{ private String congestion_distance; private String speed; private int status; private String congestion_trend; private String section_desc; }
-
//拥堵状态 @Data public class Evaluation { private int status; private String status_desc; }
-
//路况数据 @Data public class RoadTraffic { private List<CongestionSection> congestion_sections; private String road_name; }
-
-
@Scheduled(cron = "0 0/30 * * * ?") public void scheduledTask() throws Exception { List<String> nameList; List<BaiduReturn> resultList = new ArrayList<>(); nameList = getRoadName(); for(int i = 0;i<nameList.size();i++){ BaiduApi snCal = new BaiduApi(); // 创建一个Map对象,用于存储请求参数 Map params = new LinkedHashMap<String, String>(); params.put("road_name", nameList.get(i)); params.put("city", "成都市"); params.put("ak", AK); String result = snCal.requestGetAK(URL, params); ObjectMapper objectMapper = new ObjectMapper(); // 使用 readValue 方法解析 JSON 字符串为 BaiduReturn 对象 BaiduReturn baiduReturn = objectMapper.readValue(result, BaiduReturn.class); if (baiduReturn.getStatus() == 0) { resultList.add(baiduReturn); } }
4、将获取的所有道路拥堵存入excel
-
主方法代码
-
写入excel表用的实体类如下
-
//用于写入excel的数据字段 @Data public class ExcelData { //城市名称 private String cityName; //道路名称 private String roadName; //道路详情 private String description; //道路状态 private String evalDesc; //道路拥堵距离 private String congestionDistance; //道路拥堵车速 private String speed; //道路拥堵地段 private String congestionTrend; //道路拥堵的时间 private String nowTime; }
-
-
//将数据写入excel for (BaiduReturn baiduReturn : resultList) { RoadTraffic roadTraffic = new RoadTraffic(); roadTraffic.setRoad_name(baiduReturn.getRoad_traffic().get(0).getRoad_name()); roadTraffic.setCongestion_sections(baiduReturn.getRoad_traffic().get(0).getCongestion_sections()); //转化为excel格式 ExcelData excelData = new ExcelData(); excelData.setCityName("成都市"); excelData.setDescription(baiduReturn.getDescription()); excelData.setEvalDesc(baiduReturn.getEvaluation().getStatus_desc()); excelData.setRoadName(roadTraffic.getRoad_name()); // 获取当前时间戳 long timestamp = System.currentTimeMillis(); // 将时间戳转换为Instant对象 Instant instant = Instant.ofEpochMilli(timestamp); // 转换为本地时间,指定时区 LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); // 定义日期时间格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"); // 格式化日期时间 String formattedDateTime = localDateTime.format(formatter); excelData.setNowTime(formattedDateTime); //不拥堵时,这几个字段是空,要进行判空处理 if (roadTraffic.getCongestion_sections() !=null) { excelData.setCongestionDistance(roadTraffic.getCongestion_sections().get(0).getCongestion_distance()); excelData.setSpeed(roadTraffic.getCongestion_sections().get(0).getSpeed()); excelData.setCongestionTrend(roadTraffic.getCongestion_sections().get(0).getSection_desc()); }else { excelData.setCongestionDistance(""); excelData.setSpeed(""); excelData.setCongestionTrend(""); } // // 写入Excel文件 String fileName = "src\\main\\resources\\static\\cd_road_traffic.xlsx"; writeBaiduReturnToExcel(excelData, fileName); } }
-
写入excel的代码
-
/** * 将数据写入excel */ public static void writeBaiduReturnToExcel(ExcelData excelData, String fileName) throws IOException, IllegalAccessException { FileInputStream fis = new FileInputStream(new File(fileName)); Workbook workbook = new XSSFWorkbook(fis); Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表 int rowCount = sheet.getLastRowNum(); // 行数从0开始计数,所以需要加1 int rowIndexToAppendAfter = rowCount; // 指定要在第几行之后追加数据(从0开始计数) fis = new FileInputStream(new File(fileName)); workbook = new XSSFWorkbook(fis); sheet = workbook.getSheetAt(0); // 获取第一个工作表 // 创建新行 Row newRow = sheet.createRow(rowIndexToAppendAfter + 1); List<String> list = new ArrayList<>(); // 通过反射获取ExcelData类的所有字段 Class<?> clazz = excelData.getClass(); // 遍历所有字段 for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); Object value = field.get(excelData); list.add(value != null ? value.toString() : null); } // 将list转换为字符串数组方便填充 String[] array = list.toArray(new String[0]); // 在新行中填充数据 for (int i = 0; i < array.length; i++) { Cell cell = newRow.createCell(i); cell.setCellValue(array[i]); } // 将更改写回文件 try (FileOutputStream fos = new FileOutputStream(fileName)) { workbook.write(fos); } }
-