起因

准备做一个省级联动的功能,从网页上查找了很多资源符合要求的很少(缺失港澳台数据,不好实现直辖市、特别行政区判断)。复制代码,能直接运行。

数据来源:中国统计局标准 http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/
运行环境:jdk8;

代码

jar 包

<!-- 依赖包 --><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.11.3</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.5.11</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.35</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.1</version></dependency>

_服务实现类 _ChinasServiceImpl

package com.hn.yuan.city.service.impl;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.hn.yuan.city.entity.Chinas;
import com.hn.yuan.city.mapper.ChinasMapper;
import com.hn.yuan.city.service.ChinasService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hn.yuan.reptileCity.demoTest.Test;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;/*** <p>* 服务实现类* </p>** @author XIAOCAO* */
@Service
public class ChinasServiceImpl extends ServiceImpl<ChinasMapper, Chinas> implements ChinasService {@Autowiredprivate ChinasMapper chinasMapper;/*什么情况下使用AtomicInteger1、作为多个线程同时使用的原子计数器。2、在比较和交换操作中实现非阻塞算法。https://www.jianshu.com/p/073096a729f6*/public String addChinas(Chinas chinas) {chinasMapper.insert(chinas);return "成功";}private static final Logger log = LoggerFactory.getLogger(Test.class);//AtomicInteger类是系统底层保护的int类型,通过提供执行方法的控制进行值的原子操作private static AtomicInteger atomicInteger = new AtomicInteger(0);private static AtomicInteger atomicIntegerErrorNum = new AtomicInteger(0);public void test(String appendProvide, String appendCity) {System.out.println("===============开始抓取数据=================");var url = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/index.html";String html = HttpUtil.get(url);var htmlDoc = Jsoup.parse(html);var selectClasses = htmlDoc.getElementsByClass("provincetr");var startDateStr = DateUtil.formatDateTime(new Date());long startDate = System.currentTimeMillis();
//        ExecutorService executorService = new ThreadPoolExecutor(4, 5, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory());for (int i = 0; i < selectClasses.size(); i++) {int finalI = i;
//            executorService.execute(() -> {//                System.out.println(Thread.currentThread().getName() + " " + "--->开始爬数据");try {//一个线程跑就行startProvide(selectClasses, finalI, baseUrl, appendProvide, appendCity);} catch (Exception e) {e.printStackTrace();}}System.out.println("耗时 =》");System.out.println((System.currentTimeMillis() - startDate) / 1000);System.out.println("开始时间 ==> " + startDateStr);System.out.println("结束时间 ==>" + DateUtil.formatDateTime(new Date()));}private String getHtml(String url) throws Exception {//以原子方式将当前值递增1并在递增后返回新值。它相当于i ++操作。atomicInteger.incrementAndGet();log.info("调用接口次数 :" + atomicInteger.get());log.info("请求开始时间 ==>" + DateUtil.formatDateTime(new Date()));log.info(url);String html = null;try {html = getHtml2(url);} catch (Exception e) {e.printStackTrace();log.info(Thread.currentThread().getName() + " = 超时。。睡5秒再重试");Thread.sleep(1000 * 5);log.info(Thread.currentThread().getName() + " = 超时重试");atomicIntegerErrorNum.incrementAndGet();log.info("error num = " + atomicIntegerErrorNum.get());try {//重试1次html = getHtml2(url);} catch (Exception e2) {e2.printStackTrace();log.info("error num = " + atomicIntegerErrorNum.get());log.info(Thread.currentThread().getName() + " 第二次超时重试");log.info(Thread.currentThread().getName() + " = 第二次超时。。睡12分钟再重试");log.info("error num = " + atomicIntegerErrorNum.get());Thread.sleep(1000 * 60 * 12);//重试2次html = getHtml2(url);}}log.info("请求结束时间 ==>" + DateUtil.formatDateTime(new Date()));System.out.println("");System.out.println("");return html;}private String getHtml2(String url) throws Exception {//链式构建请求return HttpRequest.get(url).header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36")//头信息,多个头信息多次调用此方法即可.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")//头信息,多个头信息多次调用此方法即可.header("Cookie", "_trs_uv=" + IdUtil.simpleUUID() + "; SF_cookie_1=" + IdUtil.fastUUID()).header("If-None-Match", "f32-5d4bccaa05a80-gzip")
//                    .header("If-Modified-Since",new Date())
//                    .form(paramMap)//表单内容.timeout(15000)//超时,毫秒.execute().body();}//国家统计局链接public static String baseUrl = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/";/*** @param selectClasses* @param i* @param baseUrl* @param appendProvide 需要查询的省  ,null表示查询所有* @throws Exception*/private void startProvide(Elements selectClasses, Integer i, String baseUrl, String appendProvide, String appendCity) throws Exception {var provideCodes = selectClasses.get(i).children();//1.省份 provincetrfor (int provideCodeIndex = 0; provideCodeIndex < provideCodes.size(); provideCodeIndex++) {var provideCodeUrl = provideCodes.get(provideCodeIndex).select("a").attr("href");var provideName = provideCodes.get(provideCodeIndex).select("a").text();
//            System.out.println("省份 = " + provideName);if (!StringUtils.isBlank(provideCodeUrl)) {if (StringUtils.isBlank(appendProvide)) {provide(provideCodeUrl, provideName, null);} else {if (appendProvide.equals(provideName)) {System.out.println("要的省份 = " + provideName);provide(provideCodeUrl, provideName, appendCity);}}}}}/*** 通过省,市获取下面的数据** @param provideCodeUrl*/public void provide(String provideCodeUrl, String provideName, String appendCity) throws Exception {var provideCode = provideCodeUrl.split("\\.")[0];//                    String gotoCityHtml = HttpUtil.get(baseUrl + provideCodeUrl);String gotoCityHtml = getHtml(baseUrl + provideCodeUrl);var cityHtmlDoc = Jsoup.parse(gotoCityHtml);Elements selectCityClass = cityHtmlDoc.select(".citytr");//拼接省code码插入数据库var len = provideCode.length();var provideCode2 = provideCode;if (len < 6) {len = 6 - len;for (int l = 0; l < len; l++) {provideCode2 += "0";}}if (StringUtils.isBlank(appendCity)) {//todo 保存到数据库  保存省System.out.println("保存数据库的id:" + provideCode2 + "省名称:" + provideName + "code码:" + provideCode2 + "level:" + 1);Chinas chinas = new Chinas().setCode(Long.valueOf(provideCode2)).setName(provideName).setPid(Long.valueOf(0)).setLevel("1");this.addChinas(chinas);city(selectCityClass, provideName, provideCode, null);} else {city(selectCityClass, provideName, provideCode, appendCity);}}/*** 城市** @param selectCityClass* @param provideName* @param provideCode* @throws Exception*/private void city(Elements selectCityClass, String provideName, String provideCode, String appendCity) throws Exception {//2.城市  citytrfor (int cityIndex = 0; cityIndex < selectCityClass.size(); cityIndex++) {var gotoCountyUrl = selectCityClass.get(cityIndex).select("td").get(1).select("a").attr("href");var cityName = selectCityClass.get(cityIndex).select("td").get(1).select("a").text();if (StringUtils.isBlank(gotoCountyUrl)) {continue;}if (StringUtils.isBlank(appendCity)) {this.appendCity(gotoCountyUrl, provideName, provideCode, cityName);} else {if (appendCity.equals(cityName)) {this.appendCity(gotoCountyUrl, provideName, provideCode, cityName);}}}}private void appendCity(String gotoCountyUrl, String provideName, String provideCode, String cityName) throws Exception {//String countytr = HttpUtil.get(baseUrl + gotoCountyUrl);boolean flag = true;String countytr = getHtml(baseUrl + gotoCountyUrl);var countytrDoc = Jsoup.parse(countytr);Elements countyClass = countytrDoc.select(".countytr");if (countyClass.size() == 0) {flag = false;countyClass = countytrDoc.select(".towntr");}var strCityUrl = gotoCountyUrl.split("/");var cityCode = strCityUrl[strCityUrl.length - 1].split("\\.")[0];var cityCodeLen = cityCode.length();var cityCode2 = cityCode;if (cityCodeLen < 6) {cityCodeLen = 6 - cityCodeLen;for (int l = 0; l < cityCodeLen; l++) {cityCode2 += "0";}}if (cityName.equals("市辖区")) {cityName = provideName;}cityCode = cityCode2;//拼接省code码插入数据库var len = provideCode.length();var provideCode2 = provideCode;if (len < 6) {len = 6 - len;for (int l = 0; l < len; l++) {provideCode2 += "0";}}if (!flag) {System.out.println("直辖市,进入此方法");} else {//todo 保存到数据库   保存城市System.out.println("保存数据库的市id:" + cityCode + " 市名称:" + cityName + " code码:" + provideCode2 + "level:" + 2);Chinas chinas = new Chinas().setCode(Long.valueOf(cityCode)).setName(cityName).setPid(Long.valueOf(provideCode2)).setLevel("2");this.addChinas(chinas);county(countyClass,provideName,provideCode, cityCode);}}/*** 街道** @param countyClass* @param provideCode*/private void county(Elements countyClass, String provideName, String provideCode, String cityCode) throws Exception {//3.县区  countytrfor (int county = 0; county < countyClass.size(); county++) {var gotoTownUrl = countyClass.get(county).select("td").get(1).select("a").attr("href");var countyName = countyClass.get(county).select("td").get(1).select("a").text();if (StringUtils.isBlank(gotoTownUrl)) {continue;}String gotoTownUrls = StringUtils.substringBetween(gotoTownUrl, "/", ".");//todo 保存到数据库System.out.println("保存数据库的县 区数据id:" + gotoTownUrls + " 县区名称:" + countyName + " code码:" + cityCode + "level:" + 3);Chinas chinas = new Chinas().setCode(Long.valueOf(gotoTownUrls)).setName(countyName).setPid(Long.valueOf(cityCode)).setLevel("3");this.addChinas(chinas);}}}

_服务类 _ChinasService

package com.hn.yuan.city.service;import com.hn.yuan.city.entity.Chinas;
import com.baomidou.mybatisplus.extension.service.IService;/*** <p>*  服务类* </p>* @author XIAOCAO* */
public interface ChinasService extends IService<Chinas> {public void test(String appendProvide, String appendCity);
}

测试类 testDemo

package com.hn.yuan.city;import com.hn.yuan.city.service.ChinasService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest
public class testDemo {@Autowiredprivate ChinasService chinasService;@Testpublic void tests() {//获取所有的数据chinasService.test(null, null);//获取指定的城市//chinasService.test("河南省", "郑州市");}}

注意:controller、service、mapper、entity层通过mybatis-plus自动生成的;此方法不涉及controller,mapper,entity;
全面省市区县居委5级详情看转载:https://blog.csdn.net/qq_15421685/article/details/124754314

Mysql数据表数据包含港澳台

https://pan.baidu.com/s/1CwnmUGSPFzhZdwIWNTwd_Q?pwd=1102
提取码:1102

各位看官》创作不易,点个赞!!!
诸君共勉:万事开头难,只愿肯放弃。

免责声明:本文章仅用于学习参考


实战模式-Vue+Java后台实现省市区三级联动
实战模式-微信小程序java后台+mysql实现省市区三级联动
微信小程序组件简易实现省市区三级联动
免责声明:本文章仅用于学习参考

爬虫模式-JAVA获取省市区编码相关推荐

