项目目的

根据传入的地址,智能提取所属的省市县镇村5级地址。例如:用户输入“江苏南通嗨安李堡镇陈庄村8组88号”,我们需要提取到江苏省  南通市  海安县(即便用户输入了错字,“海”写成了“嗨”) 李堡镇  陈庄村 这5级地址以及相应编号。

项目地址

https://github.com/jaa88/springboot-mybatis-elasticsearch

使用步骤

 1.安装elasticsearch,推荐es 5.6,因为版本不同可能部分api访问失败。在配置文件中配置相关地址
2.执行localhost:7070/address/readAddress 五级地址信息放在resource下,另外,我是500条一执行(因为我给es分的内存只有 256mb,穷啊,买的1g内存的阿里云服务器,内存有限),请根据自己的内存,适当调高,一般本地测的时候,10000条/次导入es无压力。
3.访问时,localhost:7070/address/searchAddress?addressName=********即可

解决方案分析

一开始同事的思路:研究分词算法,将用户输入的地址按省市县镇村分隔。

个人感觉:实现不了,因为用户输入并不是标准输入,例如标准地址为“江苏省南通市海安县李堡镇陈庄村**组**号”,但是用户 的输入不可控,他可能输入“江苏南通海安....”,也许输入“江苏海安....”,可能多字,可能少字,可能错别字

我的实现思路:分词、倒排索引、文本相似度匹配

思路听起来很高大上,其实有现成的工具ElasticSearch(底层是Lucene全文搜索引擎)帮我们完成了几乎所有的工作。

问题分析抽象:

其实这个场景很清晰,我们就是要从一个地址中识别出各级别,但是这个地址本身不能够为我们提供这些标准数据。
       转化一下思路,我们可不可以拿用户输入的,去和标准的五级完整数据(例如江苏省南通市海安县李堡镇陈庄村)匹配?取匹配度最高的那一条,标准的那条对应的五级就很清晰明了了。
例如用户输入“江苏省海安县李堡镇陈庄村8组88号”,发现和“江苏省南通市海安县李堡镇陈庄村”匹配度最高,而这条文档又可以提供出省、市、县、镇、村相关信息。

付诸实现:详见代码

过程&结果

将国家统计局爬取的地址数据,导入es中用于检索,原数据存放格式为:

 110000000000   北京市 1   省
110100000000 市辖区 2 市
110101000000 东城区 3 区县
110101001000 东华门街道办事处 4 街道
110101001001 多福巷社区居委会 5 村、社区
110101001002 银闸社区居委会 5 村、社区

中间的间隔为空格或者tab,不太好分隔,首先在nodepad++中将所有的空格和tab都使用@@替换,这样可以使用@@分隔。处理后的格式为:

 110000000000@@北京市@@1@@省
110100000000@@市辖区@@2@@市
110101000000@@东城区@@3@@区县
110101001000@@东华门街道办事处@@4@@街道
110101001001@@多福巷社区居委会@@5@@村、社区
110101001002@@银闸社区居委会@@5@@村、社区
110101001005@@东厂社区居委会@@5@@村、社区
110101001006@@智德社区居委会@@5@@村、社区

es中存储的数据结构为若干以下格式的文档,约67万条:

 {
"fullAddressName": "北京市市辖区东城区东华门街道办事处黄图岗社区居委会",
"provAddrNo": "110000000000",
"provAddr": "北京市",
"cityAddrNo": "110100000000",
"cityAddr": "市辖区",
"areaAddrNo": "110101000000",
"areaAddr": "东城区",
"townAddrNo": "110101001000",
"townAddr": "东华门街道办事处",
"villageAddrNo": "110101001008",
"villageAddr": "黄图岗社区居委会"
}

检索时,拿fullAddressName进行匹配,默认带出10条数据,相似度降序排列.例如键入"http://localhost:7070/address/searchAddress?addressName=海安李堡陈庄村十一组47号"时,结果默认展示10条,按相似度降序排列,用的时候一般用第一条,咋用看需求

