这是一篇17年记的笔记,现在笔记vip过期了,懒得充值,现在把笔记都搬到CSDN上来,所以这篇文章属于从笔记誊抄过来的,那时的老代码,可能写的不够好,但是那个时候解决了朋友的一个小小需求,大家自行取舍看是否有帮助
昨天一朋友打来电话,问能不能帮忙写个程序从一个网站上抓一些数据,然后能通过Excel汇总出来,之前他是一条一条数据去查,查出来后复制粘贴到Excle里,比较耗时耗力,他大概说了下场景,大致是这样的:
- 先输入车牌号,点击查询按钮,查出车辆基本信息;
- 然后点击基本信息后面的详细按钮,弹出详情页
- 然后详情页里的信息一一copy到excel里保存下来
- 这样一来,如果只需要查询几个车牌的信息,那复制粘贴一下还行,如果有成百上千条车牌数据需要汇总,那真是一件令人崩溃的事情。
了解了需求以后,首先想到了用python来写个爬虫程序,python以前学过一点皮毛,能看懂,不咋会写;Java呢是老本行,但好像很少看过有人用Java去写爬虫;
- 网上找了些python爬网页的例子,照着操作了一下,发现能跑成功,但是好多语法不熟,写起来很慢,没有Java顺手,有的还不知道咋实现;研究一会不是很成功后,果断放弃,准备用Java来实现;
- 度娘了一下Java爬虫,还真有很一些人用Java做了一些例子,于是综合了几个例子,确定了用到哪些技术:解析网页用Jsoup(可以将网页解析成DOM对象,解析成功后可以使用类似于操作DOM对象的各种方法),导出用poi:
- 整理思路,先想办法读到网页上的所有有用信息,汇总起来,然后一起导出;
- 开工,先分析网页结构:
- 输入车牌号,点击查询按钮后,出现查询结果,然后F12打开Google浏览器的调试模式:
- 切换到Network,看到点击查询按钮后发出了如下请求,带了些如下参数:
- 分析查询结果页面,有用信息全部在这个tbody节点里(如车牌号,车辆颜色等)
- 再来分析点击详细按钮触发的事件
发现执行的是一个js方法,于是搜索该方法,发现写在一个js文件里,方法找到如下
可以看到ViewVehicleDetail('2407047', '粤BBC197', '黄色');
这个方法,对应的第一个参数是id
(应该是数据库里的记录id),第二个参数是车牌号
,第三个参数是车牌颜色
,这个方法其实也就是组装了一个a标签
,带上了这些关键信息,然后做了个a标签的触发事件
;点击后就弹到这条记录的详情页了:
查出来的结果全在这个tbody
里
- 输入车牌号,点击查询按钮后,出现查询结果,然后F12打开Google浏览器的调试模式:
原理搞清楚后,用程序实现起来就容易了
先理一下逻辑:先读到要查询的车牌号(不管读本地txt文件,还是Excle文件,或者是网页上做个输入框输入),然后一条一条模拟请求去查询,然后想办法解析出想要的数据,并且存起来,最后一起汇总导出成Excel;
-
建工程,用到的jar包(可以用Maven)
-
码代码
程序默认读取D盘根目录下的vehicle.txt,当然也可以在运行jar包的时候指定盘符,这样程序就会到指定盘符下读取;
package com.sayc.action; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.jsoup.Connection; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /** * 广东省道路运输管理局车辆信息查询系统 * @author sayc * @version 1.0 */ public class VehicleInfoQuery { public static void main(String[] args) { System.out.println("欢迎使用广东省道路运输车辆信息查询系统V1.0!"); // 盘符,默认是D盘 String driver = "D"; // 如果用户自己输入盘符,则使用用户输入的盘符 if (args.length == 1) { String userInput = args[0]; String regEx = "[C-Zc-z]{1}"; Pattern pattern = Pattern.compile(regEx); if (pattern.matcher(userInput).matches()) { if (userInput.equalsIgnoreCase("H")) { // Help帮助 System.out.println("语法:【java -jar car.jar d】 d表示d盘,代表您的文件存放在d盘根目录下,这里您可以指定您本机上的任意盘符;如有疑问,可联系sayc@foxmail.com"); return; } else { driver = userInput.toUpperCase(); } } else { System.err.println("语法有误,请重新输入,或者键入【java -jar car.jar h】获取帮助信息"); return; } } List<Map<String,String>> list = new ArrayList<Map<String,String>>(); // 读取车牌号信息 String carInfos = getCarInfo(driver + ":\\vehicle.txt"); if (StringUtils.isNotBlank(carInfos)) { if (carInfos.contains("\r\n")) { Map<String,String> data = null; String[] carArr = carInfos.split("\r\n"); for (int i = 0,len = carArr.length; i < len; i++) { String chepaihao = carArr[i]; if (StringUtils.isNotBlank(chepaihao)) { data = getCarInfos(chepaihao.trim()); if (data.isEmpty()) { System.err.println(String.format("*****异常:查询不到车牌号为%s的相关信息*****",chepaihao)); continue; } list.add(data); } else { System.err.println("*****错误:车牌号为空*****"); } } // 写入数据到Excel if (list != null && list.size() > 0) { createExcel(driver,carArr,list); } } } else { System.err.println("*****文件找不到!*****"); System.out.println("请输入:【java -jar car.jar d】 指定文件所在的盘(d表示d盘,您可以随意指定且大小写不限,如须帮助,请键入【java -jar car.jar h】获取帮助信息)"); } } /** * 连接信息公共设置 * @param conn */ public static void setConnection(Connection conn) { conn.timeout(30000); // 模拟请求头 conn.header("Accept", "*/*"); conn.header("Content-Type", "application/x-www-form-urlencoded"); conn.header("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"); } /** * 根据车牌号查询出车辆的详细信息 * @param chepaihao * @return 键值对形式的详细信息 */ public static Map<String, String> getCarInfos(String chepaihao) { Map<String,String> data = new HashMap<String,String>(); String url = "http://121.33.200.106:8010/IndustryData/Vehicle"; try { // 获取连接 Connection conn = Jsoup.connect