参考文章:https://blog.csdn.net/weixin_43638187/article/details/110220928。
一、爬取思路分析
爬取思路:首先就是获取每一个省,然后根据每一个省层层往下扒,直到获取完这个省下边的所有市县村,在获取下一个省的数据。
网址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/,如下所示:
可见最新的是2021年的,点击进入
1、获取所有省
获取所有省的URL:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/index.html
页面如下图所示:
查看网页源代码:
此时,北京市的<a>标签下的href属性为11.html
可以看到需要的数据是从一个class=‘provincetr’ 下的 <a> 标签中拿到的,我们主要的任务就是拿到class=‘provincetr’,并遍历获取所有 <td> 下的 <a> 标签 中数据,根据这个 *.html获取这个省下边的所有市信息。
2、获取所有市
获取所有市的URL:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/11.html,
可以看出获取所有市的数据是在baseUrl(“http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/”) 的基础上添加省获取到的herf=11.html得到的
页面如下所示:
查看网页源代码
此时,市辖区的<a>标签下的href属性为11/1101.html。根据这个11/1101.html获取这个市下边的所有区/县信息。
可以看到是拿到所有class=‘citytr’ 下的 <td> 标签中拿到的,与省的信息不同,这里市的信息有两个 <a> 标签我们需要的是第二个 <a> 标签里的数据,从href中可以获取code信息
3、获取所有区/县
获取所有区/县的URL:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/11/1101.html
可以看出获取所有区、县的数据是在baseUrl(“http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/”) 的基础上添加市获取到的herf=11/1101.html得到的
页面如下所示:
查看网页源代码
此时,东城区的<a>标签下的href属性为01/110101.html。根据这个01/110101.htmll获取这个区下边的所有街道办/镇信息。
区县数据,第一个市辖区,没 <a> 标签,除此之外和市区的数据格式一样,取class=‘countytr’,遍历获取所有的 <td> ,并获取 <td> 下第二个 <a> 中数据,其中href值为01/110101.html。
4、获取街道办/乡镇
获取街道办、镇的URL:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/11/01/110101.html
从区、县获取的herf=01/110101.html,对比url前边缺一个省的代码,因此使用省的code(即11)+区县herf(即01/110101.html)
页面如下图所示:
查看网页源代码
此时,东华门街道的<a>标签下的href属性为01/110101001.html。根据这个01/110101001.html获取这个街道下边的所有村信息。
可以看出来和市的数据结构差不多一样,只需要修改获取类的明显就,取class=‘towntr’,遍历获取所有的 <td> ,并获取 <td> 下第二个 <a> 中数据
5、获取社区/村
获取社区/村的URL:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/11/01/01/110101001.html
从乡、镇获取的herf=01/110101001.html,对比url前边缺一个省的代码+市(市代码为1101)的后两位代码,因此使用省的code(即11)+市的code(即01)+乡镇herf(即01/110101001.html)
页面如下所示:
查看网页源代码
6、注意事项
在获取街道办、乡镇的时候,在herf前边会新增一个省的code,在获取村、居委会的时候,在herf前边会增加一个市的code。
二、项目搭建
1、创建一个springboot工程并添加依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.10.2</version> </dependency> <dependency> <groupId>com.ejlchina</groupId> <artifactId>okhttps</artifactId> <version>2.4.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.8</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
发送http请求使用的okhttps;解析数据用的jsoup;数据库操作使用的mybatis(数据量比较大,可以使用批插入);commons-lang3 使用了一些其他工具类,如StringUtils,ObjectUtils等;
2、编写启动类
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } }
3、编写application.yml配置文件
server: port: 8080 spring: application: name: smallTools datasource: #数据库配置 driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 url: jdbc:mysql://127.0.0.1:3306/region?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false mybatis: mapper-locations: /mapper/*Mapper.xml
4、创建数据库region和表base-region-detail
脚本如下:
CREATE TABLE `base_region_detail` ( `region_code` varchar(255) NOT NULL COMMENT '区域代码', `region_name` varchar(255) DEFAULT NULL COMMENT '区域名称', `pid` varchar(255) DEFAULT NULL COMMENT '父级区域代码', `type` varchar(255) DEFAULT NULL COMMENT '0 省级/1 市级/2 区、县/3 乡镇、街道办/其他 村、社区111 主城区、112 城乡结合区、121 镇中心区、122 镇乡结合区、123 特殊区域、210 乡中心区、220 村庄', PRIMARY KEY (`region_code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
5、创建实体类
@Data public class BaseRegionDetail { /*** * 区域代码 */ private String regionCode; /*** * 区域名称 */ private String regionName; /*** * 父级区域代码 */ private String pid; /*** * 区域类型 */ private String type; }
6、编写dao接口
@Mapper public interface BaseRegionDetailDao { /*** * 根据 regionCode 查找 * @param regionCode 区域CODE * @return */ List<BaseRegionDetail> find(String regionCode, String regionName, String pid); /*** * 批量插入 * @param list 皮插入参数 */ void insert(List<BaseRegionDetail> list); /*** * 获取数据库保存的最后一个省 * @return */ List<String> getAllProvince(); /*** * 获取当前省的最后一个市信息 * @param regionCode * @return */ String getLastCityForPro(String regionCode); }
7、编写mapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zwh.dao.BaseRegionDetailDao"> <!-- namespace指向对应的dao --> <select id="find" resultType="com.zwh.domain.BaseRegionDetail"> select * from base_region_detail where 1 = 1 <if test="regionCode != null and regionCode != ''"> and region_code = #{regionCode,jdbcType=VARCHAR} </if> <if test="regionName != null and regionName != ''"> and region_name = #{regionName,jdbcType=VARCHAR} </if> <if test="pid != null and pid != ''"> and pid = #{pid,jdbcType=VARCHAR} </if> </select> <insert id="insert" parameterType="List"> insert into base_region_detail ( region_code, region_name, pid, type ) values <foreach collection="list" item="detail" index="index" separator=","> ( #{detail.regionCode,jdbcType=VARCHAR}, #{detail.regionName,jdbcType=VARCHAR}, #{detail.pid,jdbcType=VARCHAR}, #{detail.type,jdbcType=VARCHAR} ) </foreach> </insert> <select id="getAllProvince" resultType="string"> select region_code from base_region_detail where type = "0" </select> <select id="getLastCityForPro" resultType="string"> select MAX(region_code) from base_region_detail where pid = #{regionCode,jdbcType=VARCHAR} </select> </mapper>
8、编写配置类SpiderPropertyModel
@Data @Component @ConfigurationProperties(prefix = "spider") public class SpiderPropertyModel { /*** * 爬取年份数据 */ private String spiderYear = "2021"; /*** * 是否开启动态IP代理 */ private Boolean proxyEnable = false; /*** * 设置ip代理后ip.txt地址 */ private String ipLocation = "111"; /*** * 是否开启 市级睡眠 */ private Boolean isCitySleep = true; /*** * 市级睡眠默认时间 s级 */ private Integer citySleepTime = 30; /*** * 是否开启 区、县 级睡眠 */ private Boolean isCountySleep = false; /*** * 区、县 级睡眠默认时间 s级 */ private Integer countySleepTime = 30; /*** * 是否获取乡镇、街道信息 */ private Boolean getTowntr = false; /*** * 是否获取村、社区信息 */ private Boolean getVillagetr = false; }
spiderPropertyModel是一个配置类,定义了一些配置信息,如是否开启Ip代理,sleep的时间等
application.yml中新增配置如下:
spider: spider-year: 2021 # 爬取年份的数据 proxy-enable: false # 是否开启动态代理 ip-location: 222 #开启的话需要ip地址的存放位置 is-city-sleep: true #是否开启市级睡眠 city-sleep-time: 30 #开启市级睡眠 的睡眠时间 s is-county-sleep: true #是否开启区 县睡眠 county-sleep-time: 15 #开启县级睡眠 的睡眠时间 s get-villagetr: false # 是否获取村、社区信息 get-towntr: false # 是否获取乡镇、街道信息
注意:如果只获取省市县,则get-villagetr和get-towntr的值设为false。如果还要获取乡镇/街道、村/社区的信息,则将get-villagetr和get-towntr的值设为true。
9、编写service
import com.ejlchina.okhttps.HTTP; import com.ejlchina.okhttps.HttpResult; import com.zwh.config.SpiderPropertyModel; import com.zwh.dao.BaseRegionDetailDao; import com.zwh.domain.BaseRegionDetail; import okhttp3.ConnectionPool; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import org.apache.commons.lang3.StringUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.*; import java.net.InetSocketAddress; import java.net.Proxy; import java.util.*; import java.util.concurrent.TimeUnit; @Service public class BaseRegionDetailService { @Autowired private SpiderPropertyModel spiderPropertyModel; @Autowired private BaseRegionDetailDao baseRegionDetailDao; private static HTTP http = null; private static List<Map<String, Object>> proxyList = null; /*** * 初始化 http * @Param isChange 是否发需要切换代理Ip * @return */ private void initHttpClint() { http = HTTP.builder() .config(new HTTP.OkConfig() { @Override public void config(OkHttpClient.Builder builder) { // 配置连接池 最小10个连接(不配置默认为 5) builder.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES)); // 配置连接超时时间(默认10秒) builder.connectTimeout(1000, TimeUnit.SECONDS); // 配置 WebSocket 心跳间隔(默认没有心跳) builder.pingInterval(60, TimeUnit.SECONDS); // 配置拦截器 builder.addInterceptor((Interceptor.Chain chain) -> { Request request = chain.request(); // 必须同步返回,拦截器内无法执行异步操作 return chain.proceed(request); }); // 其它配置: CookieJar、SSL、缓存、代理、事件监听... // 是否需要开启动态代理Ip if (spiderPropertyModel.getProxyEnable()) { // 从ipLocation 中获取 ipList getProxy(spiderPropertyModel.getIpLocation()); Map<String, Object> proxy = proxyList.get(new Random().nextInt(proxyList.size())); String ip = proxy.get("ip").toString(); System.out.println("--------代理Ip------------" + ip); int port = Integer.parseInt(proxy.get("port").toString()); System.out.println("----------端口------------" + port); builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ip, port))); } } }) .baseUrl("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/" + spiderPropertyModel.getSpiderYear() + "/") .build(); } /*** * 发送http请求 * @param childHref 访问得子页面 * @return */ private String toGet(String childHref) { BufferedReader in = null; String ret = ""; HttpResult httpResult = null;// GET请求 try { httpResult = http.sync(childHref) .get(); if (httpResult.isSuccessful()) { try { // in = new BufferedReader(new InputStreamReader(httpResult.getBody().toByteStream(), "GB2312")); in = new BufferedReader(new InputStreamReader(httpResult.getBody().toByteStream(), "UTF-8")); String line = ""; while ((line = in.readLine()) != null) { ret += line; } if (StringUtils.isBlank(ret)) { System.out.println("-----获取到得ret == '' ----"); initHttpClint(); toGet(childHref); } } catch (IOException e) { in.close(); } } } catch (Exception e) { // e.printStackTrace(); System.out.println("-----连接超时,请求切换代理IP----"); initHttpClint(); toGet(childHref); } return ret; } /*** * 获取省信息 */ public void getProvince() throws InterruptedException { // 初始化 httpClint initHttpClint(); // 从index.html 中获取所有 省、直辖市、自治区 数据 Document doc = Jsoup.parse(toGet("/index.html")); // 解析html文档,返回Document对象 Elements provincetrEles = doc.getElementsByClass("provincetr"); // 根据类名获取元素对象集合 // 查找数据库中保存的最后一个省的regionCode List<String> provinceCodeList = baseRegionDetailDao.getAllProvince(); for (Element e : provincetrEles) { Elements tdEles = e.getElementsByTag("td"); // 获取provincetr下面所有的td for (Element td : tdEles) { // 遍历所有 <td> Elements a = td.select("a"); // 查找a标签元素 if (!a.isEmpty()) { // 解析数据 获取 指向市的href String href = td.select("a").attr("href"); // 获取a标签的href属性的值 // 获取省份名称 String name = td.select("a").text().trim(); // 获取a标签文本内容 // 获取省份代码 String areaCode = ""; areaCode = href.substring(0, href.indexOf(".")) + "00"; // 两位省的code,后面补两个零,如北京11后补两个零为1100 String last2code = getLast2code(href, 0, 2); // 根据href值取前两位得到省的代码,如11 // 判断 数据库中 没有省信息 则证明是第一次爬取 if (provinceCodeList == null || !provinceCodeList.contains(areaCode)) { System.out.println("--------------省-------------"); System.out.println("省: " + name + " 代码:" + areaCode + " href:" + href); // 保存省信息数据 ArrayList<BaseRegionDetail> list = new ArrayList<>(); list.add(createModel(name, areaCode, "0", "0")); // 将该省的name和areaCode、pid、type存入实体类对象,再将实体类对象存入list集合中 baseRegionDetailDao.insert(list); // 将list集合中的数据批量插入数据库 getCity(toGet(href), areaCode, last2code); // 根据每一个省层层往下爬取 provinceCodeList.add(areaCode); // 将areaCode存入集合,就不会重复插入表 } else { // 则证明 最后spider 的是个省 不进行保存 直接开始进入 此省的市判断 getCity(toGet(href), areaCode, last2code); } System.out.println("--------------省-------------"); } } } } /*** * 获取城市 * @param cityHtmlStr http 请求回来的市body * @param pid 父Id * @param provinceCode 省ID */ private void getCity(String cityHtmlStr, String pid, String provinceCode) throws InterruptedException { List<BaseRegionDetail> list = null; Document doc = Jsoup.parse(cityHtmlStr); // 解析html文档,返回Document对象 Elements citytrEles = doc.getElementsByClass("citytr"); // 根据类名获取元素对象集合 for (Element e : citytrEles) { // 每个市及市下边的数据 保存一下 list = new ArrayList<>(); Elements tdEles = e.getElementsByTag("td"); // 根据标签名称获取元素对象集合 Element td = tdEles.last(); // 得到第二个td Elements a = td.select("a"); // 查找第二个td中a标签元素 if (!a.isEmpty()) { String href = td.select("a").attr("href"); // 获取第二个td中a标签的href属性值 String name = td.select("a").text().trim(); // 获取第二个td中a标签的文本内容 String areaCode = ""; // href = 14/1401.html areaCode = href.substring(href.indexOf("/") + 1, href.indexOf(".")); // 获取/后面.前面的code,该code为市的code System.out.println("市: " + name + " 代码:" + areaCode + " href:" + href); // 判断此城市是否已经存在数据库中 List<BaseRegionDetail> detailModels = baseRegionDetailDao.find(areaCode, null, null); if (detailModels == null || detailModels.size() == 0) { // 获取 code 末尾两码 list.add(createModel(name, areaCode, pid, "1")); // 将市的name、areaCode、pid、type存入对象中,再将对象存入list集合中 // 获取市下边的 县、区 信息 getCounty(toGet(href), list, areaCode, provinceCode); if (list.size() > 0) { baseRegionDetailDao.insert(list); // 将list集合中的数据批量插入数据库 if (spiderPropertyModel.getIsCitySleep()) { // 每个市之间要歇息15s,否则频繁的访问网站可能被加入黑名单 System.out.println("-----------市级睡眠 " + spiderPropertyModel.getCitySleepTime() + " s 开始---------"); TimeUnit.SECONDS.sleep(spiderPropertyModel.getCitySleepTime()); System.out.println("-----------市级睡眠结束----------"); } } } } } } /*** * 获取 区县 代码 * @param cityHtmlStr * @param list * @param pid * @param provinceCode */ private void getCounty(String cityHtmlStr, List<BaseRegionDetail> list, String pid, String provinceCode) throws InterruptedException { Document doc = Jsoup.parse(cityHtmlStr); // 解析html文档,返回Document对象 Elements countytrEles = doc.getElementsByClass("countytr"); // 根据类名获取元素对象集合 for (Element tr : countytrEles) { // 如果没有获取到 a标签 Elements tdEles = tr.getElementsByTag("td"); if (tdEles.select("a").isEmpty()) { String name = tdEles.last().text(); String areaCode = tdEles.first().text().substring(0, 6); // // href = 01/140105.html 区往街道走 要获取上一级的14/01/140105 System.out.println("区、县: " + name + " 区、县:" + areaCode); list.add(createModel(name, areaCode, pid, "2")); } else { Element td = tdEles.last(); Elements a = td.select("a"); if (!a.isEmpty()) { String href = td.select("a").attr("href"); // 获取第二个td中a标签的href属性值 String name = td.select("a").text().trim(); // 获取第二个td中a标签的文本内容 String areaCode = ""; areaCode = href.substring(href.indexOf("/") + 1, href.indexOf(".")); // 获取/后面.前面的code,该code为区/县的code System.out.println("区、县: " + name + " 区、县:" + areaCode + " href:" + href); list.add(createModel(name, areaCode, pid, "2")); // 将该区/县加入list集合 String cityCode = getLast2code(href, 0, 2); // 获取href属性值的前两位作为区/县的code href = "/" + provinceCode + "/" + href; // 使用省的code(即11)+区县herf(即01/110101.html) // 是否获取乡镇、街道信息 if (spiderPropertyModel.getGetTowntr()) { getTowntr(toGet(href), list, areaCode, provinceCode, cityCode); } } } if (spiderPropertyModel.getIsCountySleep()) { System.out.println("-----------区、县 级睡眠 " + spiderPropertyModel.getCountySleepTime() + " s 开始---------"); TimeUnit.SECONDS.sleep(spiderPropertyModel.getCountySleepTime()); // 每个区/县之间要歇息30s,否则频繁的访问网站可能被加入黑名单 System.out.println("-----------区、县 市级睡眠结束----------"); } } } /*** * 获取 乡镇 街道办 信息 */ private void getTowntr(String towntrHtmlStr, List<BaseRegionDetail> list, String pid, String provinceCode, String cityCode) { Document doc = Jsoup.parse(towntrHtmlStr); // 解析html文档,返回Document对象 Elements countytrEles = doc.getElementsByClass("towntr"); // 根据类名获取元素对象集合 for (Element tr : countytrEles) { // 如果没有获取到 a标签 Elements tdEles = tr.getElementsByTag("td"); Element td = tdEles.last(); // 取第二个td Elements a = td.select("a"); if (!a.isEmpty()) { String href = td.select("a").attr("href"); // 获取第二个td中a标签的href属性值 String name = td.select("a").text().trim(); // 获取第二个td中a标签的文本内容 String areaCode = ""; areaCode = href.substring(href.indexOf("/") + 1, href.indexOf(".")); // 获取/后面.前面的code,该code为乡镇/街道办的code //System.out.println("街道办: " + name + " 代码:" + areaCode + " href:" + href); list.add(createModel(name, areaCode, pid, "3")); href = "/" + provinceCode + "/" + cityCode + "/" + href; // 使用省的code(即11)+市的code(即01)+乡镇herf(即01/110101001.html) // 是否获取村、社区信息 if (spiderPropertyModel.getGetVillagetr()) { getVillagetr(toGet(href), list, areaCode); } } } } /*** * 获取 村 社区 居委会信息 * @param villagetrHtmlStr * @param list * @param pid */ private void getVillagetr(String villagetrHtmlStr, List<BaseRegionDetail> list, String pid) { Document doc = Jsoup.parse(villagetrHtmlStr); Elements countytrEles = doc.getElementsByClass("villagetr"); for (Element tr : countytrEles) { Elements tdEles = tr.getElementsByTag("td"); if (tdEles != null && tdEles.size() > 0) { Element first = tdEles.get(0); Element last = tdEles.get(2); // 解析 获取 regionName,regionCode list.add(createModel(last.text().trim(), first.text().trim(), pid, tdEles.get(1).text().trim())); } } } /*** * 取herf得前两位 * @param regionCode * @return */ private String getLast2code(String regionCode, int startIndex, int endIndex) { return regionCode.substring(startIndex, endIndex); } /*** * 获取 id代理 库 */ private void getProxy(String ipLocation) { // 1,建立联系 File file = new File(ipLocation); //2,选择流 InputStream is = null; try { is = new FileInputStream(file); BufferedReader in2 = new BufferedReader(new InputStreamReader(is)); // 设置缓冲区域,就像搬家一样,定义一个车子来搬家 byte[] data = new byte[1024]; // 记录实际读取的长度,就像搬家一样,不是说每个都是刚好一车就装满了的 proxyList = new ArrayList<>(); String y = ""; // read 将字节流读取到 定义 的 data 中,len 记录每次读取的长度,当 is 的数据读完之后len的值则为-1 while ((y = in2.readLine()) != null) { HashMap<String, Object> map = new HashMap<>(); String[] split = y.split(":"); map.put("ip", split[0]); map.put("port", split[1]); proxyList.add(map); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (null != is) { try { // 4,释放资源 is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /*** * 创建 regionModel * @param regionName * @param regionCode * @param pid * @param type * @return */ private BaseRegionDetail createModel(String regionName, String regionCode, String pid, String type) { BaseRegionDetail model = new BaseRegionDetail(); model.setRegionName(regionName); model.setRegionCode(regionCode); model.setPid(pid); model.setType(type); return model; } }
10、编写controller
@RestController @RequestMapping("/utils") public class BaseRegionDetailsController { @Autowired BaseRegionDetailService baseRegionDetailService; /*** * 批量插入 */ @RequestMapping("/getAllRegion") public void insert() { try { baseRegionDetailService.getProvince(); } catch (InterruptedException e) { e.printStackTrace(); } } }
总结:全国共有31个省/直辖市,共有342市,共有3238个县。