全国省市县三级地区数据库设计基于jsoup获取最新数据

一、引言

        为了实现地址选择等功能,经常需要获取详细地区信息,本文面向这一目标设计了数据库,并通过jsoup爬虫爬取最新数据。

二、数据库设计

        数据库结构,此处较为简单,就保存了每个区域的层级、名称及其上级区域的代码,以便查询层级关系。

-- ----------------------------
-- Table structure for district
-- ----------------------------
DROP TABLE IF EXISTS `district`;
CREATE TABLE `district`  (`_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',`region_name` varchar(50) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL COMMENT '地区名称',`region_short_name` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL COMMENT '地区简称',`region_code` varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL COMMENT '行政地区编号',`region_level` tinyint(3) UNSIGNED NOT NULL COMMENT '地区级别 1-省、自治区、直辖市 2-地级市、地区、自治州、盟 3-市辖区、县级市、县',`region_parent_id` int(10) UNSIGNED NOT NULL COMMENT '所属上级地区编号',PRIMARY KEY (`_id`) USING BTREE
);

三、获取数据并生成导入脚本

        在民政网站可以查询全国地区信息,地址:县以上行政区划代码

        可以发现数据具有极强的顺序性规律:所有地域都紧邻其上级地区之后,即所有市都在其所属省份之后而不穿插其他省份,所有县都在其所属市之后而不穿插其他市。这为我们之后的数据处理提供了极大的方便。

        爬取前,先通过F12查看网页结构,可以发现:省、市地区的class为xl722830,而县一级的class为xl732830,不能通过一个类名获取所有信息,因此本文采取的方法为遍历所有tr获取地区代码和名称。为将数据插入库中,同时输出了sql脚本。代码如下:

public class Districter {public static void main(String[] args) {try {//2020年12月中华人民共和国县以上行政区划代码网页Document doc = Jsoup.connect("http://www.mca.gov.cn/article/sj/xzqh/2020/20201201.html").get();Element eDiv = doc.getElementById("2020年12月份县以上行政区划代码_28320");Element tBody = eDiv.getElementsByTag("tbody").get(0);Elements trs = tBody.getElementsByTag("tr");// 以上为爬取部分,trs保存所有地域数据的行,// 处理trs获取地区代码和名称List codes = new ArrayList();List names = new ArrayList();for (int i = 3; i < trs.size()-9; i++) {    // 跳过不属于地区信息的trElements info = trs.get(i).getElementsByTag("td");String code = info.get(1).text().trim();String name = info.get(2).text().trim();codes.add(code);names.add(name);}// 判断数据正确性assert codes.size()== names.size():"地区代码与地区名称数目不相等!!";processDistricts(codes, names);} catch (IOException e) {e.printStackTrace();}}/*** 设置标记判断直辖市等特殊情况,一次遍历处理地区数据* @param codeList* @param nameList* @throws IOException*/private static void processDistricts(List codeList, List nameList) throws IOException {// 输出sql脚本String filePath="path/to/script";BufferedWriter writer = new BufferedWriter(new FileWriter(filePath));int num = codeList.size();// x、y分别保存i之前的省、市级地区的下标,即当前市县所属于的上级地区int x=0,y=0;// 标记一级地区(省、直辖市等)下是否有二级地区(市)boolean has2=false;String code;for (int i = 0; i < num; i++) {code=codeList.get(i);if (code.endsWith("0000")){System.out.println(codeList.get(i) +"\t"+nameList.get(i)+",1级");writer.write("insert into district(region_name,region_code,region_level,region_parent_id) values('"+nameList.get(i)+"','"+codeList.get(i)+"',1,'0');"+"\n");has2=false;x=i;}else if (code.endsWith("00")){System.out.println(codeList.get(i) + "\t" + nameList.get(i) + "\t" + "2级,属于" + nameList.get(x));writer.write("insert into district(region_name,region_code,region_level,region_parent_id) values('"+nameList.get(i)+"','"+codeList.get(i)+"',2,'"+codeList.get(x)+"');"+"\n");has2=true;y=i;}else {if (has2){System.out.println(codeList.get(i) + "\t" + nameList.get(i) + "\t" + "3级,属于:" + nameList.get(y));writer.write("insert into district(region_name,region_code,region_level,region_parent_id) values('"+nameList.get(i)+"','"+codeList.get(i)+"',3,'"+codeList.get(y)+"');"+"\n");}else {System.out.println(codeList.get(i) + "\t" + nameList.get(i) + "\t" + "3级,属于:" + nameList.get(x));writer.write("insert into district(region_name,region_code,region_level,region_parent_id) values('"+nameList.get(i)+"','"+codeList.get(i)+"',3,'"+codeList.get(x)+"');"+"\n");}}}writer.close();}}

四、使用

基本的SQL语句就好。

1.查看所有一级地区:

select * from district where region_parent_id='0';

2.查看北京市各下级地区:

select * from district where region_parent_id='110000';

3.搜索陕西省下属地区

select * from district where region_parent_id=(select region_code from district where region_name='陕西省');


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部