[{
"fullAddressName": "江苏省南通市海安县李堡镇陈庄村委会",
"provAddrNo": "320000000000",
"provAddr": "江苏省",
"cityAddrNo": "320600000000",
"cityAddr": "南通市",
"areaAddrNo": "320621000000",
"areaAddr": "海安县",
"townAddrNo": "320621103000",
"townAddr": "李堡镇",
"villageAddrNo": "320621103200",
"villageAddr": "陈庄村委会"
}, {
"fullAddressName": "吉林省松原市长岭县前七号镇西十一号村委会",
"provAddrNo": "220000000000",
"provAddr": "吉林省",
"cityAddrNo": "220700000000",
"cityAddr": "松原市",
"areaAddrNo": "220722000000",
"areaAddr": "长岭县",
"townAddrNo": "220722104000",
"townAddr": "前七号镇",
"villageAddrNo": "220722104207",
"villageAddr": "西十一号村委会"
}, {
"fullAddressName": "吉林省长春市榆树市八号镇十一号村委会",
"provAddrNo": "220000000000",
"provAddr": "吉林省",
"cityAddrNo": "220100000000",
"cityAddr": "长春市",
"areaAddrNo": "220182000000",
"areaAddr": "榆树市",
"townAddrNo": "220182110000",
"townAddr": "八号镇",
"villageAddrNo": "220182110205",
"villageAddr": "十一号村委会"
}, {
"fullAddressName": "吉林省松原市长岭县三十号乡三十一村委会",
"provAddrNo": "220000000000",
"provAddr": "吉林省",
"cityAddrNo": "220700000000",
"cityAddr": "松原市",
"areaAddrNo": "220722000000",
"areaAddr": "长岭县",
"townAddrNo": "220722209000",
"townAddr": "三十号乡",
"villageAddrNo": "220722209202",
"villageAddr": "三十一村委会"
}, {
"fullAddressName": "江苏省南通市海安县李堡镇李堡社区居委会",
"provAddrNo": "320000000000",
"provAddr": "江苏省",
"cityAddrNo": "320600000000",
"cityAddr": "南通市",
"areaAddrNo": "320621000000",
"areaAddr": "海安县",
"townAddrNo": "320621103000",
"townAddr": "李堡镇",
"villageAddrNo": "320621103007",
"villageAddr": "李堡社区居委会"
}, {
"fullAddressName": "天津市市辖区静海区独流镇十一堡村委会",
"provAddrNo": "120000000000",
"provAddr": "天津市",
"cityAddrNo": "120100000000",
"cityAddr": "市辖区",
"areaAddrNo": "120118000000",
"areaAddr": "静海区",
"townAddrNo": "120118102000",
"townAddr": "独流镇",
"villageAddrNo": "120118102218",
"villageAddr": "十一堡村委会"
}, {
"fullAddressName": "吉林省松原市扶余市三岔河镇西十一号村委会",
"provAddrNo": "220000000000",
"provAddr": "吉林省",
"cityAddrNo": "220700000000",
"cityAddr": "松原市",
"areaAddrNo": "220781000000",
"areaAddr": "扶余市",
"townAddrNo": "220781100000",
"townAddr": "三岔河镇",
"villageAddrNo": "220781100211",
"villageAddr": "西十一号村委会"
}, {
"fullAddressName": "吉林省松原市长岭县前七号镇东十一村委会",
"provAddrNo": "220000000000",
"provAddr": "吉林省",
"cityAddrNo": "220700000000",
"cityAddr": "松原市",
"areaAddrNo": "220722000000",
"areaAddr": "长岭县",
"townAddrNo": "220722104000",
"townAddr": "前七号镇",
"villageAddrNo": "220722104213",
"villageAddr": "东十一村委会"
}, {
"fullAddressName": "河北省张家口市崇礼区狮子沟乡十一号村委会",
"provAddrNo": "130000000000",
"provAddr": "河北省",
"cityAddrNo": "130700000000",
"cityAddr": "张家口市",
"areaAddrNo": "130709000000",
"areaAddr": "崇礼区",
"townAddrNo": "130709205000",
"townAddr": "狮子沟乡",
"villageAddrNo": "130709205216",
"villageAddr": "十一号村委会"
}, {
"fullAddressName": "吉林省松原市扶余市三岔河镇东十一号村委会",
"provAddrNo": "220000000000",
"provAddr": "吉林省",
"cityAddrNo": "220700000000",
"cityAddr": "松原市",
"areaAddrNo": "220781000000",
"areaAddr": "扶余市",
"townAddrNo": "220781100000",
"townAddr": "三岔河镇",
"villageAddrNo": "220781100210",
"villageAddr": "东十一号村委会"
}]

