geocode-sqlite 作者:eyeseast

标星

README 源代码

geocode-sqlite

PyPI Changelog Tests License

对 SQLite 表中的行进行地理编码

安装

使用 pippipx 安装此工具

# install inside a virtualenv
pip install geocode-sqlite

# install globally
pipx install geocode-sqlite

使用方法

假设您有一个包含地址的电子表格,并且想要将这些位置映射出来。首先,使用 sqlite-utils 创建一个 SQLite 数据库并将电子表格中的行插入其中。

sqlite-utils insert data.db data data.csv --csv

现在,使用 OpenStreetMap 的 Nominatim 地理编码器对其进行地理编码。

geocode-sqlite nominatim data.db data \
 --location="{address}, {city}, {state} {zip}" \
 --delay=1 \
 --user-agent="this-is-me"

在上面的命令中,您使用的是 Nominatim,它是免费的,只需要一个唯一的用户代理(--user-agent)。

这将连接到数据库 (data.db) 并读取表 data 中的所有行(跳过任何已填充 latitudelongitude 列的行)。

您还在告诉地理编码器如何使用 Python 的内置字符串格式从数据行中提取位置查询(--location),并设置每秒一个请求的速率限制(--delay)。

对于地理编码成功的每一行,都会填充 latitudelongitude。如果遇到错误或达到速率限制,请再次运行相同的查询,从中断的地方继续。

可以使用 datasette-cluster-map 将结果表布局可视化。

在底层,此软件包使用了优秀的 geopy 库,该库稳定且经过充分实践检验。如果您需要帮助理解特定地理编码器的选项,请查阅 geopy 的文档

支持的地理编码器

CLI 目前支持这些地理编码器

  • bing
  • googlev3
  • mapquest(和 open-mapquest
  • mapbox
  • nominatim
  • opencage

添加新的地理编码器

  1. 以地理编码服务的名称作为议题标题提出议题(示例)。将任何值得注意的实现细节放在议题正文中,例如如果需要 API 密钥,在哪里获取。
  2. Fork 仓库并添加一个地理编码器。
  3. Makefile 中添加示例。如果新增了共享功能,请添加测试。

常用参数和选项

每个地理编码器需要知道在哪里找到它处理的数据。这是前两个参数

  • database: SQLite 文件的路径,必须已存在
  • table: 该数据库中已存在且包含待地理编码数据的表的名称

此外,我们还有一组传递给每个地理编码器的选项

  • location: 一个 字符串格式,将用每行数据进行展开,以构建完整的待地理编码查询
  • delay: 每次调用之间的延迟(某些服务要求此项)
  • latitude: 纬度列名
  • longitude: 经度列名
  • geojson: 将结果存储为 GeoJSON,而不是存储在 latitude 和 longitude 列中
  • spatialite: 将结果存储在 SpatiaLite 几何列中,而不是存储在 latitude 和 longitude 列中
  • raw: 将原始地理编码结果存储在 JSON 列中

每个地理编码器除上述选项外,还接受额外的特定参数,例如 API 密钥。同样,geopy 的文档 是一个极好的资源。

使用 SpatiaLite

--spatialite 标志会将结果存储在 几何列 中,而不是存储在 latitudelongitude 列中。如果您正在进行其他 GIS 操作,例如使用 空间索引,这将非常有用。请参阅 SpatiaLite 手册函数列表,了解更多可能性。

捕获额外的地理编码数据

地理编码服务通常返回的不仅仅是坐标数据。这可能包括精度、标准化地址或其他上下文信息。可以使用 --raw 标志捕获这些信息。默认情况下,这将添加一个 raw 列并将完整的地理编码响应存储为 JSON。如果您想重命名该列,请传递一个值,例如 --raw custom_raw

此响应对象的结构会因服务而异。您可以使用 SQLite 的内置 JSON 函数 查询特定值。例如,这适用于 Google 的地理编码器

select
  json_extract(raw, '$.formatted_address') as address,
  json_extract(raw, '$.geometry.location_type') as location_type
from
  innout_test

请查阅各地理编码服务的文档,了解响应中包含哪些内容。

Python API

命令行界面旨在支持每个地理编码器最常用的选项。如需更精细的控制,请使用 Python API。

与 CLI 一样,这假设您已经有一个 SQLite 数据库和包含位置数据的表。

from geocode_sqlite import geocode_table
from geopy.geocoders import Nominatim

# create a geocoder instance, with some extra options
nominatim = Nominatim(user_agent="this-is-me", domain="nominatim.local.dev", scheme="http")

# assuming our database is in the same directory
count = geocode_table("data.db", "data", query_template="{address}, {city}, {state} {zip}")

# when it's done
print(f"Geocoded {count} rows")

任何 geopy 地理编码器 都可以与 Python API 一起使用。

开发

要为这个工具贡献代码,首先检出代码。然后创建一个新的虚拟环境

cd geocode-sqlite
python -m venv .venv
source .venv/bin/activate

或者如果您使用的是 pipenv

pipenv shell

现在安装依赖和测试

pip install -e '.[test]'

运行测试

pytest

请记住,这个库主要是其他经过充分测试的项目(特别是:clickgeopysqlite-utils)之间的“胶水”代码。测试应侧重于确保这些部分正确地连接在一起。我们可以假设这些部分本身已经正常工作。

为此,其中包含一个测试地理编码器:geocode_sqlite.testing.DummyGeocoder。该地理编码器配合 AllThePlaces 提供的 In-N-Out Burger 位置数据集使用。它像一个普通的 GeoPy 地理编码器一样工作,但只使用包含的数据库返回 In-N-Out 位置的结果。