Java:基于Java的爬虫程序示例

这篇博客分享了一次使用Java实现爬虫程序的实践过程,旨在解决批量查询车辆信息并汇总到Excel的问题。通过解析网页DOM结构,利用Jsoup库抓取数据,结合poi库导出到Excel。程序首先分析请求和响应,模拟HTTP请求获取信息,然后存储并导出。升级版程序增加了请求间隔,避免对服务器造成过大压力。
摘要由CSDN通过智能技术生成

这是一篇17年记的笔记,现在笔记vip过期了,懒得充值,现在把笔记都搬到CSDN上来,所以这篇文章属于从笔记誊抄过来的,那时的老代码,可能写的不够好,但是那个时候解决了朋友的一个小小需求,大家自行取舍看是否有帮助

昨天一朋友打来电话,问能不能帮忙写个程序从一个网站上抓一些数据,然后能通过Excel汇总出来,之前他是一条一条数据去查,查出来后复制粘贴到Excle里,比较耗时耗力,他大概说了下场景,大致是这样的:
  1. 先输入车牌号,点击查询按钮,查出车辆基本信息;
    在这里插入图片描述
  2. 然后点击基本信息后面的详细按钮,弹出详情页
    在这里插入图片描述
  3. 然后详情页里的信息一一copy到excel里保存下来
  • 这样一来,如果只需要查询几个车牌的信息,那复制粘贴一下还行,如果有成百上千条车牌数据需要汇总,那真是一件令人崩溃的事情。
    了解了需求以后,首先想到了用python来写个爬虫程序,python以前学过一点皮毛,能看懂,不咋会写;Java呢是老本行,但好像很少看过有人用Java去写爬虫;
  • 网上找了些python爬网页的例子,照着操作了一下,发现能跑成功,但是好多语法不熟,写起来很慢,没有Java顺手,有的还不知道咋实现;研究一会不是很成功后,果断放弃,准备用Java来实现;
  • 度娘了一下Java爬虫,还真有很一些人用Java做了一些例子,于是综合了几个例子,确定了用到哪些技术:解析网页用Jsoup(可以将网页解析成DOM对象,解析成功后可以使用类似于操作DOM对象的各种方法),导出用poi:
  • 整理思路,先想办法读到网页上的所有有用信息,汇总起来,然后一起导出;
  • 开工,先分析网页结构:
    1. 输入车牌号,点击查询按钮后,出现查询结果,然后F12打开Google浏览器的调试模式:
      在这里插入图片描述
    2. 切换到Network,看到点击查询按钮后发出了如下请求,带了些如下参数:
      在这里插入图片描述
    3. 分析查询结果页面,有用信息全部在这个tbody节点里(如车牌号,车辆颜色等)
      在这里插入图片描述
    4. 再来分析点击详细按钮触发的事件
      在这里插入图片描述
      发现执行的是一个js方法,于是搜索该方法,发现写在一个js文件里,方法找到如下
      在这里插入图片描述
      可以看到ViewVehicleDetail('2407047', '粤BBC197', '黄色');这个方法,对应的第一个参数是id(应该是数据库里的记录id),第二个参数是车牌号,第三个参数是车牌颜色,这个方法其实也就是组装了一个a标签,带上了这些关键信息,然后做了个a标签的触发事件;点击后就弹到这条记录的详情页了:
      在这里插入图片描述
      查出来的结果全在这个tbody
      在这里插入图片描述

原理搞清楚后,用程序实现起来就容易了
先理一下逻辑:先读到要查询的车牌号(不管读本地txt文件,还是Excle文件,或者是网页上做个输入框输入),然后一条一条模拟请求去查询,然后想办法解析出想要的数据,并且存起来,最后一起汇总导出成Excel;

  1. 建工程,用到的jar包(可以用Maven)
    在这里插入图片描述

  2. 码代码

    程序默认读取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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值