如何通过坐标设置地址搜索(以及在何处获取必要的目录)



在春季,我们向DaData.ru API添加了“反向地理编码”功能,也称为“ 坐标坐标 ”。 名称暗示:该方法采用地理坐标并提供有关地址的数据。

Yandex提供了具有相同功能的固体产品-称为Geocoder 。 但是Yandex服务仅对开放的非商业项目免费。 标准关税-每年120000 tariff起-不适合所有人。

我们认为-如果您免费或廉价地替代“ Geocoder”,开发人员可能会说声谢谢。 他们做到了。 在本文中,我将告诉您“按坐标表示地址”结构的工作原理:我们如何设置搜索,将目录放在一起并将其打包为现成的方法。

我们从哪里获得数据以及如何寻找地址


在完成任务时,我们研究了现成的解决方案:在哪里获取带有地址的坐标目录,然后如何从该目录中搜索地理对象。 事实证明,您甚至不需要为使用正确的工具而走得太远。

我们将地址对象放在FIAS- 联邦信息地址系统中 。 这是开放地址和官方地址目录中最全面的。 我们已经哈布雷(Habré)上进行了详细介绍,现在有四个重要事实:

  • FIAS存储该国家的所有可寻址对象,从区域及以下-到建筑物和其他领土;
  • 该目录免费提供DBF和XML格式;
  • FIAS并不完美-缺少数万所房屋和许多街道,尤其是新的街道。
  • 目录中的每个地址对象都对应一个唯一的ID-FIAS代码。 目标代码有时会更改,但是对于我们的文章而言,它并不是那么重要。

从FIAS下载的地址对象以及ID是我们反向地理编码目录的基础。

OpenStreetMap (OSM)下载坐标。 OSM是具有免费许可证的项目:发烧友收集各种对象的坐标并将其发布给所有人。

简单来说,OSM是地图上的一组点,线和面。 每个对象都有其自己的描述,类型和坐标集。 俄罗斯的OSM数据位于needgeo.comosm.sbin.ru/osm_dump/osmosis.svimik.com/latest/


来源列表发布在项目“ Wiki”的特殊页面上

卸载由PBF文件组成-使用这种格式代替XML是一种更为紧凑的格式。 将PBF转换为OSM XML无需花费任何费用, 许多社区认可的实用程序都可以解决这个问题。

对于我们自己的目录,我们从FIAS获取地址对象,然后在OSM中查找它们的坐标。 如果找到,请保存合并的数据。 事实证明,FIAS和OSM如此交集。

所有这一切都很棒,但是有一个问题:OSM中的数据质量使事情变得不容易。 对象的坐标通常与现实不符。 例如,区域和区域的多边形就足够了。 但对于城市及以下城市-并不是那么多。


多边形是界定地图上区域的多边形。 它们由一组带有坐标的链接点组成。 多边形表示区域,地区,城市甚至建筑物的边界

很大程度上,主要工作是从OSM收集足够的数据并清除婚姻。 任务如此繁琐,以至于我在本文中专门针对它进行了单独的介绍。

我们还会从OSM下载不在FIAS中的房屋。 正如我上面所说,FIAS中有成千上万的房屋。 这甚至不是问题,而仅仅是现实,背景。 因此,我们用OSM的房屋来补充目录。 但是,只有FIAS中有街道的那些人。 来自OSM的建筑物没有FIAS ID,因此我们将其标识为父母的FIAS代码+门牌号

在目录中,我们正在寻找美丽的Lucene (我们的长期助手)的帮助。 感谢这个技巧,他是一位精通印度的印度人,他写了一篇文章《 使用Lucene索引地理数据》 (一个很好的补充是有关“ adv into space search algorithm ”的材料,关于建立搜索算法的kd树)。

一旦我们了解了Lucene,搜索问题就几乎被自己解决了。 生意依旧-去沙纸。

  1. 我们在Lucene中加载了您的坐标和地址目录,并获得了搜索索引。 为简便起见,几乎所有内容都从其中删除了,仅保留了地址ID和坐标。
  2. 我们通过索引建立搜索:输入-坐标,输出-找到的地址对象的ID。 该搜索不会返回其他信息,因为该索引已被完全缩短。
  3. 满足发行要求,通过找到的ID从“大型” FIAS加载数据。 我们添加了许多内容,从每个人需要的地址在一行中到城市区域首都的标志。
  4. 我们弄清楚了如何对接收的对象进行排序和给出。

