cn-division
v2025.0.1
Published
2025年中国行政区划数据,基于民政部最新数据
Downloads
116
Readme
cn-division
🇨🇳 中国行政区划数据 2025版 - 基于民政部2025年1月最新数据
特性
- ✅ 最新数据: 基于民政部2025年1月最新行政区划数据
- 🎯 精简优化: 数据体积小,支持tree-shaking,仅导入所需部分
- 📦 多种格式: 提供带编码和不带编码两种版本,满足不同场景需求
- 🛠 开箱即用: 直接支持antd Cascader组件,无需额外转换
- 🔍 地址解析: 内置地址解析功能,可从地址字符串提取省市区信息
- 💪 TypeScript: 完整的TypeScript类型定义
- 🚀 ESM: 纯ESM模块,支持现代构建工具
安装
npm install cn-division
# 或
pnpm add cn-division
# 或
yarn add cn-division版本说明
本项目采用特殊的版本号格式:年份.月份数据.修订版本号
- 年份:数据对应的年份(如 2025)
- 月份数据:数据更新的月份(0 表示年度整体数据,1-12 表示具体月份)
- 修订版本号:bug 修复和功能改进的递增版本号
示例:
2025.0.0- 2025年度数据,首次发布2025.1.0- 2025年1月数据更新2025.0.1- 2025年度数据的第一次修订
数据格式
带编码版本(/dist/code/)
- 省份代码:2位(如:11)
- 城市代码:4位(如:1101)
- 区县代码:6位(如:110101)
不带编码版本(/dist/no-code/)
- 纯名称数组和对象结构
- 适用于只需要显示名称的场景
文件体积
本包提供带编码和不带编码两种版本,可根据需要按需引入,有效控制包体积。
数据文件体积对照表
| 文件路径 | 大小 | 说明 |
|---------|------|------|
| 带编码版本 (dist/code/) | | |
| dist/code/pca.json | 105K | 省市区三级结构(含代码) |
| dist/code/counties.json | 126K | 区县数据(含代码) |
| dist/code/cities.json | 13K | 城市数据(含代码) |
| dist/code/pc.json | 11K | 省市二级结构(含代码) |
| dist/code/provinces.json | 833B | 省份数据(含代码) |
| 不带编码版本 (dist/no-code/) | | |
| dist/no-code/pca.json | 43K | 省市区三级结构(纯名称)⭐ |
| dist/no-code/counties.json | 36K | 区县数据(纯名称) |
| dist/no-code/cities.json | 4.6K | 城市数据(纯名称) |
| dist/no-code/pc.json | 5.9K | 省市二级结构(纯名称) |
| dist/no-code/provinces.json | 430B | 省份数据(纯名称) |
| 主文件 | | |
| index.js | 3.2K | Node.js 版本入口文件 |
| browser.js | 1.2K | 浏览器版本入口文件 |
| index.d.ts | 2.1K | TypeScript 类型定义 |
体积优化建议
完整功能场景 (推荐使用不带编码版本)
import { getAntdCascaderData } from 'cn-division'; // 导入: ~43K (pca.json)只需要代码 (使用带编码版本)
import { getAntdCascaderDataWithCode } from 'cn-division'; // 导入: ~105K (pca-code.json)按需引入 (最小化体积)
import { provinces, cities } from 'cn-division'; // 仅导入省份和城市: ~5K直接引入 JSON (tree-shaking 友好)
import pca from 'cn-division/dist/no-code/pca.json'; // 仅导入需要的 JSON: ~43K
快速开始
基础数据导入
import {
provinces, // 省份数据(带编码)
cities, // 城市数据(带编码)
areas, // 区县数据(带编码)
provincesNoCode,// 省份数据(纯名称)
citiesNoCode, // 城市数据(纯名称)
countiesNoCode, // 区县数据(纯名称)
pca, // 省市区三级结构(不带编码)
pc, // 省市二级结构(不带编码)
pcaCode, // 省市区三级结构(带编码)
pcCode // 省市二级结构(带编码)
} from 'cn-division';
console.log(provinces);
// [{ c: '11', n: '北京市' }, { c: '12', n: '天津市' }, ...]
console.log(provincesNoCode);
// ['北京市', '天津市', '河北省', ...]antd Cascader 组件
import { getAntdCascaderData, getAntdCascaderDataWithCode } from 'cn-division';
// 不带编码版本(适用于显示场景)
const cascaderData = getAntdCascaderData();
// [
// {
// label: '北京市',
// value: '北京市',
// children: [
// {
// label: '北京市',
// value: '北京市',
// children: [
// { label: '东城区', value: '东城区' }
// ]
// }
// ]
// }
// ]
// 带编码版本(适用于需要代码的场景)
const cascaderWithCode = await getAntdCascaderDataWithCode();
// [
// {
// label: '北京市',
// value: '11',
// code: '110000',
// children: [
// {
// label: '北京市',
// value: '1101',
// code: '110100',
// children: [
// { label: '东城区', value: '110101', code: '110101' }
// ]
// }
// ]
// }
// ]
// React中使用
import { Cascader } from 'antd';
function AddressSelector() {
const [options, setOptions] = useState([]);
useEffect(() => {
setOptions(getAntdCascaderData());
}, []);
return <Cascader options={options} placeholder="请选择地址" />;
}工具函数
import {
getProvinceByCode,
getCityByCode,
getCountyByCode,
getNameByCode,
parseAddress,
formatFullPath,
isMunicipalityCode,
getCitiesByProvince,
getCountiesByCity,
validateCode
} from 'cn-division';
// 根据代码获取信息
getProvinceByCode('110000'); // { c: '11', n: '北京市' }
getCityByCode('110100'); // { c: '1101', n: '北京市', p: '11' }
getCountyByCode('110101'); // { c: '110101', n: '东城区', cc: '1101' }
// 根据代码获取名称
getNameByCode('110000'); // '北京市'
getNameByCode('110101'); // '东城区'
// 格式化完整路径
formatFullPath('110101'); // '北京市 / 东城区'
formatFullPath('320505'); // '江苏省 / 苏州市 / 虎丘区'
// 地址解析
parseAddress('北京市朝阳区建国路88号');
// {
// province: '北京市',
// city: undefined,
// county: '朝阳区',
// rest: '建国路88号'
// }
parseAddress('广东省深圳市南山区科技园');
// {
// province: '广东省',
// city: '深圳市',
// county: '南山区',
// rest: '科技园'
// }
// 检查是否为直辖市
isMunicipalityCode('110000'); // true
isMunicipalityCode('320000'); // false
// 获取省份下的城市
getCitiesByProvince('32'); // 江苏省下的所有城市
// 获取城市下的区县
getCountiesByCity('3201'); // 南京市下的所有区县
// 验证代码格式
validateCode('110101'); // true
validateCode('123'); // falseAPI 参考
数据导出
| 导出名 | 类型 | 描述 |
|--------|------|------|
| provinces | Province[] | 省份数据(带编码) |
| cities | City[] | 城市数据(带编码) |
| counties | County[] | 区县数据(带编码) |
| provincesNoCode | string[] | 省份名称数组 |
| citiesNoCode | string[] | 城市名称数组 |
| countiesNoCode | string[] | 区县名称数组 |
| pca | PCAData | 省市区三级结构(不带编码) |
| pc | PCData | 省市二级结构(不带编码) |
| pcaCode | PCACodeData[] | 省市区三级结构(带编码) |
| pcCode | PCCodeData[] | 省市二级结构(带编码) |
函数导出
Cascader数据生成
// 同步获取Cascader数据(不带编码)
function getAntdCascaderData(): CascaderOption[]
// 异步获取Cascader数据(不带编码)
function getAntdCascaderDataAsync(): Promise<CascaderOption[]>
// 异步获取Cascader数据(带编码)
function getAntdCascaderDataWithCode(): Promise<CascaderWithCodeOption[]>
// 获取省市二级Cascader数据
function getAntdCascaderPC(): Promise<CascaderOption[]>
// 同步获取Cascader数据(别名)
function getCascaderDataSync(): CascaderOption[]查询函数
// 根据代码获取省份信息
function getProvinceByCode(code: string): Province | undefined
// 根据代码获取城市信息
function getCityByCode(code: string): City | undefined
// 根据代码获取区县信息
function getCountyByCode(code: string): County | undefined
// 根据代码获取名称
function getNameByCode(code: string): string | undefined
// 检查是否为直辖市代码
function isMunicipalityCode(code: string): boolean
// 获取省份下的所有城市
function getCitiesByProvince(provinceCode: string): City[]
// 获取城市下的所有区县
function getCountiesByCity(cityCode: string): County[]
// 验证代码格式
function validateCode(code: string): boolean工具函数
// 地址解析
function parseAddress(address: string): ParseResult | null
// 格式化完整路径
function formatFullPath(code: string): stringTypeScript 类型
interface Province {
c: string; // 省份代码(2位)
n: string; // 省份名称
}
interface City {
c: string; // 城市代码(4位)
n: string; // 城市名称
p: string; // 所属省份代码(2位)
}
interface County {
c: string; // 区县代码(6位)
n: string; // 区县名称
cc: string; // 所属城市代码(4位)
}
interface CascaderOption {
label: string;
value: string;
children?: CascaderOption[];
}
interface CascaderWithCodeOption {
label: string;
value: string;
code: string;
children?: CascaderWithCodeOption[];
}
interface ParseResult {
province?: string;
city?: string;
county?: string;
rest: string;
}常量
import { MUNICIPALITY_CODES, VERSION } from 'cn-division';
console.log(MUNICIPALITY_CODES); // ['11', '12', '31', '50']
console.log(VERSION); // '2025.0.0'数据更新
本项目支持从民政部官网自动抓取最新的行政区划数据。
更新命令
# 完整更新(抓取 + 构建)
npm run update
# 仅抓取数据(不构建)
npm run fetch
# 仅构建数据(使用已抓取的数据)
npm run build更新流程说明
1. 抓取数据 (npm run fetch)
从民政部官网抓取最新数据:
- 数据源: https://www.mca.gov.cn/mzsj/xzqh/2025/202401xzqh.html
- 自动解析: 自动识别 HTML 结构,提取省市区数据
- 特殊处理:
- 自动处理直辖市(北京、天津、上海、重庆)
- 自动添加省直辖县级市的虚拟城市
- 自动过滤台湾、香港、澳门数据
- 输出文件:
temp/raw-data.json(原始抓取数据)
npm run fetch执行后会看到类似输出:
开始从民政部获取2025年行政区划数据...
数据源: https://www.mca.gov.cn/mzsj/xzqh/2025/202401xzqh.html
正在获取HTML数据...
HTML数据获取成功,大小: 158234 字符
开始解析HTML数据...
解析完成: 省份 34 个, 城市 333 个, 区县 2845 个
处理直辖市数据...
数据验证完成
原始数据已保存到: temp/raw-data.json
=== 数据统计 ===
省份数量: 31
城市数量: 337
区县数量: 2846
总计: 32142. 构建数据 (npm run build)
将抓取的原始数据转换为多种格式:
- 输入文件:
temp/raw-data.json - 输出目录:
dist/code/- 带编码版本(含行政区划代码)dist/no-code/- 不带编码版本(纯名称)
- 生成文件:
provinces.json- 省份列表cities.json- 城市列表counties.json- 区县列表pca.json- 省市区三级结构pc.json- 省市二级结构
npm run build3. 完整更新 (npm run update)
相当于依次执行 npm run fetch 和 npm run build,完成从抓取到构建的完整流程。
npm run update自定义数据源
如果需要使用不同年份或版本的数据,可以修改 lib/fetch.js 中的 URL:
const CONFIG = {
url: 'https://www.mca.gov.cn/mzsj/xzqh/2025/202401xzqh.html',
// 修改为其他年份的 URL
};注意事项
- 网络连接: 数据抓取需要访问民政部官网,确保网络连接正常
- HTML 结构变化: 如果民政部网站 HTML 结构发生变化,可能需要更新解析逻辑
- 数据验证: 抓取后会自动验证数据完整性,如有异常会输出警告
- 备份数据: 更新前建议备份现有数据文件
数据说明
数据来源
- 官方来源: 中华人民共和国民政部
- 数据链接: https://www.mca.gov.cn/mzsj/xzqh/2025/202401xzqh.html
- 更新时间: 2025年1月
- 数据范围: 不包含台湾省、香港特别行政区、澳门特别行政区
与微信小程序的兼容性
本数据与微信小程序的 picker-region 组件数据基本一致,可直接用于替代或补充微信小程序的地区选择功能。
已知差异:
- 省直辖县级市显示名称:
- 本项目:显示为 "省直辖县级行政单位"
- 微信小程序:显示为 "省直辖县级行政区划"
- 说明:这是唯一已知的显示差异,不影响数据结构和功能使用。其余数据和微信小程序基本一致。如需与微信小程序完全一致,可以通过简单的字符串替换实现。
直辖市处理
对于北京市、天津市、上海市、重庆市四个直辖市:
- 省级和市级名称相同
- 避免了传统的"市辖区"显示问题
- 保持了数据结构的一致性
特殊映射处理
为确保数据完整性和用户体验,项目包含以下特殊映射:
1. 特殊城市区县映射
对于四个没有标准区县划分或缺少区县数据的地级市/地区,使用硬编码方式补充区县数据:
东莞市(441900)
- 补充36个街道镇:东城街道、南城街道、万江街道、莞城街道、石碣镇等
- 原因:东莞市作为地级市但不设县级区划,直接管辖街道和镇
中山市(442000)
- 补充23个街道镇:石岐街道、东区街道、中山港街道、西区街道等
- 原因:中山市作为地级市但不设县级区划,直接管辖街道和镇
儋州市(460400)
- 补充18个镇区:那大镇、和庆镇、南丰镇、大成镇等
- 原因:海南省儋州市升格为地级市后的特殊行政结构
大兴安岭地区(2327)
- 补充4个区:加格达奇区、松岭区、新林区、呼中区
- 原因:原始数据源中缺少这4个区的记录,需要手动补充
2. 重庆市虚拟城市映射
为解决重庆市部分县级单位(cityCode=500200)缺少上级城市的问题,创建虚拟城市映射:
虚拟城市"县"(500200)
- 归属:重庆市下级
- 包含12个县:城口县、丰都县、垫江县、忠县、云阳县、奉节县、巫山县、巫溪县、石柱土家族自治县、秀山土家族苗族自治县、酉阳土家族苗族自治县、彭水苗族土家族自治县
- 原因:这些县在原始数据中使用cityCode=500200,但缺少对应的城市记录,通过虚拟映射确保数据结构完整
通过这些特殊映射,确保了:
- 数据结构的完整性和一致性
- 用户界面显示的正确性
- 地址解析功能的准确性
数据统计
- 省份:31个
- 城市:337个
- 区县:2846个
- 总计:3214条记录
性能
经过性能测试,主要操作的执行时间:
- 生成Cascader数据1000次:~18ms
- 地址解析1000次:~12ms
- 数据体积经过优化,最小化存储空间
更新日志
2025.0.0
- 🎉 首次发布
- 📊 基于民政部2025年1月最新数据
- 🏗️ 完整的ESM模块结构
- 📝 TypeScript类型定义
- 🔧 工具函数库
- 🧪 完整的测试覆盖
许可证
MIT License
作者: kk 维护: 如有问题欢迎提交Issue
