BE_ParseAddress.groovy 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. import com.sweetfish.service.RetResult
  2. import com.yinjie.heating.common.api.BusinessExecutor
  3. import com.yinjie.heating.common.datas.ERPModule
  4. import com.yinjie.heating.common.entity.base.ProcessStringItem
  5. import com.yinjie.heating.common.entity.system.ParseAreaResult
  6. import com.yinjie.heating.common.tool.ERPUtils
  7. import groovy.json.JsonSlurper
  8. import org.apache.commons.lang3.StringUtils
  9. import org.apache.logging.log4j.LogManager
  10. import org.apache.logging.log4j.Logger
  11. import javax.annotation.Resource
  12. import java.util.concurrent.atomic.AtomicInteger
  13. import java.util.concurrent.atomic.AtomicReference
  14. import java.util.regex.Matcher
  15. import java.util.regex.Pattern
  16. import java.util.stream.Collectors
  17. import java.util.stream.Stream
  18. /**
  19. * Created by jlutt on 2022-02-09
  20. * 地址解析为省市区联系人电话
  21. * @author jlutt
  22. */
  23. class BE_ParseAddress implements BusinessExecutor<ProcessStringItem, ParseAreaResult> {
  24. protected final Logger logger = LogManager.getLogger(this.getClass().getSimpleName())
  25. private static final String EMPTY = "", BLANK = " "
  26. /**
  27. * 手机号正则
  28. */
  29. public static String mobile = "(86-1[0-9]{10})|(861[0-9]{10})|(1[0-9]{10})|(1[0-9]{2} [0-9]{4} [0-9]{4})|(1[0-9]{6} [0-9]{4})|(1[0-9]{6}-[0-9]{4})"
  30. public static Pattern mobilePattern = Pattern.compile(mobile, 32)
  31. /**
  32. * 座机号正则
  33. */
  34. public static String phone = "(([0-9]{3,4}-)[0-9]{7,8})|([0-9]{12})|([0-9]{11})|([0-9]{10})|([0-9]{9})|([0-9]{8})|([0-9]{7})"
  35. public static Pattern phonePattern = Pattern.compile(phone, 32)
  36. /**
  37. * 邮编正则
  38. */
  39. public static String zipCode = "([0-9]{6})"
  40. public static Pattern zipCodePattern = Pattern.compile(zipCode, 32)
  41. def excludeKeys = [
  42. "自治区直辖县级行政区划",
  43. "省直辖县级行政区划",
  44. "联系人手机号码",
  45. "不代收货款",
  46. "所在地区",
  47. "详细地址",
  48. "收货地址",
  49. "手机号码",
  50. "发件人",
  51. "手机号",
  52. "收货人",
  53. "收件人",
  54. "不代收",
  55. "收货",
  56. "邮编",
  57. "电話",
  58. "电话",
  59. "地址",
  60. ":",
  61. ":",
  62. ";", ";", ",", ",", "。", "、"
  63. ]
  64. //省份有些简称,搜索省份时,可以去掉下面这些词再搜索一次,比如内蒙古自治区,可能简称为内蒙
  65. public Set<String> provinceKeys = new LinkedHashSet<>(Arrays.asList("特别行政区", "古自治区", "维吾尔自治区", "壮族自治区", "回族自治区", "自治区", "省省直辖", "省", "市"))
  66. public Set<String> cityKeys = new LinkedHashSet<>(Arrays.asList("布依族苗族自治州", "苗族侗族自治州", "藏族羌族自治州", "哈尼族彝族自治州", "壮族苗族自治州", "傣族景颇族自治州", "蒙古族藏族自治州",
  67. "傣族自治州", "白族自治州", "藏族自治州", "彝族自治州", "回族自治州", "蒙古自治州", "朝鲜族自治州", "地区", "哈萨克自治州", "盟", "市"))
  68. public Set<String> countyKeys = new LinkedHashSet<>(Arrays.asList("满族自治县", "满族蒙古族自治县", "蒙古族自治县", "朝鲜族自治县",
  69. "回族彝族自治县", "彝族回族苗族自治县", "彝族苗族自治县", "土家族苗族自治县", "布依族苗族自治县", "苗族布依族自治县",
  70. "彝族傣族自治县", "傣族彝族自治县", "仡佬族苗族自治县", "黎族苗族自治县", "苗族侗族自治县", "哈尼族彝族傣族自治县", "哈尼族彝族自治县",
  71. "彝族哈尼族拉祜族自治县", "傣族拉祜族佤族自治县", "傣族佤族自治县", "拉祜族佤族布朗族傣族自治县", "苗族瑶族傣族自治县", "彝族回族自治县",
  72. "独龙族怒族自治县", "保安族东乡族撒拉族自治县", "回族土族自治县", "撒拉族自治县", "哈萨克自治县", "塔吉克自治县",
  73. "回族自治县", "畲族自治县", "土家族自治县", "布依族自治县", "苗族自治县", "瑶族自治县", "侗族自治县", "水族自治县", "傈僳族自治县",
  74. "仫佬族自治县", "毛南族自治县", "黎族自治县", "羌族自治县", "彝族自治县", "藏族自治县", "纳西族自治县", "裕固族自治县", "哈萨克族自治县",
  75. "哈尼族自治县", "拉祜族自治县", "佤族自治县",
  76. "回族",
  77. "左旗", "右旗", "中旗", "后旗", "联合旗", "自治旗", "旗", "自治县",
  78. "区", "县", "市"))
  79. private Map<String, String> provinceShort = new LinkedHashMap<>()
  80. private Map<String, String> cityShort = new LinkedHashMap<>()
  81. private Map<String, String> countyShort = new LinkedHashMap<>()
  82. private Map<String, String> PROVINCES = new LinkedHashMap<String, String>()
  83. private Map<String, String> CITIES = new LinkedHashMap<String, String>()
  84. private Map<String, String> COUNTIES = new LinkedHashMap<String, String>()
  85. @Resource(name = "APP_HOME")
  86. private String appHome
  87. @Override
  88. String scriptName() {
  89. return "地址解析为省市区联系人电话"
  90. }
  91. @Override
  92. ERPModule module() {
  93. return ERPModule.ADDRESSPARSER
  94. }
  95. @Override
  96. void start(long supplierCode) {
  97. def jsonSlurper = new JsonSlurper()
  98. def provicesJsonFile = new File(appHome + File.separator + "conf" + File.separator + "addressdata" + File.separator + "provices.json")
  99. def provicesJsonArray = jsonSlurper.parse(provicesJsonFile)
  100. provicesJsonArray.each { it ->
  101. PROVINCES.put(it["code"] as String, it["name"] as String)
  102. }
  103. def citiesJsonFile = new File(appHome + File.separator + "conf" + File.separator + "addressdata" + File.separator + "cities.json")
  104. def citiesJsonArray = jsonSlurper.parse(citiesJsonFile)
  105. citiesJsonArray.each { it ->
  106. CITIES.put(it["code"] as String, it["name"] as String)
  107. }
  108. def countiesJsonFile = new File(appHome + File.separator + "conf" + File.separator + "addressdata" + File.separator + "counties.json")
  109. def countiesJsonArray = jsonSlurper.parse(countiesJsonFile)
  110. countiesJsonArray.each { it ->
  111. COUNTIES.put(it["code"] as String, it["name"] as String)
  112. }
  113. for (Map.Entry<String, String> entry : PROVINCES.entrySet()) {
  114. String result = entry.getValue()
  115. for (String key : provinceKeys) {
  116. result = result.replace(key, "")
  117. }
  118. provinceShort.put(entry.getKey(), result)
  119. }
  120. for (Map.Entry<String, String> entry : CITIES.entrySet()) {
  121. String result = entry.getValue()
  122. if (result.length() > 2) {
  123. for (String key : cityKeys) {
  124. result = result.replace(key, "")
  125. }
  126. cityShort.put(entry.getKey(), result)
  127. }
  128. }
  129. for (Map.Entry<String, String> entry : COUNTIES.entrySet()) {
  130. String result = entry.getValue()
  131. if ("雨花台区" == result) {
  132. result = "雨花区"
  133. } else if ("郑州高新技术产业开发区" == result) {
  134. result = "高新区"
  135. }
  136. if (result.length() > 2) {
  137. for (String key : countyKeys) {
  138. if (result.indexOf(key) > 0) {
  139. result = result.replace(key, "")
  140. }
  141. }
  142. countyShort.put(entry.getKey(), result)
  143. }
  144. }
  145. }
  146. @Override
  147. RetResult<List<ParseAreaResult>> executeList(ProcessStringItem source) {
  148. List<ParseAreaResult> results = parse(source.getItemValue(), false)
  149. return RetResult.<List<ParseAreaResult>> successT().result(results)
  150. }
  151. List<ParseAreaResult> parse(String address, boolean parseAll) {
  152. String inputAddress = address
  153. ParseAreaResult extraResult = new ParseAreaResult()
  154. //地址清洗 替换特殊字符,解析手机,座机,邮编,格式化多余空格
  155. address = cleanAddress(address)
  156. //提取手机号
  157. address = parseMobile(address, extraResult)
  158. //提取电话号码
  159. address = parsePhone(address, extraResult)
  160. //提取邮编
  161. address = parseZipCode(address, extraResult)
  162. address = address.replaceAll(" {2,}", BLANK)
  163. // logger.info(address)
  164. String memo = parseMemo(inputAddress)
  165. //解析地址
  166. List<ParseAreaResult> results = parseAddress(address, parseAll)
  167. //将解析的地址结果重新解析一次名称
  168. if ((results != null) && (!results.isEmpty())) {
  169. results.each { r ->
  170. r.setMobile(extraResult.getMobile())
  171. r.setPhone(extraResult.getPhone())
  172. r.setZipCode(extraResult.getZipCode())
  173. parseName(r, 11)
  174. }
  175. } else {
  176. parseName(extraResult, 11)
  177. results.add(extraResult)
  178. }
  179. results.each { it.memo = memo }
  180. return results
  181. }
  182. private String cleanAddress(String address) {
  183. address = address.replaceAll("-", EMPTY)
  184. address = address.replaceAll("\\[.*?]", "")
  185. address = address.replaceAll("【.*?】", "")
  186. for (String key : excludeKeys) {
  187. address = address.replaceAll(key, " ")
  188. }
  189. //有一段替换代码groovy执行不了,改成java执行
  190. return ERPUtils.formatParseAddress(address)
  191. }
  192. /**
  193. * 提取手机号码
  194. */
  195. private static String parseMobile(String address, ParseAreaResult result) {
  196. String mobile = patternGetStr(mobilePattern, address, 0)
  197. if (StringUtils.isNotEmpty(mobile)) {
  198. result.setMobile(mobile)
  199. return address.replaceAll(mobile, BLANK)
  200. }
  201. return address
  202. }
  203. /**
  204. * 提取座机号码
  205. */
  206. private static String parsePhone(String address, ParseAreaResult result) {
  207. String phone = patternGetStr(phonePattern, address, 0)
  208. if (StringUtils.isNotEmpty(phone)) {
  209. result.setPhone(phone)
  210. return address.replaceAll(phone, BLANK)
  211. }
  212. return address
  213. }
  214. /**
  215. * 提取邮编
  216. */
  217. private static String parseZipCode(String address, ParseAreaResult result) {
  218. String zipCode = patternGetStr(zipCodePattern, address, 0)
  219. if (StringUtils.isNotEmpty(zipCode)) {
  220. result.setZipCode(zipCode)
  221. return address.replaceAll(zipCode, BLANK)
  222. }
  223. return address
  224. }
  225. /**
  226. * 提取名称
  227. */
  228. private static void parseName(ParseAreaResult result, int maxLen) {
  229. //设置result
  230. if (StringUtils.isEmpty(result.getName())) {
  231. //List<String> list = Stream.of(result.getDetails().split(" ")).collect(Collectors.toCollection(ArrayList::new));
  232. if (StringUtils.isNotBlank(result.getDetails())) {
  233. List<String> list = result.getDetails().split(" ") as List
  234. AtomicReference<String> name = new AtomicReference<>("")
  235. AtomicInteger index = new AtomicInteger(-1)
  236. list.each { s ->
  237. index.addAndGet(1)
  238. if (StringUtils.isNotEmpty(s) && s.length() < maxLen) {
  239. if (StringUtils.isEmpty(name.get()) || name.get().length() > s.length()) {
  240. name.set(s)
  241. }
  242. }
  243. }
  244. if (StringUtils.isNotEmpty(name.get())) {
  245. result.setName(name.get().trim())
  246. list.remove(index.get())
  247. result.setDetails(list.stream().collect(Collectors.joining(" ")))
  248. }
  249. } else {
  250. result.setName("")
  251. }
  252. }
  253. }
  254. private static String parseMemo(String address) {
  255. def result = []
  256. def matcher = address =~ /([\[【])(.*?)([]】])/
  257. matcher.each { result << it[2] }
  258. return result.join(",")
  259. }
  260. private static String patternGetStr(Pattern pattern, CharSequence content, int groupIndex) {
  261. if (null != content && null != pattern) {
  262. Matcher matcher = pattern.matcher(content)
  263. return matcher.find() ? matcher.group(groupIndex) : null
  264. } else {
  265. return null
  266. }
  267. }
  268. private List<ParseAreaResult> parseAddress(String address, boolean parseAll) {
  269. List<ParseAreaResult> list = new ArrayList<>()
  270. list.addAll(0, parseByProvince(address))
  271. if (parseAll || list.isEmpty() || !list.get(0).getParse()) {
  272. list.addAll(0, parseByCity(address))
  273. if (parseAll || list.isEmpty() || !list.get(0).getParse()) {
  274. list.addAll(0, parseByCounty(address))
  275. }
  276. }
  277. // 可信度排序
  278. list.sort { a, b ->
  279. int aNameLength = StringUtils.isEmpty(a.name) ? -1 : a.getName().length()
  280. int bNameLength = StringUtils.isEmpty(b.getName()) ? -1 : b.getName().length()
  281. return a.getParse() && !b.getParse() ? -1 : !a.getParse() && b.getParse() ? 1 : aNameLength > bNameLength ? 1 : aNameLength < bNameLength ? -1 : 0
  282. }
  283. return list
  284. }
  285. /**
  286. * 通过区解析地址
  287. * @param addressBase
  288. * @return
  289. */
  290. private List<ParseAreaResult> parseByCounty(String addressBase) {
  291. List<ParseAreaResult> results = new ArrayList<>()
  292. ParseAreaResult result = new ParseAreaResult()
  293. result.setType("parseByCounty")
  294. String address = addressBase
  295. for (Map.Entry<String, String> entry : COUNTIES.entrySet()) {
  296. String countyCode = entry.getKey()
  297. String countyName = entry.getValue()
  298. int index = address.indexOf(countyName)
  299. String shortCounty = index > -1 ? "" : countyShort.get(countyCode)
  300. int countyLength = StringUtils.isNotEmpty(shortCounty) ? shortCounty.length() : countyName.length()
  301. if (StringUtils.isNotEmpty(shortCounty)) {
  302. index = address.indexOf(shortCounty)
  303. }
  304. if (index > -1) {
  305. if (countyCode.contains("-")) {
  306. countyCode = countyCode.split("-")[0]
  307. }
  308. result.setCode(countyCode)
  309. result.setCounty(countyName)
  310. result.setCountyCode(countyCode)
  311. String cityCode = countyCode.substring(0, 4) + "00"
  312. String city = CITIES.get(cityCode)
  313. result.setCityCode(cityCode)
  314. result.setCity(city)
  315. String provinceCode = countyCode.substring(0, 2) + "0000"
  316. String province = PROVINCES.get(provinceCode)
  317. result.setProvinceCode(provinceCode)
  318. result.setProvince(province)
  319. String leftAddress = address.substring(0, index)
  320. String _provinceName = "", _cityName = ""
  321. if (StringUtils.isNotEmpty(leftAddress)) {
  322. _provinceName = province
  323. int _index = leftAddress.indexOf(_provinceName)
  324. if (_index == -1) {
  325. _provinceName = provinceShort.get(countyCode.substring(0, 2) + "0000")
  326. _index = leftAddress.indexOf(_provinceName)
  327. if (_index == -1) {
  328. _provinceName = ""
  329. }
  330. }
  331. if (StringUtils.isNotEmpty(_provinceName)) {
  332. leftAddress = leftAddress.replaceAll(_provinceName, "")
  333. }
  334. _cityName = city
  335. _index = leftAddress.indexOf(_cityName)
  336. if (_index == -1) {
  337. _cityName = cityShort.get(countyCode.substring(0, 4) + "00")
  338. _index = (StringUtils.isBlank(_cityName)) ? -1 : leftAddress.indexOf(_cityName)
  339. if (_index == -1) {
  340. _cityName = ""
  341. }
  342. }
  343. if (StringUtils.isNotEmpty(_cityName)) {
  344. leftAddress = leftAddress.replaceAll(_cityName, "")
  345. }
  346. if (StringUtils.isNotEmpty(leftAddress)) {
  347. result.setName(leftAddress.trim())
  348. }
  349. }
  350. address = address.substring(index + countyLength)
  351. if (StringUtils.isNotEmpty(_provinceName) || StringUtils.isNotEmpty(_cityName)) {
  352. result.setParse(true)
  353. break
  354. } else {
  355. //如果没有识别到地区 缓存本次结果,并重置数据
  356. ParseAreaResult newResult = new ParseAreaResult()
  357. newResult.mobile = result.mobile
  358. newResult.phone = result.phone
  359. newResult.zipCode = result.zipCode
  360. newResult.province = result.province
  361. newResult.provinceCode = result.provinceCode
  362. newResult.city = result.city
  363. newResult.cityCode = result.cityCode
  364. newResult.county = result.county
  365. newResult.countyCode = result.countyCode
  366. newResult.address = result.address
  367. newResult.details = result.details
  368. newResult.code = result.code
  369. newResult.name = result.name
  370. newResult.type = result.type
  371. newResult.parse = result.parse
  372. newResult.setDetails(address.trim())
  373. results.add(0, newResult)
  374. result.clean()
  375. address = addressBase
  376. }
  377. }
  378. }
  379. if (StringUtils.isNotEmpty(result.getCode())) {
  380. result.setDetails(address.trim())
  381. results.add(0, result)
  382. }
  383. return results
  384. }
  385. /**
  386. * 通过省解析地址
  387. * @param addressBase
  388. * @return
  389. */
  390. private List<ParseAreaResult> parseByCity(String addressBase) {
  391. List<ParseAreaResult> results = new ArrayList<>()
  392. ParseAreaResult result = new ParseAreaResult()
  393. result.setType("parseByCity")
  394. String address = addressBase
  395. for (Map.Entry<String, String> entry : CITIES.entrySet()) {
  396. String cityCode = entry.getKey()
  397. String cityName = entry.getValue()
  398. int index = address.indexOf(cityName)
  399. String shortCity = index > -1 ? "" : cityShort.get(cityCode)
  400. int cityLength = StringUtils.isNotEmpty(shortCity) ? shortCity.length() : cityName.length()
  401. if (StringUtils.isNotEmpty(shortCity)) {
  402. index = address.indexOf(shortCity)
  403. }
  404. if (index > -1) {
  405. result.setCode(cityCode)
  406. result.setCity(cityName)
  407. result.setCityCode(cityCode)
  408. String provinceCode = cityCode.substring(0, 2) + "0000"
  409. String province = PROVINCES.get(provinceCode)
  410. result.setProvinceCode(provinceCode)
  411. result.setProvince(province)
  412. String leftAddress = address.substring(0, index)
  413. String _provinceName = ""
  414. if (StringUtils.isNotEmpty(leftAddress)) {
  415. _provinceName = province
  416. int _index = leftAddress.indexOf(_provinceName)
  417. if (_index == -1) {
  418. _provinceName = provinceShort.get(cityCode.substring(0, 2) + "0000")
  419. _index = leftAddress.indexOf(_provinceName)
  420. if (_index == -1) {
  421. _provinceName = ""
  422. }
  423. }
  424. if (StringUtils.isNotEmpty(_provinceName)) {
  425. leftAddress = leftAddress.replace(_provinceName, "")
  426. }
  427. if (StringUtils.isNotEmpty(leftAddress)) {
  428. result.setName(leftAddress)
  429. }
  430. }
  431. address = address.substring(index + cityLength)
  432. address = parseAreaByCity(address, result)
  433. if (StringUtils.isNotEmpty(_provinceName) || StringUtils.isNotEmpty(result.getCounty())) {
  434. result.setParse(true)
  435. break
  436. } else {
  437. //如果没有识别到地区 缓存本次结果,并重置数据
  438. ParseAreaResult newResult = new ParseAreaResult()
  439. newResult.mobile = result.mobile
  440. newResult.phone = result.phone
  441. newResult.zipCode = result.zipCode
  442. newResult.province = result.province
  443. newResult.provinceCode = result.provinceCode
  444. newResult.city = result.city
  445. newResult.cityCode = result.cityCode
  446. newResult.county = result.county
  447. newResult.countyCode = result.countyCode
  448. newResult.address = result.address
  449. newResult.details = result.details
  450. newResult.code = result.code
  451. newResult.name = result.name
  452. newResult.type = result.type
  453. newResult.parse = result.parse
  454. newResult.setDetails(address.trim())
  455. results.add(0, newResult)
  456. result.clean()
  457. address = addressBase
  458. }
  459. }
  460. }
  461. if (StringUtils.isNotEmpty(result.getCode())) {
  462. result.setDetails(address.trim())
  463. results.add(0, result)
  464. }
  465. return results
  466. }
  467. /**
  468. * 通过省解析地址
  469. * @param addressBase
  470. * @return
  471. */
  472. private List<ParseAreaResult> parseByProvince(String addressBase) {
  473. List<ParseAreaResult> results = new ArrayList<>()
  474. ParseAreaResult result = new ParseAreaResult()
  475. result.setType("parseByProvince")
  476. String address = addressBase
  477. for (Map.Entry<String, String> entry : PROVINCES.entrySet()) {
  478. String code = entry.getKey()
  479. String province = entry.getValue()
  480. int index = address.indexOf(province)
  481. String shortProvince = index > -1 ? "" : provinceShort.get(code)
  482. int provinceLength = StringUtils.isNotEmpty(shortProvince) ? shortProvince.length() : province.length()
  483. if (StringUtils.isNotEmpty(shortProvince)) {
  484. index = address.indexOf(shortProvince)
  485. }
  486. if (index > -1) {
  487. if (index > 0) {
  488. result.setName(address.substring(0, index).trim())
  489. address = address.substring(index).trim()
  490. }
  491. result.setCode(code)
  492. result.setProvince(province)
  493. result.setProvinceCode(code)
  494. String _address = address.substring(provinceLength)
  495. if (StringUtils.isNotBlank(_address)) {
  496. if (!_address.startsWith("市") || _address.indexOf(province) > -1) {
  497. address = _address
  498. }
  499. }
  500. //如果是用短名匹配的 要替换省关键字
  501. if (StringUtils.isNotEmpty(shortProvince)) {
  502. for (String key : provinceKeys) {
  503. if (address.indexOf(key) == 0) {
  504. address = address.substring(key.length())
  505. }
  506. }
  507. }
  508. String __address = parseCityByProvince(address, result)
  509. if (StringUtils.isEmpty(result.getCity())) {
  510. __address = parseCountyByProvince(address, result)
  511. }
  512. if (StringUtils.isNotEmpty(result.getCity())) {
  513. address = __address
  514. result.setParse(true)
  515. break
  516. } else {
  517. //如果没有识别到地区 缓存本次结果,并重置数据
  518. ParseAreaResult newResult = new ParseAreaResult()
  519. newResult.mobile = result.mobile
  520. newResult.phone = result.phone
  521. newResult.zipCode = result.zipCode
  522. newResult.province = result.province
  523. newResult.provinceCode = result.provinceCode
  524. newResult.city = result.city
  525. newResult.cityCode = result.cityCode
  526. newResult.county = result.county
  527. newResult.countyCode = result.countyCode
  528. newResult.address = result.address
  529. newResult.details = result.details
  530. newResult.code = result.code
  531. newResult.name = result.name
  532. newResult.type = result.type
  533. newResult.parse = result.parse
  534. newResult.setDetails(address.trim())
  535. results.add(0, newResult)
  536. result.clean()
  537. address = addressBase
  538. }
  539. }
  540. }
  541. //设置code
  542. if (StringUtils.isNotEmpty(result.getCode())) {
  543. result.setDetails(address.trim())
  544. results.add(0, result)
  545. }
  546. return results
  547. }
  548. private String parseCountyByProvince(String address, ParseAreaResult result) {
  549. Map<String, String> counties = getTargetsByCode(AreaEnum.COUNTY, result.getCode())
  550. for (Map.Entry<String, String> entry : counties.entrySet()) {
  551. String countyCode = entry.getKey()
  552. String countyName = entry.getValue()
  553. int index = address.indexOf(countyName)
  554. String shortCounty = index > -1 ? "" : countyShort.get(countyCode)
  555. int countyLength = StringUtils.isNotEmpty(shortCounty) ? shortCounty.length() : countyName.length()
  556. if (StringUtils.isNotEmpty(shortCounty)) {
  557. index = address.indexOf(shortCounty)
  558. }
  559. if (index > -1 && index < 6) {
  560. if (countyCode.contains("-")) {
  561. countyCode = countyCode.split("-")[0]
  562. }
  563. result.setCode(countyCode)
  564. result.setCounty(countyName)
  565. result.setCountyCode(countyCode)
  566. String cityCode = countyCode.substring(0, 4) + "00"
  567. String cityName = CITIES.get(cityCode)
  568. result.setCity(cityName)
  569. result.setCityCode(cityCode)
  570. address = address.substring(index + countyLength)
  571. if (StringUtils.isNotEmpty(shortCounty)) {
  572. for (String key : countyKeys) {
  573. if (address.indexOf(key) == 0) {
  574. address = address.substring(key.length())
  575. }
  576. }
  577. }
  578. break
  579. }
  580. }
  581. return address
  582. }
  583. /**
  584. * 通过省解析城市信息
  585. * @param address
  586. * @param result
  587. * @return
  588. */
  589. private String parseCityByProvince(String address, ParseAreaResult result) {
  590. Map<String, String> cities = getTargetsByCode(AreaEnum.CITY, result.getCode())
  591. for (Map.Entry<String, String> entry : cities.entrySet()) {
  592. String cityCode = entry.getKey()
  593. String cityName = entry.getValue()
  594. int index = address.indexOf(cityName)
  595. String shortCity = index > -1 ? "" : cityShort.get(cityCode)
  596. int cityLength = StringUtils.isNotEmpty(shortCity) ? shortCity.length() : cityName.length()
  597. if (StringUtils.isNotEmpty(shortCity)) {
  598. index = address.indexOf(shortCity)
  599. }
  600. if (index > -1 && index < 3) {
  601. result.setCode(cityCode)
  602. result.setCity(cityName)
  603. result.setCityCode(cityCode)
  604. address = address.substring(index + cityLength)
  605. //如果是用短名匹配的 要替换市关键字
  606. if (StringUtils.isNotEmpty(shortCity)) {
  607. String finalAddress = address
  608. for (String key : cityKeys) {
  609. if (address.indexOf(key) == 0 && !StringUtils.equals(key, "市")) {
  610. //排除几个会导致异常的解析
  611. boolean anyMatch = Stream.of("市北区", "市南区", "市中区", "市辖区").anyMatch { v -> finalAddress.indexOf(v) == 0 }
  612. if (!anyMatch) {
  613. address = address.substring(key.length())
  614. }
  615. }
  616. }
  617. }
  618. address = parseAreaByCity(address, result)
  619. break
  620. }
  621. }
  622. return address
  623. }
  624. /**
  625. * 通过城市解析地区信息
  626. * @param address
  627. * @param result
  628. * @return
  629. */
  630. private String parseAreaByCity(String address, ParseAreaResult result) {
  631. Map<String, String> counties = getTargetsByCode(AreaEnum.COUNTY, result.getCode())
  632. for (Map.Entry<String, String> entry : counties.entrySet()) {
  633. String countyCode = entry.getKey()
  634. String countyName = entry.getValue()
  635. int index = address.indexOf(countyName)
  636. String shortCounty = index > -1 ? "" : countyShort.get(countyCode)
  637. int countyLength = StringUtils.isNotEmpty(shortCounty) ? shortCounty.length() : countyName.length()
  638. if (StringUtils.isNotEmpty(shortCounty)) {
  639. index = address.indexOf(shortCounty)
  640. }
  641. if (index > -1 && index < 3) {
  642. if (countyCode.contains("-")) {
  643. countyCode = countyCode.split("-")[0]
  644. }
  645. result.setCode(countyCode)
  646. result.setCounty(countyName)
  647. result.setCountyCode(countyCode)
  648. address = address.substring(index + countyLength)
  649. if (StringUtils.isNotEmpty(shortCounty)) {
  650. for (String key : countyKeys) {
  651. if (address.indexOf(key) == 0) {
  652. address = address.substring(key.length())
  653. }
  654. }
  655. }
  656. break
  657. }
  658. }
  659. return address
  660. }
  661. /**
  662. * 通过编码获取省市集合对象
  663. *
  664. * @param target 省,市枚举
  665. * @param code 编码,为地区,市,省
  666. * @return 地址对象
  667. */
  668. private Map<String, String> getTargetsByCode(AreaEnum target, String code) {
  669. Map<String, String> targets = null
  670. if (AreaEnum.PROVINCE == target) {
  671. String provinceCode = code.substring(0, 2)
  672. targets = putTargets(provinceCode, PROVINCES)
  673. } else if (AreaEnum.CITY == target) {
  674. String provinceCode = code.substring(0, 2)
  675. targets = putTargets(provinceCode, CITIES)
  676. } else if (AreaEnum.COUNTY == target) {
  677. if ("00" == code.substring(2, 4)) {
  678. String provinceCode = code.substring(0, 2)
  679. targets = putTargets(provinceCode, COUNTIES)
  680. } else {
  681. String cityCode = code.substring(0, 4)
  682. targets = putTargets(cityCode, COUNTIES)
  683. }
  684. }
  685. return targets
  686. }
  687. /**
  688. * 查找sources中key以preCode开头的对象,并存储到targets中
  689. * 其中break必须要依赖于数据是有一定顺序的,必须targets记录在同一范围,中间不能插入其他对象
  690. *
  691. * @param preCode
  692. * @param sources
  693. */
  694. private static Map<String, String> putTargets(String preCode, Map<String, String> sources) {
  695. Map<String, String> targets = new LinkedHashMap<>()
  696. for (Map.Entry<String, String> entry : sources.entrySet()) {
  697. int index = entry.getKey().indexOf(preCode)
  698. if (index == 0) {
  699. targets.put(entry.getKey(), entry.getValue())
  700. } else if (targets.size() > 0 && index != 0) {
  701. break
  702. }
  703. }
  704. return targets
  705. }
  706. }