到目前为止,一切看起来都很简单,但这只是工作的一小部分。 如果我们没有编译一个像样的目录,那么按坐标搜索地址是行不通的。

如何收集座标和地址


首先,我将摆好行李箱:阅读文章后,迅速做这样的手册是行不通的。 自2014年以来,我们一直在收集它,并不断对其进行补充。 我将谈论这个很长的路要走。

编译目录时最困难的部分是整理来自OSM的坐标。 在开始时,我们尽力验证了它们,包括亲手验证了它们。 然后,主要目标是获取大城市的参考点,并从中获得参考指南。 现在有许多这样的要点,几乎不需要手动检查新数据。 一次,我们将200,000-300,000个带有坐标的地址添加到参考目录,这是我们的操作方法。

我们通过OSM标签形成完整的地址。 在OSM上传中,地址的组成部分被不同的标签分散:

  • 地址:城市村庄Bulatnikovo
  • 地址:街道-中央大街
  • 地址:housenumber-103

我们遍历标签并从中收集完整地址: 中央大街103号Bulatnikovo村

我们通过Dadat标准化API运行每个新地址。 该服务将地址转换为单一格式“类似于FIAS”:

  • 纠正错别字;
  • 解码“ NiNo”和“ Msk”之类的缩写;
  • 将旧名称更改为新名称;
  • 通过索引查找地址中缺少的城市;
  • 定义FIAS代码。

API的地址是干净的,尽管现在它们正在发送信件或包裹。
标准化之前之后
中央大街103号Bulatnikovo村

142718,莫斯科地区,列宁斯基区,以及中央大街103号的布拉特尼科沃。


FIAS代码-a8b6a52f-e96d-4ec3-a0ff-641013ab0445

我们将标准化的房屋,街道和住区存储为一处。 对于街道和村庄,此点是中心。 结果,所有地址对象都在同一张表中,即地址,FIAS ID,纬度和经度。
地址FIAS ID纬度经度
142718,莫斯科地区,列宁斯基区,与中央大街103号布拉特尼科沃a8b6a52f-e96d-4ec3-a0ff-641013ab044555.55877337.667103
119034,莫斯科,Lane Turchaninov,d 6 bldg.28c925e61-9173-48b3-999e-dc85c86d89e755.73709637.597190
我们分析了Dadata未标准化的地址。 该服务会用标志标记无法与FIAS匹配的地址。 我们手动检查它们,有几种选择。

  1. 该地址未包含在正确的OSM上传标签中,但魔鬼知道在哪里。 遇到并没有填写地址标签,还有街道标签中的城市等等。
  2. OSM中有一个异国情调的物体,例如操场,大学橄榄球场甚至是墓地。 FIAS中没有这样的事情,出于我们的目的,这些结果不适合。 这些对象只是被筛选出来。
  3. 一个错误-根本不是一个错误。 例如,FIAS中不存在的城市区域来自OSM。 或在OSM中,该对象位于一个定居点中,但在FIAS中,此定居点已附加到城市并被删除。 然后,完成加载数据的算法,然后再次运行。


解析卸载,在那里-标签混乱

我们检查加载的坐标是否足够。 为此,我们使用特殊的工具来查看新对象的坐标是否落入父级区域或地区的多边形。 如果地址告知该物体位于鄂木斯克地区,请友好地进入其掩埋场。 不需要进入城市-OSM并不能准确覆盖所有城市,因为许多城市的数据不会更新。

我们从OSM加载参考面并将其按原样存储-以GeoJSON格式存储。 要选择要在点上尝试的多边形,请查看单独的表格。 在其中,我们比较了CLADR代码的前缀和多边形的ID:您找到了地址的CLADR代码,并看到了要选择的多边形。


KLADR代码是FIAS之前使用的唯一标识符。 一百万个服务可以找到该代码的地址

该实用程序使物体可以站在距离垃圾填埋场1,700米处。 之所以添加此规则,是因为高速公路经常超出该地区的边界。 统计数据显示,但距离超过1,700米是错误的迹象。

在城市和街道上,检查结束。

再一次,更严格地说,我们检查房屋的加载坐标。 再次提到的实用程序开始起作用,这就是它的作用。

  1. 他取得了新房子的地址,并在参考目录中找到了他的邻居。
  2. 根据坐标,它考虑了未经验证的新房子与可靠邻居之间的距离。


很容易找到邻居:1.我们买了一所新房子,并找到了父母的FIAS ID。 2.我们从参考目录中选择父母具有相同FIAS ID的房屋