省市县镇村五级地址智能提取(标准地址源来自国家统计局官网)SpringBoot+Elasticsearch 5.6的更多相关文章

  1. Jsoup获取全国地区数据(省市县镇村)(续) 纯干货分享

    前几天给大家分享了一下,怎么样通过jsoup来从国家统计局官网获取全国省市县镇村的数据.错过的朋友请点击这里.上文说到抓取到数据以后,我们怎么转换成我们想要格式呢?哈哈,解析方式可能很简单,但是有一点 ...

  2. Jsoup获取全国地区数据(省市县镇村)

    最近手头在做一些东西,需要一个全国各地的地域数据,从省市区到县镇乡街道的.各种度娘,各种谷歌,都没找到一个完整的数据.最后功夫不负有心人,总算找到一份相对来说比较完整的数据,但是这里的数据也只是精确到 ...

  3. [转]OpenTK学习笔记(1)-源码、官网地址

    OpenTK源码下载地址:https://github.com/opentk/opentk OpenTK使用Nuget安装命令:OpenTK:Install-Package OpenTK -Versi ...

  4. OpenTK学习笔记(1)-源码、官网地址

    OpenTK源码下载地址:https://github.com/opentk/opentk OpenTK使用Nuget安装命令:OpenTK:Install-Package OpenTK -Versi ...

  5. 全中国的省市县镇乡村数据获取以及展示java源代码

    第一步.准备工作(数据源+工具): 数据源(截止目前最全面权威的官方数据):http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/ 爬取数据的工具 ...

  6. 基于PHP的地址智能解析案例-快宝开放平台

    快宝地址智能解析,批量录入收件人.发件人最好的解决方案,广泛应用于快递行业,电商行业,ERP应用等. 一.对接前准备 注册快宝开放平台,获得开发者账号,查看如何注册. 二.对接联调 快宝开放平台支持多 ...

  7. 提取IPv6地址的编码信息

    提取IPv6地址的编码信息   为了保持兼容和地址转化,很多IPv6地址将额外的信息编码到地址信息中,如IPv4地址和Mac地址.在Nmap中,可以使用address-info脚本提取内嵌的信息,并进 ...

  8. c# HTML中提取图片地址

    public class HtmlHelper    {        /// <summary>        /// HTML中提取图片地址        /// </summa ...

  9. asp之GetArray提取链接地址,以$Array$分隔的代码

    '================================================== '函数名:GetArray '作 用:提取链接地址,以$Array$分隔 '参 数:ConStr ...

随机推荐

  1. 【原创】大叔经验分享(71)docker容器中使用jvm工具

    java应用中经常需要用到jvm工具来进行一些操作,如果java应用部署在docker容器中,如何使用jvm工具? 首先要看使用的docker镜像, 比如常用的openjdk镜像分为jdk和jre,只 ...

  2. 题解 P2661 【信息传递】

    首先介绍个概念:基环外向树,也叫环加外向树,环基树,章鱼图. 这就是一颗基环外向树. 不难发现,若基环外向树有n个结点就有n条边,这也意味 着它不是颗普通的树,而是必定有一个自环. 再看看题目中的介绍 ...

  3. 与 QWidget 有关的 Qt 可视化组件的继承关系图

    与 QWidget 有关的 Qt 可视化组件的继承关系图

  4. O042、Live Migrate 操作

    参考https://www.cnblogs.com/CloudMan6/p/5554549.html   Migrate 操作会先将Instance停掉,也就是所谓的 冷迁移 .而 Live Migr ...

  5. vue2.0关于for循环 index的使用方法

    <!DOCTYPE html> <html> <head> <title>for循环</title> </head> <b ...

  6. 解决 'mvn' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    'mvn' 不是内部或外部命令,也不是可运行的程序 或批处理文件. 九步完成

  7. LINUX中lrzsz软件的使用

    安装lrzsz 可以在Linux 和 windows直接相互传文件 Linux无论ssh跳过去也可以sz rz打开图像进行传输文件 [root@master2 ~]# yum install lrzs ...

  8. python 小记

    判断一个数是奇数还是偶数 #!/usr/bin/env python3 #_*_coding:UTF-8_*_ def pan(num): ==: print( str(num) + ' is: 偶数 ...

  9. dedecms 上传目录路径

    DedeCms已经升级到5.7版本了..可惜附件的目录还是不统一,比如我们从后台把附件目录调整为Ym(默认为Ymd)然而我们的附件路径依然是不一样的比如:Ymd代表年月日从文章里上传路径为:/Ym/1 ...

  10. httpleaks及url的小技巧(http:evil)

    HTTP Leak攻击简介 当前Web技术下包含了大量HTML元素和属性,这些HTML元素和属性会请求一些外部资源,而在它们的HTTP请求过程中,可能存在潜在的敏感信息泄露.为此,德国著名网络安全公司 ...