目录

前言

一、天地图POI分类简介

1、数据表格

2、分类结构

二、从CSV导入到PG数据库

1、CSV解析流程

2、数据转换及入库

3、入库成果及检索

三、总结


前言

        在之前的博客中,曾经对高德地图和百度地图的POI分类以及使用PostGIS数据库来进行管理的模式进行了详细的介绍。之前的博文列表:

序号博客地址
1基于ApachePOI实现百度POI分类快速导入PostgreSQL数据库实战
2基于ApachePOI实现高德POI分类快速导入PostgreSQL数据库实战

        相信大家在平时的日常生活中,用的比较多的肯定是百度地图和高德地图。虽然天地图在移动端的使用市场没有前两者的份额多。但是作为官方的标准,天地图还是拥有自己得天独厚的优势,除了本身最具权威的地理数据,同时还有承载着官方标准的执行。因此天地图的POI数据也是非常重要的,因此可以作为我们日常数据分析和处理的一个可靠的信息来源。不同的平台对POI的分级分类都有所不同,相信看过上面两篇博文的朋友一定知道,不同的厂商,对于POI分类时,它的大类和小类的定义一定是不一样的。但是天地图POI的分类存在非常大的差异,层次结构也是不一样的。如下图:

         天地图的POI分类从大类来说就跟高德和百度不一样。单从一级大类的数量来说,百度拥有 32个,而高德只区分了25个,天地图居然有58个,在数量上天地图是比较多的(是否可以再精简和合并呢,需要讨论),比前两个加起来都多。另外从层级上来说,高德通常只区分了3级分类,而百度竟然有5级分类,然而天地图在层级上非常简单,只有2级展示,从扁平的角度来说,天地图的扁平化做的不错。

        那么本文即来重点讲讲天地图POI分类与高德POI分类以及百度POI分类存在什么不一样的地方,同时结合代码深入讲解使用Java标准库来读取天地图的POI 分类兵如何进行数据导入到PostGIS空间数据库中,也为各类基于 POI 分类数据的地理信息系统开发、商业智能分析以及城市规划应用等,铺设一条从数据获取到存储利用的高效路径,助力行业在空间数据赋能下实现精准决策与创新发展。

一、天地图POI分类简介

        本节将首先重点介绍天地图地图的POI分类信息,在之前的博客中我们设计了用于POI管理的物理表,这里可以继续用来存储天地图对应的POI分类信息。然后使用数据库脚本的方法对POI分类信息进行录入管理。对于天地图而言,其POI的分类较多,但是层级简单,因此这一节我们来详细的解读一下天地图的POI分类,让大家对分类信息有进一步的了解,为下一步对数据层级组装和批量解析入库打下牢固的基础。

1、数据表格

        与之前介绍的内容一样,大家可以从天地图的地图开放平台中获取其最新的POI分类的CSV表格(是的,你没有看错,官方提供的确实是CSV而不是Excel,如果需要使用Excel也可以将CSV转一下格式),这里我将从官网下载的类型截取一部分给大家参考。下载链接传送门:分类编码表。下面来看下官方在数据检索的相关介绍:

1.1.1输入参数说明

参数值参数说明参数类型是否必备备注(值域)
keyWord搜索的关键字String必填
specify指定行政区的国标码(行政区划编码表)严格按照行政区划编码表中的(名称,gb码)String必填下载行政区划编码表。9位国标码,如:北京:156110000或北京。
queryType服务查询类型参数String必填12:行政区划区域搜索服务。
start返回结果起始位(用于分页和缓存)默认0String必填0-300,表示返回结果的起始位置。
count返回的结果数量(用于分页和缓存)String必填1-300,返回结果的条数。
dataTypes数据分类(分类编码表)String可选下载分类编码表,参数可以分类名称或分类编码。多个分类用","隔开(英文逗号)。
show返回poi结果信息类别String可选取值为1,则返回基本poi信息; 取值为2,则返回详细poi信息

        这里不进行赘述,需要原始CSV表格的,可以去网站上下载。打开下载后的表格数据如下:

 

        从上面这张图可以看出天地图的POI分类确实分的比较简单。 同时也能看到一个比较明显的区别,与百度的POI分类不一样的是,天地图有编码的概念。同样的,基于天地图地图的POI检索可以从返回接口中看到其对应的POI分类值为:

