发布于2021-08-28 19:58 阅读(1292) 评论(0) 点赞(13) 收藏(4)
最近新做一个项目,要在数据库初始化省市区三级数据,所以在网上找了个爬虫工具,从国家统计局区划代码网站爬取了相关数据。具体原理不解释了,只要能实现功能就OK。
<!--爬虫工具-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.2</version>
</dependency>
/**
* @作者 yangs
* @日期 2021/8/25
* @描述 中国省市区
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "area")
public class Area implements Serializable {
//主键,区划代码
@TableId(value = "id")
private String id;
//上级区划代码
@TableField(value = "parentId")
private String parentId;
//区域名称,如山东省
@TableField(value = "areaName")
private String areaName;
//区域等级,1代表省,2代表市,3代表区
@TableField(value = "level")
private Integer level;
}
package com.yckj.appauth.service.impl;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yckj.appauth.mapper.InitAreaMapper;
import com.yckj.appauth.service.InitAreaService;
import com.yckj.common.entity.Area;
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.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @作者 yangs
* @日期 2021/8/26
* @描述 初始化省市区数据
*/
@Service
public class InitAreaServiceImpl extends ServiceImpl<InitAreaMapper, Area> implements InitAreaService {
//这是DAO层
@Autowired
private InitAreaMapper initAreaMapper;
private static Map<Integer, String> cssMap = new HashMap<>();
static {
cssMap.put(1, "provincetr");// 省
cssMap.put(2, "citytr");// 市
cssMap.put(3, "countytr");// 县
//数据只需要统计省市区,所以把镇和村注释掉了。如果你需要镇和村,直接打开注释就行
/*cssMap.put(4, "towntr");// 镇
cssMap.put(5, "villagetr");// 村*/
}
/**
* @作者 yangs
* @日期 2021/8/26
* @描述 爬取数据直接存入数据库,这是方法入口,使用controller调用即可
*/
public void initArea() {
int level = 1;
// 获取全国各个省级信息
Document connect = connect("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2020/");
Elements rowProvince = connect.select("tr." + cssMap.get(level));
System.out.println("区划代码****上级代码****区域名称****区域等级");
// 遍历每一行的省份城市
for (Element provinceElement : rowProvince) {
Elements select = provinceElement.select("a");
// 每一个省份(如:山东省)
for (Element province : select) {
String strprovince = province.toString();
String areaName = strprovince.substring(strprovince.indexOf(".html\">") + 7, strprovince.indexOf("<br></a>"));
String areaCode = "";
switch (areaName) {
case "北京市":
areaCode = "110000";
break;
case "天津市":
areaCode = "120000";
break;
case "河北省":
areaCode = "130000";
break;
case "山西省":
areaCode = "140000";
break;
case "内蒙古自治区":
areaCode = "150000";
break;
case "辽宁省":
areaCode = "210000";
break;
case "吉林省":
areaCode = "220000";
break;
case "黑龙江省":
areaCode = "230000";
break;
case "上海市":
areaCode = "310000";
break;
case "江苏省":
areaCode = "320000";
break;
case "浙江省":
areaCode = "330000";
break;
case "安徽省":
areaCode = "340000";
break;
case "福建省":
areaCode = "350000";
break;
case "江西省":
areaCode = "360000";
break;
case "山东省":
areaCode = "370000";
break;
case "河南省":
areaCode = "410000";
break;
case "湖北省":
areaCode = "420000";
break;
case "湖南省":
areaCode = "430000";
break;
case "广东省":
areaCode = "440000";
break;
case "广西壮族自治区":
areaCode = "450000";
break;
case "海南省":
areaCode = "460000";
break;
case "重庆市":
areaCode = "500000";
break;
case "四川省":
areaCode = "510000";
break;
case "贵州省":
areaCode = "520000";
break;
case "云南省":
areaCode = "530000";
break;
case "西藏自治区":
areaCode = "540000";
break;
case "陕西省":
areaCode = "610000";
break;
case "甘肃省":
areaCode = "620000";
break;
case "青海省":
areaCode = "630000";
break;
case "宁夏回族自治区":
areaCode = "640000";
break;
case "新疆维吾尔自治区":
areaCode = "650000";
break;
}
//Area只有4个字段,ID代表区划代码,parentId代表上级区划代码,areaName代表区域名称,level代表区域等级
Area area = new Area();
area.setId(areaCode);
area.setParentId("root");
area.setAreaName(areaName);
area.setLevel(1);
//把省级数据入库
initAreaMapper.insert(area);
System.out.println(areaCode + "****root****" + areaName + "****" + 1);
parseNextLevel(areaCode, province, level + 1);
}
}
System.out.println("执行完毕");
}
/**
* @作者 yangs
* @日期 2021/8/26
* @描述 递归读取数据(根据业务需求,这里只读取到区级)
*/
private void parseNextLevel(String parentId, Element parentElement, int level) {
try {
Thread.sleep(500);//睡眠一下,否则可能出现各种错误状态码
} catch (InterruptedException e) {
e.printStackTrace();
}
Document doc = connect(parentElement.attr("abs:href"));
if (doc != null) {
Elements newsHeadlines = doc.select("tr." + cssMap.get(level));
// 获取表格的一行数据
for (Element element : newsHeadlines) {
printInfo(parentId, element, level + 1);
String code = element.select("td").first().text();
Elements select = element.select("a");// 在递归调用的时候,这里是判断是否是村一级的数据,村一级的数据没有a标签
if (select.size() != 0) {
parseNextLevel(code.substring(0, 6), select.last(), level + 1);
}
}
}
}
/**
* @作者 yangs
* @日期 2021/8/26
* @描述 打印市区并入库
*/
private void printInfo(String parentId, Element element, int level) {
String code = element.select("td").first().text();
Area area = new Area();
area.setId(code.substring(0, 6));
area.setParentId(parentId);
area.setAreaName(element.select("td").last().text());
area.setLevel(level - 1);
//把市和区数据入库
initAreaMapper.insert(area);
System.out.println(area.getId() + "****" + area.getParentId() + "****" + area.getAreaName() + "****" + (level - 1));
}
private static Document connect(String url) {
if (url == null || url.isEmpty()) {
throw new IllegalArgumentException("The input url('" + url + "') is invalid!");
}
try {
return Jsoup.connect(url).timeout(100 * 1000).get();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
感谢:本人是根据前辈的代码改写形成的,下面附上前辈博客链接:Jsoup获取全国地区数据(省市县镇村)。
原文链接:https://blog.csdn.net/YoungShuai1995/article/details/119924563
作者:哦哦好吧
链接:http://www.javaheidong.com/blog/article/276268/99a0a5b9adc6049dc6c0/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!