关于 Morocco communes
Morocco communes 是摩洛哥行政区划数据集、HTTP API 和网站,面向需要行政代码、人口普查数据及边界信息的开发者与分析人员。它提供多种层级的可下载数据、查询接口和只读 MCP 工具。
主要功能
- 01HCP 行政代码与法语、阿拉伯语名称
- 022014 与 2024 年人口普查指标
- 03OpenStreetMap 边界与邻接信息
- 04JSON 和 CSV 数据文件
- 05静态、别名及计算型 API
适用场景
- 01按名称或代码查找行政单位
- 02比较两次人口普查数据
- 03查询附近的市镇及边界邻接关系
- 04通过 MCP 获取市镇指标
MCP 相关
`/mcp` 提供 13 个只读工具,可搜索和查询行政单位、人口普查指标、经济、住房、村落及邻近位置。MCP 客户端可直接访问该数据。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://communes.pages.dev/mcpclaude mcp add --transport http zkousama-morocco-communes https://communes.pages.dev/mcp{"mcpServers":{"zkousama-morocco-communes":{"type":"http","url":"https://communes.pages.dev/mcp"}}}在 Cursor 中打开{"servers":{"zkousama-morocco-communes":{"type":"http","url":"https://communes.pages.dev/mcp"}}}在 VS Code 中打开{"mcpServers":{"zkousama-morocco-communes":{"type":"http","url":"https://communes.pages.dev/mcp"}}}{"mcpServers":{"zkousama-morocco-communes":{"serverUrl":"https://communes.pages.dev/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
12| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | integer | 否 | 结果数量。省略时为 10,最多为 50。 |
| query | string | 是 | 要查找的名称,可使用法语、阿拉伯语、slug 或行政单位代码。 |
| levels | array | 否 | 仅限这些级别。省略时包含所有级别。 |
详细介绍
摩洛哥市镇
一个开放数据集和 HTTP API,涵盖摩洛哥的行政区划:12 个大区、75 个省和专区、8 个城区专区、213 个区、1,503 个市镇和 41 个城区,包含 HCP 官方地理代码、法语和阿拉伯语名称、2024 年和 2014 年人口、HCP 两年人口普查中的年龄、教育、语言、工作和住房数据、2024 年经济机构数量、农村市镇的 douar,以及来自 OpenStreetMap 的边界。
HCP 以电子表格形式发布人口普查数据。本项目基于这些数据和 OpenStreetMap 构建数据集、API 和网站,并展示整个处理过程。
数据集
data/v1/ 已提交并进行版本管理,因此你完全可以在不使用 API 的情况下使用它。CHANGELOG.md 说明了每个版本新增的内容;构建过程会拒绝缺少对应条目的版本。
| 目录 | 内容 | 许可 |
|---|---|---|
attributes/ | 每个行政区划单元,JSON 和 CSV 格式 | HCP,遵循 CC BY 4.0 条款 |
geometry/ | 每个大区一个 TopoJSON 文件,以及市镇之间的邻接关系 | ODbL,相同方式共享 |
indicators/ | 每个行政区划单元的 2024 年和 2014 年人口普查指标,JSON 和 CSV 格式 | HCP,遵循 CC BY 4.0 条款 |
economy/ | 每个行政区划单元 2024 年的经济机构数量,JSON 和 CSV 格式 | HCP,遵循 CC BY 4.0 条款 |
housing/ | 2024 年城市住房存量,按住宅单元统计,JSON 和 CSV 格式 | HCP,遵循 CC BY 4.0 条款 |
douars/ | 2024 年农村市镇的 33,189 个 douar,按其分区归属统计,JSON 和 CSV 格式 | HCP,遵循 CC BY 4.0 条款 |
crosswalk/ | 2014 ↔ 2024 年的对应关系 | HCP,遵循 CC BY 4.0 条款 |
insights/ | 每个市镇在 2024 年较为突出的数据,附上邻近市镇数据和各自的 2014 年数据,JSON 格式 | 本仓库自行整理的文字;数据来自 HCP,遵循 CC BY 4.0 条款 |
sources.json | 每个来源的摘要、许可和版本信息 |
不同目录适用不同许可,geometry/ 附有自己的 LICENSE。每个市镇的五个字段(centroid、bbox、osm、areaKm2 和 density)来自 OpenStreetMap,同样遵循 ODbL;provenance.geometry 会标记这些字段。每个层级都有 CSV 文件,可在 Excel 中正常打开,包括阿拉伯语内容。
运行 pnpm dataset:build 即可重建数据集。使用同一缓存时,输出的字节内容完全一致。
pnpm build 还会根据上述 TopoJSON 将边界写入 GeoJSON:包括每个市镇的边界,以及根据市镇勾勒出的每个省和大区的边界。这些文件会与其一同提供,而不会提交到仓库。
API
分为三个层级,响应由哪个层级提供,可查看其 X-Api-Tier 标头。
预渲染。 构建时写入的 12,723 个文件,直接由 Cloudflare Pages 提供,无需运行任何代码。免费且不限量。
GET /api/regions.json GET /api/regions/01.json
GET /api/regions/01/provinces.json GET /api/regions/01/communes/page/1.json
GET /api/provinces/01.511.json GET /api/provinces/01.511/cercles.json
GET /api/cercles/01.511.05.json GET /api/communes/01.511.01.0.json
GET /api/communes/page/1.json GET /api/communes/type/urban/page/1.json
GET /api/communes/01.511.01.0/arrondissements.json
GET /api/communes/09.581.01.07/neighbours.json
GET /api/communes/01.511.01.0/indicators.json
GET /api/communes/09.581.01.07/economy.json
GET /api/communes/09.163.07.17/douars.json
GET /api/communes/01.511.01.0/neighbourhoods.json
GET /api/arrondissements/01.511.01.05.json GET /api/indicators.json
GET /api/economy.json GET /api/version.json
GET /data/v1/**
别名。 查询字符串和无扩展名的路径形式。按路径键控的资源存储无法匹配查询字符串,因此 Worker 会将这些请求解析到已包含答案的文件,并在 Content-Location 中标明该文件:
GET /api/communes?province=01.511&page=1 GET /api/communes?type=urban
GET /api/communes/tanger GET /api/communes/001511010
GET /api/communes/tanger/indicators GET /api/communes/tiznit/economy
计算生成。 没有文件保存的答案:
GET /api/search?q=tanger&levels=commune&limit=10
GET /api/douars/search?q=tachdirt
GET /api/communes/near?lat=33.5731&lng=-7.5898&radius=15
GET /api/communes/at?lat=35.786&lng=-5.8125
GET /api/communes?province=01.511&type=urban
GET /api/communes?sort=-population&min_population=100000
GET /api/communes?region=01&sort=-labour.unemploymentRate
GET /api/communes?sort=-economy.establishments.jobs
列表可按任一人口普查指标或路径排序,其中列出的每个市镇都会带上用于排序的数值。路径前加上 2014. 可按 2014 年数值排序,加上 change. 可按市镇在两次人口普查间的变动幅度排序。企业数量使用 economy.。
搜索支持法语、阿拉伯语、slug 或代码。它会统一名称中实际使用的各种字母形式:alef、ta-marbuta 和 alef maqsura,也会去除名称中不会出现、但用户输入时可能会带上的 tatweel 和元音符号。它会根据辅音匹配拼写不同的名称,因此 titwan 可以找到 Tétouan,jdida 可以找到 El Jadida。01.511.01.0、001511010、1511010 和 tanger 都指向同一个市镇;另有 18 个外名是手动列出的,因为无论如何统一字符,都无法将 Fez 转换为 Fès,或将 Port Lyautey 转换为 Kénitra。街区名称可找到其所在的市镇或区,5 位数邮政编码也可以。douar 可单独搜索,支持阿拉伯字母或拉丁字母:tachdirt 和 tashdirt 都能找到 تشديرت。
统计内容。 别名和计算生成路由以及 MCP 服务会在 Workers Analytics Engine 中统计自身使用情况:去除代码后的路由,或 MCP 消息调用工具时的工具名称,否则记录其方法;MCP 客户端提供的名称、User-Agent 的第一个词、国家、状态和耗时。预渲染文件不运行代码,因此不会被统计。pnpm stats 可读取这些数据,以及 npm、PyPI 和 GitHub 的数据。
第二个存储在 D1 中,统计 5 类记录:一次搜索、打开的地点、助手调用的工具、MCP 客户端提供的名称,以及下载的文件。通过 MCP 服务连接的助手会按其提供的名称统计,每个调用的工具则按工具名称和所查询的地点统计。每条记录包含一天的数据和少量类别信息,不包含可将其与其他记录关联的密钥、Cookie 或地址。pnpm demand 可读取这些数据;网站的 /docs/privacy/ 页面会准确说明保留了哪些数据。
pnpm deploy:live 会启用该功能。它会将迁移应用到生产数据库,使用从该数据库读取的最常查询页面构建网站,然后部署网站,接着部署每晚汇总数据的 Worker。直接运行 pnpm build 不会查询数据库,并会将该页面留空。写入失败会被忽略,因此首次部署一天后运行 pnpm demand,即可查看是否已有记录写入。
每个响应都包含 data、meta 和 links。错误采用 RFC 9457 问题详情文档格式;格式正确但指向不存在对象的代码返回 404,而无法搜索的内容返回 400。CORS 已开放。
完整参考文档:api/README.md。
面向程序和 Agent
/api/openapi.json:对每个路由的 OpenAPI 3.1 描述,由与 Worker 读取限制所用的同一模块生成,因此其中声明的默认值和范围就是实际执行的规则。大多数 Agent 框架都能直接将其转换为工具。/llms.txt:以 llmstxt.org 格式编写的 API 和数据集简要概览,供读取网站的大模型使用。/mcp:提供 13 个只读工具的 MCP 服务(search、get_commune、get_unit、communes_near、commune_at、list_communes、get_indicators、get_economy、get_housing、get_insights、get_neighbourhoods、get_douars、search_douars),Claude、Claude Code 和其他 MCP 客户端可直接查询数据,包括人口普查数据。网站的/docs/mcp/页面提供了各客户端的配置说明。
在表单中或离线使用
/components/commune-picker.js:一个自定义元素,可从静态文件填充省、大区和市镇<select>,使表单提交市镇的 HCP 代码。该元素通过开放 CORS 提供服务,/docs/components/中还有一个 React 版本。morocco-communes:以 npm 包形式提供的数据集,位于packages/morocco-communes/。代码、名称、上级单位和人口数据按级别分别作为 ES 模块提供,并包含类型定义,不含 OpenStreetMap 字段,因此不附带 ODbL 条款。pnpm npm:build从data/v1构建该包,包版本号与数据集版本号相同。- PyPI 上的
morocco-communes:面向分析人员的同一数据集,位于packages/morocco-communes-py/。行政区划单位、两次人口普查、各类机构和交叉对照表均以 pandas DataFrame 形式提供;设置as_frame=False时则返回字典列表,无需标准库以外的任何依赖。pnpm py:build从data/v1构建其数据并进行 gzip 压缩,包版本号也与数据集版本号相同。
文档站点
site/ 是一个 Astro 站点,支持英语、法语和阿拉伯语,提供浅色和深色主题,并可选择其中一种主题或跟随系统设置。它会构建为静态 HTML:主页、重点数据页面、对比页面、douar 页面、11 个文档页面(API 参考、MCP 设置、组件、npm 包、Python 包、下载、人口普查数据、术语表、重点数据的选取方式、douar 的命名方式,以及站点统计的内容),以及每个大区、省和市镇各自的页面,共 4,845 个页面。
主页打开后显示所有市镇的地图,并按人口密度、2014 年以来的人口变化,或城乡属性着色。悬停在某个市镇上会显示其数据,点击则打开其页面。市镇页面包含该市镇的数据和排名、省级地图、与之接壤的市镇、其人口变化在所有市镇中的位置,以及人口普查数据:男女年龄金字塔、与女性及全国数据并列的主要比率,以及当地居民使用的语言。 所有市镇的列表支持边输入边筛选,语言可选法语或阿拉伯语。
其中的 JavaScript 负责地图悬停和切换、列表筛选、交互演示区(一个 Solid island,会查询与其一同部署的任意 API,并显示每个响应中的 X-Api-Tier)、组件页面上的选择器,以及复制按钮。
站点中所有描述数据或 API 的内容,均由 site/scripts/ 下的脚本在构建时生成:
-
map.ts根据 API 提供的 TopoJSON 绘制主页地图。每条共用边界都是一段弧线,并针对相邻的两个市镇共同简化一次,因此填充区域衔接时不会留下细缝。两种主题下的颜色都经过对比度和色盲区分度检查。 -
hierarchy.ts构建代码层级,形成从大区到区的真实层级链。 -
charts.ts计算各大区的人口变化、市镇规模分布、一半人口居住的土地面积有多小、人口减少的市镇数量,以及 207 个通过代码交叉映射的市镇与 1,286 个代码从未改变的市镇之间的人口增长分布。最后一项是对账过程的自检:两种分布几乎完全重合。 -
downloads.ts列出data/v1下的文件及其实际大小,如果文件不存在则构建失败。 -
reference.ts根据buildOpenApi构建 API 参考,其中的每个示例都来自实际生成的文件或 Worker 自带的函数;它还会通过连接到服务的客户端列出 MCP 工具。法语和阿拉伯语页面会读取规范中每一行的译文,如果有缺失或多余的译文,构建就会失败。
大区、省和市镇页面由 site/src/lib/places.ts 构建,该脚本每次构建都会读取一次 data/v1:生成排名、根据共用边界点匹配的相邻市镇,以及按与主页地图相同的方式绘制的小地图。
图表采用内嵌 SVG 和 CSS,因此无需 JavaScript,也无需图表库。
阿拉伯语页面位于 /ar/ 下,采用从右向左的阅读方向。页面会优先显示各行政单位的阿拉伯语名称,并在旁边标注 HCP 的拉丁字母拼写;数字格式则遵循摩洛哥阿拉伯语习惯,例如 1.503 和 12,8%。site/src/i18n/fields.ts 中为每个人口普查字段提供了阿拉伯语名称,采用 HCP 自己的术语,并像英语页面一样保留其法语表述。带刻度的图表、直方图和对比条带保持从左向右;列表、条形图和页面其余部分则改为从右向左。
站点采用静态形式,因为其中没有任何内容需要服务器,因此手写的 Worker 是唯一的 Worker,页面托管也无需花费。
见解
一个公社页面最多可展示 3 项在 2024 年格外突出的数据:该公社在某项数据上位居最高或最低、与其他公社相比自 2014 年以来变化大得多或小得多,或与所在省份的差距很大。每项数据旁边还会显示接壤公社的中位数、与该公社差距最大的邻居,以及在两次人口普查数据可比较时,该公社的 2014 年数据和摩洛哥整体的变化情况。可能存在错误的数据、两次人口普查结果不一致的公社数据,以及男性和女性的占比均不予展示。
pnpm insights 会从 data/v1/ 计算所有结果,并写入 data/v1/insights/,无需模型,也不会调用网络。API 会在 /api/communes/{code}/insights.json 提供相同的文件,MCP 服务的 get_insights 会将其提供给助手。方法页面介绍了如何选取数据,insights/pilot/ 则记录了一项早期设计研究,当时曾请语言模型说明原因。
Douar
HCP 发布了细至 douar 级别的 2024 年人口普查数据;douar 是农村公社的村庄和小村落,共有 33,189 个,分布在 1,279 个公社的 5,203 个分区中,名称仅以阿拉伯语书写。data/v1/douars/ 包含每个 douar 的住户和人口数据;对于住户数不少于 30 户的 douar,还包含其人口按国籍、性别、年龄、民事登记和婚姻状况划分的数据、住户居住的住宅类型,以及住宅到铺设路面道路、小学、collège、lycée 和卫生中心的距离。HCP 不提供规模更小的 douar 的这些数据,这些 douar 的对应值为 null。
Douar 的拉丁字母名称来自使用拉丁字母书写名称的来源:国民教育部的公立学校名录、OpenStreetMap 或 GeoNames;这些名称会与 HCP 的阿拉伯语名称进行匹配,匹配范围仅限该 douar 所属的公社。共有 14,710 个 douar 找到了拉丁字母名称。每轮匹配都会再对错误的公社运行一次,其中仍能找到的名称数量,就是匹配中偶然命中的数量:学校名录为 1.0%,地图的两轮匹配分别为 1.7% 和 4.1%。超过 5% 时,该轮不会写入任何结果。
网站会根据阿拉伯语拼写其他 douar 的名称,相关逻辑位于 api/src/lib/spell.ts:它包含从双语书写的名称中归纳出的词表,以及法语书写摩洛哥名称的规则。
pnpm translit --eval 会使用留出的名称对其进行评分。访客可以为没有任何来源给出名称的 douar 提议一种拼写,同一套引擎会在每晚检查这些提议,通过后才会发布。
API 会在 /api/communes/{code}/douars.json 提供一个公社的 douar 数据,MCP 服务的 get_douars 会将其提供给助手。
名称页面说明了每个名称的来源。
运行
pnpm install
pnpm dataset:build # rebuilds data/v1 from the cached sources
pnpm insights # rebuilds data/v1/insights from the rest of data/v1
pnpm build # the docs site, then the API tree, into dist/
pnpm api:dev # wrangler pages dev on :8788, serving the site and the API together
pnpm api:smoke # probes a running deployment
pnpm check # typecheck both trees, then the tests
pnpm eval # asks a model 49 questions through the MCP server; see evals/
部署构建需要指定网站将要提供服务的源地址,规范网址、链接预览图片、站点地图和 MCP 页面上的配置代码片段都会据此生成:
SITE_URL=https://your-deployment pnpm build
不指定时,网站仍可构建,构建过程会显示提示,但不会生成这四项内容。
pnpm build 中各步骤的顺序很重要:Astro 会清空输出目录,因此会先构建网站,再将 API 文件树输出到同一个 dist/ 目录中。
pnpm site:dev 只会运行 Astro 并启用热重载,但游乐场无法通过这种方式调用 API;要同时查看两者,请使用 pnpm api:dev。
需要 Node 22 或更高版本。部署需要 Cloudflare 账户;请参阅 api/README.md。
数据的整理方式
HCP 以 Excel 格式发布人口普查数据,其中代码列以数值形式存储,前导零已丢失,因此代码长度为 7、8 或 9 位。层级关系根据文档中的行顺序还原,而不是通过代码计算;代码计算仅用于核验父级关系。城乡属性也根据相同行顺序确定:列在 Cercle 标题之前的市镇属于城市。
边界来自 OpenStreetMap 的 admin_level=8 关系,并通过所有 1,503 个关系都带有的 ref:MA:HCP 标签与 HCP 数据关联。Overpass 返回的每条边界由顺序不定的 way 片段组成,因此在输出任何内容之前,先将这些片段首尾相接,拼成闭合环。1,503 条关系中有 1,502 条成功处理:Sidi Mohamed Benmansour 的关系没有可闭合的外环,因此其几何字段为空,而不是使用猜测修补的结果。41 个 arrondissement 同样来自 admin_level=10 关系,全部纳入;每个都必须位于所属市镇内,且这些区域必须覆盖整座城市。
HCP 的指标工作簿以相同代码列出了相同单位,因此按代码关联:1,852 个单位和 164 个城市中心全部纳入。通勤数据在每次人口普查中都有各自的工作簿,单位相同、顺序相同,因此在放置数据之前逐行关联。每列均以 HCP 给出的标题命名;如果标题发生变动,构建流程就会拒绝该工作簿。随后,流程会检查每个单位的人口和家庭户数是否与人口文件一致,并核验各项数字的汇总结果。详情见 indicators/README.md。
人口普查还统计了城市住房存量,并将数据单独放在一个工作簿中:每个城镇有多少套住房、多少套空置、住房类型、房龄、建造材料以及接入的设施。统计对象是住房而非家庭户,因此数据放在 housing/ 中,而不是人口普查指标目录下;784 个单位拥有这类数据。
人口普查还统计了工作场所。HCP 的实地团队绘制了每个经济机构的位置,并按市镇发布数量;数据涵盖 1,847 个单位,每个单位有 22 项数据,包括已绘制的机构总数,以及按行业、雇员人数和创立年代划分的企业数量。每个单位内的分项必须合计为总数,且全国范围内的每项数据都必须沿层级树加总。工作簿按 arrondissement 统计的 6 座城市,采用其自身数据的精确合计,并标记为 basis,与其 2014 年人口数据使用相同的处理方式。详情见 economy/README.md。
2014 年人口普查也发布了同类数据,分别放在 4 个独立工作簿中,并映射到当今的单位:1,979 行中有 1,965 行通过代码、对照表或市镇内部名称匹配成功。3 个工作簿采用相同布局,因此同一个读取器会根据各自的字段列表分别读取。72 个字段与 2024 年普查的字段相同,可与之相减;其余字段的基数或分类有所变化,或仅见于 2014 年:人们从事的职业、工作所在行业以及持有的文凭。每个字段都注明了处理方式。详情见 indicators/2014/README.md;indicators/2014/unplaced.json 列出了 14 条无法匹配到任何单位的记录。
边界数据还表明哪些市镇彼此接壤。当两个市镇的边界共享一段边界时,它们就相邻;在 OpenStreetMap 中,这段边界在两个关系中由相同节点构成,因此匹配是精确的,而非在容差范围内匹配:共有 4,134 对,每对都记录了共享边界的长度。从任意一个市镇沿边界逐一查找,都能到达拥有边界数据的全部 1,502 个市镇;这项检查可确保全国范围形成一个连通图,而不是多个彼此分离的图。
2015 年改革为 207 个市镇重新编号,因此这些市镇没有使用当前代码记录的 2014 年数据。crosswalk/ 通过两轮确定性处理完成对照,并记录每组对应关系的依据,因此每行都可供核验,而不必盲目信任。
致谢与前期工作
- Haut-Commissariat au Plan:RGPH 2024 和 RGPH 2014,所有代码、名称、人口数据和人口普查指标的来源。
- OpenStreetMap 贡献者:所有边界、质心和边界框,采用 ODbL 许可。
- mahdiboughrous/moroccan-administrative-division-data 和 zeys/regionsPrefecturesProvincesCommunesMaroc: 较早的行政区划开放列表。该数据集的审计工作从对照人口普查核查这两份列表开始。
- tn-municipality-api,本项目借鉴的突尼斯项目。
- Bouazzi Maghribi,网站用于呈现阿拉伯语的 Maghribi 字体,由 Alef Type Foundry 按 SIL Open Font License 发布。网站将其作为 Communes Maghribi 提供,并通过
site/scripts/font.py,使用该字体自身的字母和点构造 ݣ、ڭ、گ、ک、پ、چ 和 ﻻ,因为许可证规定不得使用原名称。
引用与更正
CITATION.cff 中包含引用信息,GitHub 会将其显示为“引用此仓库”。如果发现名称、数据或边界有误,可通过数据问题反馈表单报告,表单会要求提供能够确认正确信息的来源。每次推送都会运行测试、构建所有内容,并在 wrangler dev 下进行探测。
许可证
代码采用 MIT 许可。数据许可证按目录划分,如上所述。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。