{"eaddress": "","address": "荣滨南路东段11号附28附近","city": "","provinceCode": "156500000","cityCode": "","county": "荣昌区","typeName": "副食专卖店","source": "0","typeCode": "130207","lonlat": "105.590250,29.416870","countyCode": "156500153","ename": "","province": "重庆市","phone": "18716232760","poiType": "101","name": "李氏卤鹅","hotPointID": "50166082CE55CFF5"
}

        其中typeCode对应poi分类的类别编码,而typeName则表示具体的类别名称。

2、分类结构

        在了解了天地图的POI分类之后,下面我们基于之前设计的数据库物理表和分类信息构建树形的信息。因此需要对其分类采取细致的分类管理。在进行树形层次构建时,我们根据分类名称来进行统一管理:

         这个结构是天地图POI分类管理的基础,也是后面的数据程序解析的基础。我们将使用编码来进行数据的解析及入库。 在CSV中,很大的大类和种类都是重复的,因此需要在入库时将类别进行去重分类,最终构建一棵完整的POI分类树。 

二、从CSV导入到PG数据库

        本节将详细介绍在Java中使用标准库实现从CSV中解析到存储至PostgreGIS中,主要包含两个方面,第一个是如何使用Java标准库来进行CSV解析。第二个方面是如何基于Mybatis实现程序的批量入库。关于数据处理流程与高德和百度POI入库的流程一致,基本分为三个步骤:第一步是批量读取数据源,第二步是将数据源解析出POI分类数据,最后将分类好的数据导入到PG数据库中。

1、CSV解析流程

        首先还是对天地图下载的CSV格式的POI分类进行解析,在进行POI的分类进行构建时尤其重要,为了防止各层级在构建时出现重复的情况,这里采用LinkedHashMap集合来进行重复判断,在存储集合对象时,将分类编码作为map的key,而具体分类对象作为value。在天地图的POI分类编码中,可以发现将编码的前四位和后两位可以拆开,后两位如果是00的一般都是父类节点,通过我们的观察可以看到在后续的对象去重判断时,key就是重复的标记。为了实现从CSV格式的文件中读取数据,这里首先介绍一下CSV的解析流程。在正式讲解数据导入时,需要明确一个信息,就是在CSV数据的每一行中,只要遇到-这个字符就基本表示再往后读一个单元格,当前行的数据读取任务结束。

        第一步:一些不要的辅助信息,比如需要定义需要处理的文件本地路径地址。代码如下:

@Autowired
private IPoiCategoryService poiCateGoryService;
private static final String TDT_POI_CSV_FILE = "C:/Users/Administrator/Desktop/天地图及相关信息/天地图Type-数据分类(分类编码表).csv";
private static final String TRIGGER_CHAR = "-";

        第二步:CSV解析实现

        为了能够正确的解析CSV数据,这里需要额外定外定义两个参数,以此保证数据的准确解析。关于CSV的解析实现代码如下:

// 自定义CSV行解析(处理带逗号的字段)
private static String[] parseCsvLine(String line) {java.util.List<String> fields = new java.util.ArrayList<>();StringBuilder field = new StringBuilder();boolean inQuotes = false;for (char c : line.toCharArray()) {if (c == '"') {inQuotes = !inQuotes; // 切换引号状态} else if (c == ',' && !inQuotes) {fields.add(field.toString());field.setLength(0); // 重置} else {field.append(c);}}fields.add(field.toString()); // 添加最后一个字段return fields.toArray(new String[0]);
}// 清理单元格值
private static String cleanCellValue(String value) {// 去除首尾空格和引号value = value.trim();if (value.startsWith("\"") && value.endsWith("\"")) {value = value.substring(1, value.length() - 1);}// 处理转义的双引号return value.replace("\"\"", "\"");
}

        第三步:CSV数据解析,实现最基本的数据解析读取和基础配置之后,下面就可以来实现对CSV数据的具体读取,这里采取的是直接的Java标准库解析的方法。实例代码如下:

private static LinkedHashMap<String,PoiCategory> csv2Map(){// UTF-8, GBK, GB2312, ISO-8859-1, Windows-1252Charset charset = Charset.forName("GBK"); // 根据实际文件编码设置LinkedHashMap<String,PoiCategory> amapPoiTypeMap = new LinkedHashMap<String, PoiCategory>(); try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(TDT_POI_CSV_FILE), charset))) {String line = "";int rowNum = 0;while ((line = br.readLine()) != null) {rowNum++;String[] cells = parseCsvLine(line); // 使用自定义解析方法处理带逗号的字段boolean foundTrigger = false;List<String> poiCategories = new ArrayList<String>();String poiCategoryCode = "";//获取每一行的的每个格子的数据for (int i = 0; i < cells.length; i++) {String cellValue = cleanCellValue(cells[i]);//System.out.println(cellValue);if (cellValue.contains(TRIGGER_CHAR)) {foundTrigger = true;//System.out.println("[行 " + rowNum + "] 触发单元格: " + cellValue);if (i + 1 < cells.length) {String nextValue = cleanCellValue(cells[i + 1]);poiCategoryCode = nextValue;//System.out.println("→ 终止单元格: " + nextValue);} else {System.out.println("→ 终止单元格: (空)");}break;}else {poiCategories.add(cellValue);}}if (!foundTrigger) {System.out.println("行 " + rowNum + ": 未找到触发字符");}//执行分类预处理if(foundTrigger) {String prefix_head = poiCategoryCode.substring(0,4);String prefix_tail = poiCategoryCode.substring(4);if(prefix_tail.equalsIgnoreCase("00")) {//00表示大类String levelFirst = poiCategoryCode;//处理一级,添加到集合中if(!amapPoiTypeMap.containsKey(levelFirst)) {PoiCategory category = new PoiCategory(IdWorker.getId(),1944421516292726785L,"0,100,1944421516292726785",String.join("/", poiCategories),StringUtils.EMPTY,levelFirst);amapPoiTypeMap.put(levelFirst, category);}}else {//剩下表示小类if(!amapPoiTypeMap.containsKey(poiCategoryCode)) {String _parentKey = prefix_head + "00";PoiCategory parentCategory = amapPoiTypeMap.get(_parentKey);String ancestors = parentCategory.getAncestors() + "," + parentCategory.getPkId();PoiCategory category = new PoiCategory(IdWorker.getId(),parentCategory.getPkId(),ancestors,String.join("/", poiCategories),StringUtils.EMPTY,poiCategoryCode);amapPoiTypeMap.put(poiCategoryCode, category);}}}}} catch (IOException e) {e.printStackTrace();}return amapPoiTypeMap;
}

2、数据转换及入库

        将CSV数据成功的解析转换成LinkedHashMap之后,事情还远远没结束,接下来需要将获取的LinkedHashMap转换成ArrayList。为了在查询数据的时候方便,在正式入库之前还需要增加一家额外的辅助信息,信息如下:

/**
* - 将map集合转换成list集合
* @param amapPoiTypeMap
* @return
*/
private static List<PoiCategory> convertMap2DataList(LinkedHashMap<String,PoiCategory> amapPoiTypeMap) {List<PoiCategory> categoryData = new ArrayList<PoiCategory>();Date now = DateUtils.getNowDate();for (PoiCategory value : amapPoiTypeMap.values()) {value.setPlatform("tianditu");value.setDelFlag(0);value.setStatus(0);value.setOrderNum(1);value.setCreateTime(now);categoryData.add(value);}return categoryData;
}

        到这里,我们就已经实现了如何使用Java标准库来解析CSV文件,并且将数据都读到了LinkedHashMap对象中,接下来就调用上述的方法来组装成一个完整的数据导入实例,核心代码如下:

@Test
public void writer2DB() {//step1、读取CSV到Map集合中LinkedHashMap<String,PoiCategory> map = csv2Map();//step2、将map转成list集合List<PoiCategory> categoryData = convertMap2DataList(map);//step3、插入到数据库中for (PoiCategory poiCategory : categoryData) {System.out.println(poiCategory);}//step4、数据入库 poiCateGoryService.batchInsertPoiCategory(categoryData);System.out.println("finished...");
}

3、入库成果及检索

        完成以上的程序编写,并运行操作后就完成了天地图POI分类数据的PostGIS数据库导入操作,程序执行完成后,可以在控制台看到以下输出:

        为了验证是否在数据库中是否也保存了这些数据,可以使用以下SQL语句进行查询: 

select * from biz_poi_category t where platform = 'tianditu';

          在客户端软件中执行以上SQL后可以看到以下结果:

三、总结

        以上就是本文的主要内容,支持对天地图的POI分类的CSV入库及检索就基本完成,后续我们将深入使用POI信息以及如何进行相应数据的采集。那么本文即来重点讲讲天地图POI分类与高德和百度POI分类存在什么不一样的地方,需要注意的是,本文读取的文件不是Excel而是CSV格式,因此也深入讲解了如何使用Java标准库来解析天地图的POI分类文件,同时深入讲解天地图 POI 分类如何进行数据导入,如何将CSV数据转为LinkedHashMap,再到ArrayList,最后批量入库。也为各类基于 POI 分类数据的地理信息系统开发、商业智能分析以及城市规划应用等,铺设一条从数据获取到存储利用的高效路径,助力行业在空间数据赋能下实现精准决策与创新发展。行文仓促,难免有许多不足之处,如有不足,在此恳请各位专家博主在评论区不吝留言指出,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91845.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91845.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/91845.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人-AI交互中的信息论不同于传统的信息论,其信息的增量≠不确定性的减量

在人机交互&#xff08;Human-AI Interaction, HAI&#xff09;领域&#xff0c;信息论的应用确实与传统的信息论有所不同。这种差异主要源于人机交互HAI中信息的复杂性、动态性以及人类认知的特点。1. 传统信息论的核心概念传统信息论由克劳德香农&#xff08;Claude Shannon&…

K8s 通过 Scheduler Extender 实现自定义调度逻辑

1. 为什么需要自定义调度逻辑 什么是所谓的调度? 所谓调度就是指给 Pod 对象的 spec.nodeName 赋值 待调度对象则是所有 spec.nodeName 为空的 Pod 调度过程则是从集群现有的 Node 中为当前 Pod 选择一个最合适的 实际上 Pod 上还有一个平时比较少关注的属性&#xff1a;…

7.19 换根dp | vpp |滑窗

lcr147.最小栈通过两个栈 维护实现class MinStack { public:stack<int> A, B;MinStack() {}void push(int x) {A.push(x);if(B.empty() || B.top() > x)B.push(x);}void pop() {if(A.top() B.top())B.pop();A.pop();}int top() {return A.top();}int getMin() {retur…

以太坊的心脏与大脑:详解执行客户端(EL)与共识客户端(CL)

好的&#xff0c;各位技术同道&#xff0c;欢迎再次光临我的博客。在上一篇文章中&#xff0c;我们聊了如何搭建一个以太坊测试节点&#xff0c;并提到了节点需要同时运行“执行客户端”和“共识客户端”。很多朋友对此表示了浓厚兴趣&#xff0c;想深入了解这两者究竟是什么&a…

Debian-10,用glibc二进制预编译包,安装Mysql-5.7.44 笔记250716

Debian-10,用glibc二进制预编译包,安装Mysql-5.7.44 笔记250716 &#x1f4e6; 一步脚本 #!/bin/bash### 安装依赖 apt install -y libaio1 libnuma1 libncurses5### 下载MySQL-5.7.44 的 glib二进制包: mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz ,(如果不存在) mkdir…

用逻辑回归(Logistic Regression)处理鸢尾花(iris)数据集

# 导入必要的库 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from…

华大北斗TAU1201-1216A00高精度双频GNSS定位模块 自动驾驶专用

在万物互联的时代&#xff0c;您还在为定位不准、信号丢失而烦恼吗&#xff1f;TAU1201-1216A00华大北斗高精度定位模块TAU1201是一款高性能的双频GNSS定位模块&#xff0c;搭载了华大北斗的CYNOSURE III GNSS SoC 芯片&#xff0c;该模块支持新一代北斗三号信号体制&#xff0…

坚持继续布局32位MCU,进一步完善产品阵容,96Mhz主频CW32L012新品发布!

在全球MCU市场竞争加剧、国产替代加速的背景下&#xff0c;嵌入式设备对核心控制芯片的性能、功耗、可靠性及性价比提出了前所未有的严苛需求。为适应市场竞争&#xff0c;2025年7月16日&#xff0c;武汉芯源半导体正式推出基于CW32L01x系列低功耗微控制器家族的全新成员&#…

用线性代数推导码分多址(CDMA)

什么是码分多址 码分多址&#xff1a;CDMA允许多个用户同时、在同一频率上传输数据。它通过给每个用户分配唯一的、相互正交的二进制序列来实现区分。用户的数据比特被这个码片序列扩展成一个高速率的信号&#xff0c;然后在接收端通过相同的码片序列进行相关运算来回复原数据 …

mac 配置svn

1.查看brew的版本&#xff1a;brew install subversion2.安装brew命令&#xff1a;bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"3.把路径添加到path环境变量&#xff1a;echo export PATH"/opt/homebrew/b…

使用 .NET Core 的原始 WebSocket

在 Web 开发中&#xff0c;后端存在一些值得注意的通信协议&#xff0c;用于将更改通知给已连接的客户端。所有这些协议都用于处理同一件事。但鲜为人知的协议很少&#xff0c;鲜为人知的协议也很少。今天&#xff0c;将讨论 WebSocket&#xff0c;它在开发中使用最少&#xff…

编程实现Word自动排版:从理论到实践的全面指南

在现代办公环境中&#xff0c;文档排版是一项常见但耗时的工作。特别是对于需要处理大量文档的专业人士来说&#xff0c;手动排版不仅费时费力&#xff0c;还容易出现不一致的问题。本文将深入探讨如何通过编程方式实现Word文档的自动排版&#xff0c;从理论基础到实际应用&…

力扣经典算法篇-25-删除链表的倒数第 N 个结点(计算链表的长度,利用栈先进后出特性,双指针法)

1、题干 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a;输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[] 示例 3&…

VIT速览

当我们取到一张图片&#xff0c;我们会把它划分为一个个patch&#xff0c;如上图把一张图片划分为了9个patch&#xff0c;然后通过一个embedding把他们转换成一个个token&#xff0c;每个patch对应一个token&#xff0c;然后在输入到transformer encoder之前还要经过一个class …

【服务器与部署 14】消息队列部署:RabbitMQ、Kafka生产环境搭建指南

【服务器与部署 14】消息队列部署&#xff1a;RabbitMQ、Kafka生产环境搭建指南 关键词&#xff1a;消息队列、RabbitMQ集群、Kafka集群、消息中间件、异步通信、微服务架构、高可用部署、消息持久化、生产环境配置、分布式系统 摘要&#xff1a;本文从实际业务场景出发&#x…

LeetCode中等题--167.两数之和II-输入有序数组

1. 题目 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < index1 < index2 <…

【C# in .NET】19. 探秘抽象类:具体实现与抽象契约的桥梁

探秘抽象类:具体实现与抽象契约的桥梁 在.NET类型系统中,抽象类是连接具体实现与抽象契约的关键桥梁,它既具备普通类的状态承载能力,又拥有类似接口的行为约束特性。本文将从 IL 代码结构、CLR 类型加载机制、方法调度逻辑三个维度,全面揭示抽象类的底层工作原理,通过与…

Apache RocketMQ + “太乙” = 开源贡献新体验

Apache RocketMQ 是 Apache 基金会托管的顶级项目&#xff0c;自 2012 年诞生于阿里巴巴&#xff0c;服务于淘宝等核心交易系统&#xff0c;历经多次双十一万亿级数据洪峰稳定性验证&#xff0c;至今已有十余年发展历程。RocketMQ 致力于构建低延迟、高并发、高可用、高可靠的分…

永磁同步电机控制算法--弱磁控制(变交轴CCR-VQV)

一、原理介绍CCR-FQV弱磁控制不能较好的利用逆变器的直流侧电压&#xff0c;造成电机的调速范围窄、效率低和带载能力差。为了解决CCR-FQV弱磁控制存在的缺陷&#xff0c;可以在电机运行过程中根据工况的不同实时的改变交轴电压给定uq的值&#xff0c;实施 CCR-VQV弱磁控制。…

达梦数据守护集群搭建(1主1实时备库1同步备库1异步备库)

目录 1 环境信息 1.1 目录信息 1.2 其他环境信息 2 环境准备 2.1 新建dmdba用户 2.2 关闭防火墙 2.3 关闭Selinux 2.4 关闭numa和透明大页 2.5 修改文件打开最大数 2.6 修改磁盘调度 2.7 修改cpufreq模式 2.8 信号量修改 2.9 修改sysctl.conf 2.10 修改 /etc/sy…