仅在距离可靠同事不超过150米的家里进行检查。 此外,在分析以下内容时,我们会考虑每个新批准的房屋。 运作方式如下。

假设在参考指南中, 沿Kommunarov街存储了1号,2号和3号房屋。 在新数据中出现了同一条街上的5号,6号和7号房屋。 从坐标来看,新房子就在附近。 该实用程序会看到5号房屋位于1号,2号和3号房屋旁边,并将其添加到参考目录中。 因此, 第6号和第7号房屋也在接受测试。

然后确定来自OSM的数据的命运:

  • 通过两项检查的房屋:填埋场和邻居,我们添加到参考目录中;
  • 如果对象未落入多边形,则新数据不合适。 如果房子和邻居之间的距离太大,也是如此;
  • 没有邻居的房子,我们推迟了。 它们位于单独的数据库中,有一天我们将对其进行分析。

我们将测试对象分为两部分。 他们将转到我们参考手册的不同版块。


在第一个表格中-所有具有FIAS ID的房屋对象:区域,居民点,街道。 在第二个-在家中,并从第一个表链接到父母

需要两个表来为FIAS缺少的房屋分配钥匙。 他们没有自己的FIAS代码,因此方法如下:

  • 我们将地址对象收集到一张桌子中,每个对象都有自己的FIAS代码;
  • 在第二个表格中-仅在家中,同时在第一个表格中指代父母。

由于没有FIAS代码的建筑物,我们使用FIAS密钥识别父母的ID +门牌号

参考已准备就绪,有待测试。 我们会在一夜之间运行功能测试服务并测试性能。 我们检查了莫斯科的速度,请求在三公里范围内的所有房屋。 可以肯定。 当然,他们用自动测试覆盖了所有内容。

更新后最主要的是不要变得更糟。

通过用户的眼睛进行反向地理编码


输入法采用三个参数:坐标,结果数和搜索半径。 默认半径为100米,最大半径为一公里。 确切的值在设置中设置。

curl -X POST \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -H "Authorization: Token ${API_KEY}" \ -d '{ "lat": 55.878, "lon": 37.653, "radius_meters": 50 }' \ https://suggestions.dadata.ru/suggestions/api/4_1/rs/geolocate/address 

该方法返回找到的对象:房屋,街道和居民点。 它以准确性的降序对它们进行排序。

  1. 在家
  2. 街道。
  3. 定居点。
  4. 城市

然后,它再次排序-按距给定坐标的距离进行排序。 如果该方法找到了四栋房屋和一条街道,则这些房屋将首先按照与给定点的距离顺序站立。 他们的后面是这条街。

在所有这些城堡之后,该方法最终返回它找到的对象。

 { "suggestions": [ { "value": " ,  ,  11", "unrestricted_value": " ,  ,  11", "data": {...} }, { "value": " ,  ,  11", "unrestricted_value": " ,  ,  11", "data": {...} } ] } 

内部-关于找到的对象有很多不同的地方:带有完整和缩写地址的行,当前和过时的名称,邮政编码,父对象的FIAS代码等等。


该方法提供的所有数据都在文档中

不同区域的座标涵盖范围不同,例如房屋:

  • 莫斯科-96%
  • 圣彼得堡-88%
  • 其他上百万个城市-74%,
  • 俄罗斯其他地区为47%。

这里是-覆盖街道:

  • 莫斯科-92%
  • 圣彼得堡-79%
  • 其他百万富翁城市-75%,
  • 俄罗斯其他地区为67%。

他们并没有考虑城市-在俄罗斯的规模上,甚至归属于城市的骄傲称号的事实也不稳定。 例如,根据FIAS官方目录,S / o Fedorkovsky位于雅罗斯拉夫尔地区Poshekhonsky区 。 但实际上,并在地址-农村地区。 从物理上说,农村地区在很大的程度上类似于几个村庄的结合。 不仅要确定中心,而且要在地图上找到住所也很困难。

我们已经在考虑向该方法添加什么:允许按对象类型过滤,返回到给定点的距离等。 我们监控需求并决定是否进行投资。

否则,一切都已经准备就绪。 每年最多10,000 from订阅,每天最多10,000个请求-免费,更多。 如果您需要一个商业项目的坐标地址,并且Geocoder太昂贵,请尝试使用Dadati API

原始文章发布在HFLabs博客上

Source: https://habr.com/ru/post/zh-CN467787/


All Articles