  1. java获取文件编码

    目录 1. 概述 2. 编码基本知识 2.1. iso8859-1 2.2. GB2312/GBK 2.3. unicode 2.4. UTF 3.JAVA中移位运算>> , <&l ...

  2. 爬虫中如何获取页面编码类型

    获取页面的编码格式的三种方式: 根据Response中的header获取编码格式 根据页面标签中的meta获取 根据页面内容识别自动识别出编码格式,经过测试准确率比较高 三种方式可以结合使用,由于in ...

  3. java获取文件编码_java如何获取文件编码格式

    1:简单判断是UTF-8或不是UTF-8,因为一般除了UTF-8之外就是GBK,所以就设置默认为GBK. 按照给定的字符集存储文件时,在文件的最开头的三个字节中就有可能存储着编码信息,所以,基本的原理 ...

  4. java 获取网页编码_spider JAVA如何判断网页编码

    前言 最近做一个搜索项目,需要爬取很多网站获取需要的信息.在爬取网页的时候,需要获得该网页的编码,不然的话会发现爬取下来的网页有很多都是乱码. 分析 一般情况下,网页头信息会指定编码,可以解析head ...

  5. java获取参数编码_java获取接口数据编码问题

    需求比较简单,就是获取接口数据并返回.但是在用的过程中发现编码问题.接口返回的数据编码为UTF-8,希望显示的数据也是UTF-8,问题出在从输入流中读取数据的过程中.下面是几个实例程序. 1.不管编码 ...

