使用geobuf将.pbf转JSON时返回NoneType的问题排查
问题
我从以下地址下载.pbf文件:
https://api.mapbox.com/v4/tableau-enterprise.ctcaz7rr/4/7/5.vector.pbf?sku=101NmEGuqERal&access_token=pk.eyJ1IjoidGFibGVhdS1lbnRlcnByaXNlIiwiYSI6ImNrY29iZjN6MzA4ZzgycHF6MHd0cXhyaXoifQ.rtfFAKyzk-qMYue5C-8RVA
该链接返回如下JSON数据:
{"bounds":[-171.5625,-55.37911,178.59375,81.093214],"center":[120.585938,23.563592,9],"created":1608167491585,"created_by_client":"studio","description":"admin2-lines_z49.mbtiles","filesize":56315904,"format":"pbf","generator":"tile-join v1.36.0","generator_options":"tippecanoe -f -o admin2-labels_z49.mbtiles -r0 -Z4 -z9 -l admin-2-labels-j admin2_label_mb_stage2.geojson; tippecanoe -f -o admin2-lines_z49.mbtiles -r0 -Z4 -z9 -l admin-2-lines admin2_mb_merge.geojson; tile-join -o admin-2-join_z9.mbtiles admin2-lines_z49.mbtiles admin2-labels_z49.mbtiles","id":"tableau-enterprise.ctcaz7rr","mapbox_logo":true,"maxzoom":9,"minzoom":4,"modified":1608167491377,"name":"admin_2_z9-9pepve","private":true,"scheme":"xyz","tilejson":"2.2.0","tiles":["https://a.tiles.mapbox.com/v4/tableau-enterprise.ctcaz7rr/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1IjoidGFibGVhdS1lbnRlcnByaXNlIiwiYSI6ImNrY29iZjN6MzA4ZzgycHF6MHd0cXhyaXoifQ.rtfFAKyzk-qMYue5C-8RVA","https://b.tiles.mapbox.com/v4/tableau-enterprise.ctcaz7rr/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1IjoidGFibGVhdS1lbnRlcnByaXNlIiwiYSI6ImNrY29iZjN6MzA4ZzgycHF6MHd0cXhyaXoifQ.rtfFAKyzk-qMYue5C-8RVA"],"type":"overlay","upload_id":"ckis5d9e5082z23phtcg5sol1","vector_layers":[{"description":"","fields":{"default":"String","id":"Number","name_de":"String","name_en":"String","name_es":"String","name_fr":"String","name_ja":"String","name_ko":"String","name_pt":"String","name_zh":"String","name_zh-Hans":"String","parent_0":"String","worldview":"String"},"id":"admin-2-labels-j","maxzoom":9,"minzoom":4,"source":"tableau-enterprise.ctcaz7rr","source_name":"admin_2_z9-9pepve"},{"description":"","fields":{"worldview":"String"},"id":"admin-2-lines","maxzoom":9,"minzoom":4,"source":"tableau-enterprise.ctcaz7rr","source_name":"admin_2_z9-9pepve"}],"version":"2","webpage":"https://a.tiles.mapbox.com/v4/tableau-enterprise.ctcaz7rr/page.html?access_token=pk.eyJ1IjoidGFibGVhdS1lbnRlcnByaXNlIiwiYSI6ImNrY29iZjN6MzA4ZzgycHF6MHd0cXhyaXoifQ.rtfFAKyzk-qMYue5C-8RVA"}
我通过Chrome工具将.pbf文件下载到本地,随后尝试使用geobuf将其转换为GeoJSON,代码如下:
import geobuf with open('C:\\Users\\<mydir>\\Downloads\\5.vector.pbf', 'rb') as f: contents = f.read() f.close() my_json = geobuf.decode(contents) # Geobuf string -> GeoJSON or TopoJSON print('********', my_json)
但调用geobuf.decode()后仅返回NoneType对象,请问哪里操作出错了?
原因与解决方法
核心问题
你混淆了两种完全不同的PBF格式:
- 你下载的是Mapbox矢量瓦片(Vector Tile)PBF,这是用于地图渲染的瓦片格式,遵循矢量瓦片规范
geobuf仅支持解码Geobuf格式的PBF——这是GeoJSON的二进制压缩格式,和矢量瓦片不属于同一标准,因此无法识别并返回None
步骤1:获取正确的矢量瓦片文件
你访问的原始链接返回的是TileJSON元数据,并非真正的矢量瓦片。真正的瓦片下载地址在返回JSON的tiles字段中,需要把占位符{z}/{x}/{y}替换为目标层级、行列号(即你原链接中的4/7/5),生成实际下载链接:
https://a.tiles.mapbox.com/v4/tableau-enterprise.ctcaz7rr/4/7/5.vector.pbf?access_token=pk.eyJ1IjoidGFibGVhdS1lbnRlcnByaXNlIiwiYSI6ImNrY29iZjN6MzA4ZzgycHF6MHd0cXhyaXoifQ.rtfFAKyzk-qMYue5C-8RVA
使用该链接才能下载到有效的矢量瓦片PBF文件。
步骤2:使用正确的工具解码
方法1:Python用mapbox-vector-tile库
先安装依赖:
pip install mapbox-vector-tile
解码代码示例:
import mapbox_vector_tile with open('C:\\Users\\<mydir>\\Downloads\\5.vector.pbf', 'rb') as f: tile_data = f.read() # 解码矢量瓦片,得到包含各图层的字典 tile_content = mapbox_vector_tile.decode(tile_data) # 查看每个图层的数据 for layer_name, layer in tile_content.items(): print(f"图层名称:{layer_name}") print(f"要素数量:{len(layer['features'])}") if layer['features']: print("第一个要素示例:", layer['features'][0])
方法2:命令行用ogr2ogr直接转GeoJSON
如果需要直接转换成标准WGS84坐标的GeoJSON,ogr2ogr操作更简便:
ogr2ogr -f GeoJSON output.geojson input.vector.pbf
该命令会自动完成坐标转换(从Web墨卡托转WGS84),并输出完整的GeoJSON文件。
内容的提问来源于stack exchange,提问作者gdogg371
相关产品推荐
相关产品推荐

