用正则表达式提取地址中的省、市、区等信息


=Start=

缘由:

最近对这一块的内容比较感兴趣,所以收集整理了一些这方面的内容,方便以后有需要的时候参考和使用。

正文:

参考解答:

这个功能说白了其实就是字符串处理,但因为国内的省市区地址可能性非常多,所以不方便用常规的字符串方法进行处理,这时使用正则表达式是一个不错的选择(只能保证提取结果的大概准确,因为实际生活中的情况各种各样,很难完全匹配,除非在填写输入的时候就进行严格控制,但这在大部分情况下都是不现实的)。

这里一方面是为了实现信息提取的功能,另一方面也是想借此顺便熟悉一下正则表达式的捕获组的使用。


因为用到的是正则表达式的捕获组的概念,先简单整理一下捕获组的概念和用法:

捕获组分为:
  • 普通捕获组(Expression)
  • 命名捕获组(?Expression)
普通捕获组:

从正则表达式左侧开始,每出现一个左括号”(“记做一个分组,分组编号从 1 开始。0 代表整个表达式。即,(Expression)

命名捕获组:

每个以左括号开始的命名捕获组(?Expression),都紧跟着 ?,而后才是正则表达式。

非捕获组:

在左括号后紧跟 ?:,而后再加上正则表达式,构成非捕获组 (?:Expression)


然后再整理一下中国各省级城市列表:

34个省级行政单位:23个省、4个直辖市、2个特别行政区、5个自治区。

我国共有34个省级行政区,其中:
· 直辖市有4个:北京市(京)、天津市(津)、上海市(沪)、重庆市(渝)。
· 特别行政区有2个:香港特别行政区和澳门特别行政区。
· 自治区有5个:新疆维吾尔自治区(新)、宁夏回族自治区(宁)、西藏自治区(藏)、广西壮族自治区(桂)、内蒙古自治区(内蒙古)。
· 省份有23个:河北省(冀)、山西省(晋)、辽宁省(辽)、吉林省(吉)、黑龙江省(黑)、江苏省(苏)、浙江省(浙)、安徽省(皖)、福建省(闽)、江西省(赣)、山东省(鲁)、河南省(豫)、湖北省(鄂)、湖南省(湘、)广东省(粤)、海南省(琼)、四川省(川、蜀)、贵州省(黔、贵)、云南省(滇、云)、陕西省(陕、秦)、甘肃省(甘、陇)、青海省(青)、台湾省(台)。

最后再把网上找到的Java代码片段放一下,方便使用(也可以按需进行微调):

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AddressResolutionUtil {
    public static String regex = "(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县)(?<county>[^县]+县|.+区|.+市|.+旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<village>.*)";
    public static Pattern pattern = Pattern.compile(regex);

    public static List<Map<String,String>> addressResolution(String address) {
        Matcher m = pattern.matcher(address);
        String province = null, city = null, county = null, town = null, village = null;
        List<Map<String,String>> table = new ArrayList<Map<String,String>>();
        Map<String,String> row = null;
        while(m.find()) {
            row = new LinkedHashMap<String,String>();
            province = m.group("province");
            row.put("province", province==null ? "" : province.trim());
            city = m.group("city");
            row.put("city", city==null ? "" : city.trim());
            county = m.group("county");
            row.put("county", county==null ? "" : county.trim());
            town = m.group("town");
            row.put("town", town==null ? "" : town.trim());
            village = m.group("village");
            row.put("village", village==null ? "" : village.trim());
            table.add(row);
        }
        return table;
    }

    public static void main(String[] args) {
        System.out.println(addressResolution("湖北省武汉市洪山区"));
        System.out.println(addressResolution("湖北省恩施土家族苗族自治州恩施市"));
        System.out.println(addressResolution("北京市市辖区朝阳区"));
        System.out.println(addressResolution("内蒙古自治区兴安盟科尔沁右翼前旗"));
        System.out.println(addressResolution("西藏自治区日喀则地区日喀则市"));
        System.out.println(addressResolution("海南省省直辖县级行政单位中沙群岛的岛礁及其海域"));
        System.out.println(addressResolution("陕西省延安市宝塔区麦克大厦"));
    }

}

参考链接:

java从地址串中解析提取省市区-完美匹配中国所有地址
https://blog.csdn.net/superSubfn/article/details/80290491

java 从字符串中提取省、市、区、镇、乡等区域名称(包含少数民族地区)
https://blog.csdn.net/qq_40083897/article/details/83048587

用正则表达式切割详细地址中的省、市、区
https://blog.csdn.net/qq_38584262/article/details/86302509

JAVA实现地址解析功能
https://blog.csdn.net/renfng/article/details/94738164

中国各省份城市列表
http://www.maps7.com/china_province.php

Java 正则表达式
https://www.runoob.com/java/java-regular-expressions.html

JAVA正则表达式语法示例与语法大全
https://www.w3cschool.cn/regexp/x9hf1pq9.html

[疯狂Java]正则表达式:捕获组、反向引用、捕获组命名
https://blog.csdn.net/Lirx_Tech/article/details/51721491

深入入门正则表达式(java) – 命名捕获
https://blog.csdn.net/su1216/article/details/49407381

Java 正则表达式的捕获组(capture group)
https://www.runoob.com/w3cnote/java-capture-group.html

正则表达式的捕获组(Java)
https://www.cnblogs.com/lyy-blog/p/9817361.html

=END=


《 “用正则表达式提取地址中的省、市、区等信息” 》 有 9 条评论

  1. What is “String args[]”? parameter in main method Java
    https://stackoverflow.com/questions/890966/what-is-string-args-parameter-in-main-method-java
    `
    public static void main(String[] args) {
    }

    > java MyProgram one two

    args.length == 2
    [“one”, “two”] == args

    args[0] 是你传入的第一个参数,args[1]是传入的第二个参数,以此类推。
    和 C语言 的不太一样,C语言中 args[0] 指的是程序自己的名称。
    `
    https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html
    https://www.runoob.com/note/16907

    http://journals.ecs.soton.ac.uk/java/tutorial/java/cmdLineArgs/parsing.html

  2. `
    // count/sum特定字段,内容包含手机号,查询id类字段
    String regexCalc = “(?count|sum)\\s{0,}\\((?[^()]+)\\)”;
    Pattern patternCalc = Pattern.compile(regexCalc);
    String regexMobile = “(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}”;
    Pattern patternMobile = Pattern.compile(regexMobile);
    String regexDirect = “(?user_?id|acct_?id|uid)\\s{0,}=\\s{0,}(‘|\”)?(?[0-9]{4,18})”;
    Pattern patternDirect = Pattern.compile(regexDirect);
    `

  3. 如果一个文件里面,下面的词语出现了20次以上(不做去重处理),则认为该文件中存在收货/发货地址信息:
    省,市,区,县,乡,镇,村,自治,单元,楼

    中华人民共和国行政区划(五级):省级、地级、县级、乡级和村级。省份、城市、区县、乡镇、村庄。
    https://github.com/modood/Administrative-divisions-of-China

    中国行政区划信息
    https://github.com/mumuy/data_location

    全网识别准确度最高的中国大陆收货地址智能解析
    https://github.com/ldwonday/zh-address-parse

    中国地址生成器
    https://www.meiguodizhi.com/cn-address
    `
    美国地址
    加拿大地址
    澳大利亚地址
    日本地址
    台湾地址
    韩国地址
    香港地址
    英国地址
    德国地址
    新加坡地址
    法国地址
    意大利地址
    西班牙地址
    荷兰地址
    马来西亚地址
    俄罗斯地址
    中国地址
    泰国地址
    菲律宾地址
    阿根廷地址
    土耳其地址
    越南地址
    `

  4. 市以上行政区划去掉后缀
    https://blog.est.im/2023/stdout-09
    `
    今天才知道,中国一共333个市一级行政单位。数据来源是 民政部首页 ➡ 民政数据 ➡ 2022年民政事业发展统计公报

    省、自治区、自治州、自治县、市、盟

    def short_name(name):

    上面这段代码的作用是把比如 “黔南布依族苗族自治州” 这样的名字,缩短成 “黔南”。

    有一个小坑是,市一级行政区包含 蒙古|柯尔克孜|哈萨克 这三个名字后面没有 族 字。

    有一些 XX林区 XX矿区 什么的,我觉得保留比较好。

    Python的 re.VERBOSE 真是好东西!
    `

    民政数据
    https://www.mca.gov.cn/n156/index.html
    `
    截至 2022 年底,全国共有省级行政区划单位 34 个,地级行政区划单位 333 个,县级行政区划单位 2843 个,乡级行政区划单位 38602 个。
    `

  5. ([一-龥])中各字符是啥意思?特别是中间短线。
    https://zhidao.baidu.com/question/163837330.html
    `
    龥 (发音:yu)

    [一-龥]
    就我目前所知 一-龥 代表的是 unicode 中的中文范围
    是 unicode 里面的中文编码的第一个字和最后一个字

    unicode 又叫 万国码 是一种编码,是用数字代表文字的一项标准。
    这个世界上所有可以书写,可以发音的语言都会被 unicode 吸纳
    上面的是定义 ,其实 不能书写和发音的emoji 也包含在内
    其原理就是将每一种语言的每一个文字 都给他一个数字像是人的身份证号一样。用于绝对定位它

    [一-龥] 写成十六进制 就是 [0x4e00-0x9fa5] 转换成十进制 19968-40869
    也就是说 unicode 收录了 40869 – 19968 = 20901 个 汉字

    我学的正则里面要匹配所有汉字的写法是 [\u4e00-\u9fa5] 相当于你的 [一-龥]
    \u 就是 unicode 的意思
    这种直接 [一-龥] 这么写的 由于才疏学浅并没见过。
    我猜测是易语言之类的 直接用中文编码的语言
    `

  6. python判断是否汉字的5种方法实例
    https://www.jb51.net/python/290637ks9.htm
    `
    1. 使用Python内置的ord() — ord()函数将字符转换为Unicode编码,然后判断其范围是否在汉字的范围内 if ‘\u4e00’ <= char <= '\u9fff': return True

    2. 使用Python内置的unicodedata库 — if 'CJK' in unicodedata.name(char): return True

    3. 使用正则表达式 — 使用 [^\u4e00-\u9fa5] 可以匹配所有非汉字字符,而 [^\x00-\xff] 可以匹配所有双字节字符,包括汉字和符号等

    4. 使用中文字符集 — if b'\xb0\xal' <= word.encode('gb2312') <= b'\xd7\xf9': return True

    5. 使用第三方库 — 例如 xpinyin 库可以将一个字符串转换为拼音,并判断字符串是否为汉字
    `

  7. 匹配收货地址的正则表达式
    `
    [一-龥]{2,10}(?:市)[一-龥a-zA-Z0-9]{2,30}(?:区|县)[一-龥a-zA-Z0-9]{3,10}(?:路|街|镇|乡|单元|村)[一-龥a-zA-Z0-9-]{3,10}
    [\u4e00-\u9fa5]{2,10}(?:市)[\u4e00-\u9fa5a-zA-Z0-9]{2,30}(?:区|县)[\u4e00-\u9fa5a-zA-Z0-9]{3,10}(?:路|街|镇|乡|单元|村)[\u4e00-\u9fa5a-zA-Z0-9-]{3,10}
    `
    最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等
    https://www.cnblogs.com/zxin/archive/2013/01/26/2877765.html

  8. (?[^省]+自治区|.*?省|.*?行政区|.*?市)(?[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县)(?[^县]+县|.+区|.+?市|.+旗|.+海域|.+岛)?(?[^区]+区|.+?镇)?(?.*)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注