使用 Node.js 从文本文件中解析街道地址
Posted
技术标签:
【中文标题】使用 Node.js 从文本文件中解析街道地址【英文标题】:Parse street addresses from text files using Node.js 【发布时间】:2021-11-17 07:32:57 【问题描述】:我正在尝试解决这个问题,我必须将文本文件作为输入读取并使用 Node.js 创建对象数组。唯一的极端情况是有额外的空格。
输入:
西港大道 89 号 佛罗里达州彭布罗克派恩斯 33028
贝波特路 9529 号 欧克莱尔,威斯康星州 54701
维克赫斯特街 9957 号 套房 42 佛罗里达州博尼塔斯普林斯 34135
富兰克林大道 8233 号 威斯康星州尼纳 54956
输出:
[
address1: '89 Westport Ave.',
address2: null,
city: 'Pembroke Pines',
state: 'FL',
zip: '33028' ,
address1: '9529 Bayport Rd.',
address2: null,
city: 'Eau Claire',
state: 'WI',
zip: '54701' ,
address1: '9957 Wakehurst Street',
address2: 'Suite 42',
city: 'Bonita Springs',
state: 'FL',
zip: '34135' ,
address1: '8233 Franklin Drive',
address2: null,
city: 'Neenah',
state: 'WI',
zip: '54956' ]
我正在尝试的代码:
const parseAddressFile = path =>
const fs = require('fs');
const readline = require('readline');
const data = readline.createInterface(
input: fs.createReadStream(path)
);
let address = address1: "",
address2: "",
city: "",
state: "",
zip: "";
const addressList = [];
data.on('line', function (line)
line = line.trim();
addressList.push(line);
// console.log(addressList);
);
function line2()
var lines = addressList.split(',');
return lines;
// console.log(line2());
data.on('close', function (line)
// array console.log(addressList);
// var Ncount = 0;
for(var x =0; x < addressList.length; x++)
// console.log(address);
// console.log(addressList[0]);
address['address1'] = addressList[x];
if (addressList[x].match('Suite 42'))
address['address2'] = 'Suite 42';
else
address['address2'] = null;
// address['address2'] = null;
address['city'] = addressList[line2(x)];
address['state'] = addressList[x];
address['zip'] = addressList[x];
console.log(address);
);
;
module.exports = parseAddressFile;
【问题讨论】:
这是一个相当复杂的自然语言处理/机器学习问题,已经有数百篇学术论文写在上面。我们不是代码编写服务:您尝试过什么,您在哪里卡住了?编辑您的问题,将您编写为 minimal reproducible example 的代码包含在内,并简要说明您编写的代码为何不符合您的要求。 感谢您的指导。我已经添加了我的代码和关于要求以及我卡在哪里的解释。 @esqew 您是否考虑过为此使用 NLP 模型?地址数据中存在极端数量的边缘情况 - 可能不值得您花时间去研究它们并为它们编码(因为它们的数量实际上数不胜数)。 唯一需要考虑的边缘情况是每个地址后面都有一些空格和空行。否则,所有文件的地址格式与上述相同。我也在考虑函数式编程,但我不确定如何逐行存储数据并创建对象数组。我在下一条评论中附上代码。 @esqew 让地址 = address1: "", address2: "", city: "", state: "", zip: "";常量地址列表 = []; data.on('line', function (line) addressList.push(line); ); data.on('close', function (line) for(var x =0; x 【参考方案1】:如果您真的,绝对,1,000% 肯定您的地址数据与您的示例数据没有实质性差异此处提供,您可以使用精心设计的 RegExp 根据您的数据所采用的隐式模式提取您需要的内容:
const addressTexts = [
`89 Westport Ave.
Pembroke Pines, FL 33028`,
`9529 Bayport Rd.
Eau Claire, WI 54701`,
`9957 Wakehurst Street
Suite 42
Bonita Springs, FL 34135`,
`8233 Franklin Drive
Neenah, WI 54956`
];
const parseAddress = addressText => /(?<address1>\d+.+?)\n(?:(?<address2>.+?(?!\d5))\n)?(?<city>[\w\s]+?),\s(?<state>[A-Z]2)\s(?<zip>\d5)/g.exec(addressText).groups;
addressTexts.forEach(ele => console.log(parseAddress(ele)));
根据您的数据实际情况,您可能需要调整模式。
【讨论】:
【参考方案2】:我已经使用 RegExp 提供了一个基本答案,如果所讨论的数据像 OP 向我们保证的那样真正干净且一致,那么它会运行得很好。但是,我对自己为此类数据编写解析器的建议是:不要。
要有效处理表示邮政地址的非结构化字符串,您必须考虑绝对荒谬的极端情况。仅在美国,就有几乎无数种“合法”方式来表达相同的确切地址。幸运的是,我们有服务和开源选项来提高必须使用这种非结构化地址数据的代码的效率。
如果您信任数据源并且只需要对地址的各个组成部分进行更基本的“分段”
使用像openvenues/libpostal
这样的库。这是机器学习模型被训练以从非结构化字符串中解析地址的高潮。他们已经为“地球上每个有人居住的国家超过 10 亿个地址”模型提供了数据,因此国际覆盖率也很高。
甚至还有official Node bindings for libpostal
相对容易设置。遵循Installation 指南后,只需使用一行代码将地址字符串传递到模型中:
var postal = require('node-postal');
postal.parser.parse_address('Barboncino 781 Franklin Ave, Crown Heights, ***lyn, NY 11238');
如果你关心地址本身的有效性
如果您需要确保在某种程度上存在与数据对应的现实生活中的地址,请使用 geocoder 服务。像谷歌、微软和其他较小的公司这样的公司许可他们的地图数据,通常是收费的。这包括提供非结构化字符串并确保您的数据与他们之前收集的真实街道地址相关联的能力。
【讨论】:
以上是关于使用 Node.js 从文本文件中解析街道地址的主要内容,如果未能解决你的问题,请参考以下文章