  6. java获取网页编码_java根据URL获取网页编码

    由于很多原因,我们要获取网页的编码(多半是写批量抓取的脚本吧...嘻嘻嘻) 注意: 如果你的目的是获取不乱码的网页内容(而不是根据网址发送post请求获取返回值),切记切记,移步这里 先说思路: 有三 ...

  7. 获取GBK编码的汉字笔画数

    GBK编码的汉字大概20000个左右,简繁两种字体的笔画数都可以得到,以下是源代码: 代码比较简单,重点在配置文件中,由于文件的内容比较多没办法为大家展示出来,有需要的朋友可以留下自己邮箱,我给你们发 ...

  8. 用java实现网络爬虫,实时获取中国地震台网数据

    用java实现网络爬虫,实时获取中国地震台网数据 1.如何从网络中爬取相关数据 2.怎么进行数据处理 3.绘图设计 4. 存在问题: 5.java程序的源文件 5.1 爬虫程序 5.2 绘制柱状图程序 ...

  9. 获取房屋编码的校验码的java和C#版本

    获取房屋编码的校验码java版 //获取房屋编码的校验码private String getC(String str_in){String rbc="";//26位加权因子int ...

最新文章

  1. 聊聊这两年学习slam啃过的书!
  2. 《Visual C++ 开发从入门到精通》——2.7 变量
  3. “后浪95后”吴尚哲的 CVPR 最佳论文:无需任何监督,即可重建三维图像
  4. 什么是前后端分离 前后端不分离
  5. python 按从小到大的顺序组合成一个字典_Python实现字典排序、按照list中字典的某个key排序的方法示例...
  6. Burpsuite学习(2)
  7. 百善计算机学习,党建引领学做合一,志愿服务助力乡村振兴——计算机工程学院开展“百善孝为先”主题宣传文化墙墙绘涂鸦活动...
  8. EaglePHP开源框架全新改版(v1.8)
  9. 信息学奥赛一本通(2027:【例4.13】三角形)
  10. 7 大版块 | 全面解读与认知支付系统
  11. 第2章 JSP数据交互(一)
  12. Git来回切换版本的时候,pom文件变黄,每次都需要重新添加到maven以及修改后文件不生效的解决方法
  13. STM32神舟III号 驱动直流电机学习(四 )
  14. python作排产计划_排产计划表
  15. 简单易懂的现代魔法-递归
  16. Day10【LeetCode每日一题】781. 森林中的兔子
  17. 卡尔曼滤波器的理解,C代码实现,和opencv里面KalmanFilter 的使用
  18. 【Windows11系统更新后蓝牙没了】
  19. 中国人寿保险单管理系统市场趋势报告、技术动态创新及市场预测
  20. 接收损伤和补偿(调制解调信号,QAM)

热门文章

  1. 华硕服务器系统都还原不了怎么办,华硕笔记本重装系统后dns解析失败怎么办
  2. 如何在python中获得当前时间前几天的日期
  3. 智能测试实践之路-UI缺陷检测
  4. 又一款数据分析神器:Polars 真的很强大
  5. 毛刺现象 java_记一次微服务耗时毛刺排查
  6. 3D游戏——AR图片识别与建模
  7. 杂记之罗翔语录:要爱具体的人,而不要爱抽象的人
  8. Jupyter 安装与应用
  9. 频繁出现域名无法解析该如何处理
  10. 总浮动时间(TF) 自由浮动时间(FF) 区别