2021全国省市区街道社区五级SQL文件以及爬取代码
最近项目当中要用到全国区域信息,需要包含到社区,在网上找了很久,大部分是没有到社区的,或者有的是2019年的数据。
考虑到数据的准确性,所以自己写了个爬取代码进行爬取。
数据来源
数据来源:国家统计局
爬取时间:2021/05/09。国家统计局最新的数据是2020/06月更新的。
数据说明
第一点:区域信息
是指的统计局划分的统计区域,基本是按照行政区域来进行划分了,所以会存在某些区域信息不存在的情况,(整体区域信息是完整的)
例如: 成都高新区,天府新区等等,大致的说法是高新区,天府新区是属于功能区不是行政区,高新区下面的街道/社区,从行政上来说还是属于武侯区,双流区等。部分APP上面是把高新区独立出来的,例如京东,在京东上可以发现成都桂溪街道属于高新区,但是在美团APP或者淘宝上,桂溪街道属于武侯区。
第二点:特殊地级市,省直辖县
特殊地级市:
1.绝大多数地级市的的党政机关主要领导干部的行政级别为厅局级正职,但有些地级市的行政架构为副省级建制,其党政机关主要领导干部行政级别为省部级副职,被称为“副省级城市”,共15个,分别为广州市、武汉市、哈尔滨市、沈阳市、成都市、南京市、西安市、长春市、济南市、杭州市、大连市、青岛市、深圳市、厦门市、宁波市。 [5]
2.绝大多数地级市设多个市辖区,并辖县级市、县、自治县等县级行政区,但有些地级市只设市辖区,不辖县级市、县、自治县等县级行政区,它们属于“全区市”,共13个,分别为乌海市、鄂州市、克拉玛依市、深圳市、厦门市、武汉市、珠海市、佛山市、南京市、广州市、海口市、三亚市、三沙市。而有些地级市虽辖县级市、县、自治县等县级行政区,但只设一个市辖区,它们属于“单区市”,共60个。还有些地级市既不设市辖区,也不辖县级市、县、自治县等县级行政区,直接管辖街道、镇、乡等乡级行政区,属于“不设区的市”,俗称“直筒子市”,共4个,分别为东莞市、中山市、嘉峪关市、儋州市。 [5]
省直辖县:
通常情况下县由归地级市管理,不过也存在很多县是省直接管理的。
SQL文档
文档地址:https://gitee.com/hjljy/crawler/tree/master/crawler/sql
代码说明
爬虫工具:jsoup
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
获取网页数据
第一种方式:
//避免生僻字乱码
Connection connect = HttpConnection.connect(sourceHtml);
connect.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51");
connect.cookie("_trs_uv", "ko2mem1r_6_2wb2");
connect.cookie("SF_cookie_1", "37059734");
connect.followRedirects(false);
BufferedInputStream inputStream = connect.execute().bodyStream();
//获取到网页数据,采用GBK编码的方式,避免乱码存在
Document document = Jsoup.parse(inputStream, "GBK", sourceHtml);
第二种方式:网页采用什么编码,这里就用什么编码,容易存在乱码
Document document = Jsoup.connect(sourceHtml)
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51")
.cookie("_trs_uv", "ko2mem1r_6_2wb2")
.followRedirects(false)
.get();
如何查看网页的编码格式
获取省份信息
public void getProvinceInfo(String sourceHtml, boolean next) throws IOException {
Document document = this.getDocument2(null, sourceHtml, 5);
int sort = 1;
//省份信息
Elements provincetr = document.getElementsByClass("provincetr");
for (Element element : provincetr) {
Elements aElements = element.getElementsByTag("a");
for (Element aElement : aElements) {
//省份名称
String provinceName = aElement.text();
String href = aElement.attr("href");
//省份行政区划代码 2位
String provinceCode = href.split("\\.")[0];
//省份行政区划代码 12位
String provinceRCode = provinceCode + "0000000000";
if (next) {
String absUrl = aElement.absUrl("href");
//获取城市信息
getCityInfo(provinceCode, provinceRCode, absUrl, next);
}
System.out.println(provinceName);
sort++;
}
}
}
获取城市信息
/**
* 获取省份下面的城市数据
*
* @param provinceCode 省份行政区划代码 2位
* @param provinceRCode 省份行政区划代码 12位
* @param sourceHtml 爬取网页
* @param next 是否获取下级
* @throws IOException
*/
public void getCityInfo(String provinceCode, String provinceRCode, String sourceHtml, boolean next) throws IOException {
Document document = this.getDocument2(null, sourceHtml, 5);
int sort = 1;
//城市信息
if (null == document) {
document = this.getDocument3(null, sourceHtml, 5);
}
Elements citytr = document.getElementsByClass("citytr");
if (citytr.size() == 0) {
document = this.getDocument3(null, sourceHtml, 5);
}
citytr = document.getElementsByClass("citytr");
if (citytr.size() == 0) {
log.error(sourceHtml + "未获取到城市信息");
}
for (Element element : citytr) {
Elements tds = element.getElementsByTag("td");
Element aElement = tds.get(0);
Element aElement2 = tds.get(1);
//城市12位区划代码
String cityRCode = aElement.text();
//城市名称
String cityName = aElement2.text();
//城市4位区划代码
String cityCode = "";
Element a = aElement.getElementsByTag("a").first();
if (a != null) {
String href = a.attr("href");
//城市4位区划代码
cityCode = href.split("\\.")[0].split("/")[1];
if (next) {
String absUrl = a.absUrl("href");
//获取区县数据
getCountyInfo(provinceCode, cityCode, cityRCode, absUrl, next);
}
}
System.out.println(cityName);
sort++;
}
}
获取区县信息
/**
* 获取城市下面的区、县数据
*
* @param provinceCode 省份行政区划代码 2位
* @param cityCode 城市行政区划代码 4位
* @param cityRCode 城市行政区划代码 12位
* @param sourceHtml 爬取网页
* @param next 是否获取下级
* @throws IOException
*/
public void getCountyInfo(String provinceCode, String cityCode, String cityRCode, String sourceHtml, boolean next) throws IOException {
Document document = this.getDocument2(null, sourceHtml, 5);
if (null == document) {
document = this.getDocument3(null, sourceHtml, 5);
}
//城市信息
Elements countytr = document.getElementsByClass("countytr");
if (countytr.size() == 0) {
document = this.getDocument3(null, sourceHtml, 5);
}
countytr = document.getElementsByClass("countytr");
if (countytr.size() == 0) {
log.error(sourceHtml + "未获取到区、县信息");
}
int sort = 1;
for (Element element : countytr) {
Elements tds = element.getElementsByTag("td");
Element aElement = tds.get(0);
Element aElement2 = tds.get(1);
//区/县12位区划代码
String countyRCode = aElement.text();
//区/县名称
String countyName = aElement2.text();
//区/县6位区划代码
String countyCode = "";
Element a = aElement.getElementsByTag("a").first();
if (a != null) {
String href = a.attr("href");
//区/县6位区划代码
countyCode = href.split("\\.")[0].split("/")[1];
if (next) {
String absUrl = a.absUrl("href");
getStreetInfo(provinceCode, cityCode, countyCode, countyRCode, absUrl, next);
}
}
System.out.println(countyName);
sort++;
}
}
获取街道、镇信息
/**
* 获取街道信息
*
* @param provinceCode 省份CODE
* @param cityCode 城市code
* @param countyCode 区县code
* @param countyRCode 区县完整code
* @param sourceHtml 街道信息html地址
* @param next 是否获取下级区划
* @throws IOException 异常
*/
public void getStreetInfo(String provinceCode, String cityCode, String countyCode, String countyRCode, String sourceHtml, boolean next) throws IOException {
Document document = this.getDocument2(null, sourceHtml, 5);
if (null == document) {
document = this.getDocument3(null, sourceHtml, 5);
}
int sort = 1;
//城市信息
Elements towntr = document.getElementsByClass("towntr");
if (towntr.size() == 0) {
document = this.getDocument3(null, sourceHtml, 5);
}
towntr = document.getElementsByClass("towntr");
if (towntr.size() == 0) {
log.error(sourceHtml + "未获取到街道信息");
}
for (Element element : towntr) {
Elements tds = element.getElementsByTag("td");
Element aElement = tds.get(0);
Element aElement2 = tds.get(1);
//街道/镇12位区划代码
String streetRCode = aElement.text();
//街道/镇名称
String streetName = aElement2.text();
//街道/镇8位区划代码
String streetCode = "";
Element a = aElement.getElementsByTag("a").first();
if (a != null) {
String href = a.attr("href");
//街道/镇8位区划代码
streetCode = href.split("\\.")[0].split("/")[1];
if (next) {
String absUrl = a.absUrl("href");
getCommitteeInfo(provinceCode, cityCode, countyCode, streetCode, streetRCode, absUrl, next);
}
}
System.out.println(streetName);
sort++;
}
}
获取社区,村庄信息
/**
* 获取社区、乡村信息
*
* @param provinceCode 省份CODE
* @param cityCode 城市code
* @param countyCode 区县code
* @param sourceHtml 街道信息html地址
* @param streetCode 街道code
* @param streetRCode 街道完整code
* @throws IOException
*/
public void getCommitteeInfo(String provinceCode, String cityCode, String countyCode, String streetCode, String streetRCode, String sourceHtml, boolean next) throws IOException {
Document document = this.getDocument2(null, sourceHtml, 5);
if (null == document) {
document = this.getDocument3(null, sourceHtml, 5);
}
//城市信息
Elements villagetr = document.getElementsByClass("villagetr");
if (villagetr.size() == 0) {
document = this.getDocument3(null, sourceHtml, 5);
}
villagetr = document.getElementsByClass("villagetr");
if (villagetr.size() == 0) {
log.error(sourceHtml + "未获取到社区信息");
}
int sort = 1;
for (Element element : villagetr) {
Elements tds = element.getElementsByTag("td");
Element aElement = tds.get(0);
Element aElement2 = tds.get(1);
Element aElement3 = tds.get(2);
//社区/乡12位区划代码
String committeeRCode = aElement.text();
//城乡分类代码
String type = aElement2.text();
//社区/乡名称
String committeeName = aElement3.text();
System.out.println(committeeName);
sort++;
}
}
完整代码地址
https://gitee.com/hjljy/crawler/tree/master/crawler
数据问题
1 爬取的数据基本上是没什么问题的,不过在使用上要考虑到层级的问题,因为在区划上面,国家为了方便,创建了少部分概念上的划分,例如:河南省下面的济源市,它的具体划分是:河南省-省直辖县级行政区划-济源市
2 社区和乡村的变化很大,基本上每年的主要变化就是社区和村庄。