为什么同一个房源,在A网站上标1,750欧,到B网站却成了1,700欧“起”?这只是冰山一角。搭建都柏林租房比较层时,我原以为数据聚合是关卡,后来发现,抓取数据几乎是最简单的环节——真正的硬骨头,是把这些五花八门的信息扭成一把能直接比较的尺子。

表面上看,把多个租房门户的房源拢到一起展示就行。Daft.ie、Rent.ie这些主流网站的页面结构虽有差异,但只要针对每个源写一套提取脚本,蕞初的原始记录就能到手。聚合这件事,说穿了就是几行解析逻辑。但问题不在这里,而在于下一步:当两条记录其实说的是同一套房、同一个价格,却因为书写方式不同,系统根本认不出它们是同一件事。

打开网易新闻 查看精彩图片

拿价格来说,就这一个字段,你会在不同来源见到无数种写法:“€1,750 per month”“1750 pcm”“£1750/month”(有些英国注册的平台对都柏林的房源仍用英镑标注)、“From €1,700”“Price on application”,甚至只有孤零零的数字“1,750”,要靠上下文猜测币种。还有的标“€1,750 per month + utilities”,你得决定是剥掉公用事业费的部分,还是把它标记为特殊价格。卧室数量同样混乱:“2 bed”“2 bedroom”“Two bedrooms”“2BR”“2+1”(两间卧室加一个杂物间)——有的源干脆不写卧室数,只用物业类型来替代。

打开网易新闻 查看精彩图片

更让人头疼的是地区和位置。不同源用的地理分类完全是各说各话:一家用都柏林邮政编码(D4、D6、D6W),另一家用社区名(Rathmines、Ranelagh、Rathgar),还有的只给街道地址,其他一概缺省。偶尔出现“Ranelagh, Dublin 6”这样含混的组合,和另一个源里的“Dublin 6”其实是同一片区域,但要让代码自动认出这种等价关系,远非一句简单的字符串匹配。

站在“标准化没必要”的角度看,把各平台原本的样子直接展示给用户似乎最省事。你甚至可以在页脚加一句“信息来自各源,请自行核对”,轻松甩锅。但是从使用体验上,这就等同于把整理数据的责任推给每个看房的人。而反过来看,如果想让用户一眼看出两套房的性价比,想让筛选和排序靠谱,标准化就不是锦上添花,而是地基。

我在HomeScout项目里采用的方案,是先给每个来源做一个定制提取器,输出的是只经过轻量清洗的原始记录(去掉HTML标签、整理空字符、解码转义符),不做任何语义解释。然后,紧接着一个专门的标准化步骤,把原始记录转成带类型标记、格式统一的标准记录。这个过程对价格、卧室数、区域分别处理,核心不是简单的正则替换,而是一套带着判别逻辑的小管道。

打开网易新闻 查看精彩图片

以价格标准化为例,我写了一个normalize_price函数,它返回两个元素:月租金欧元数值和价格限定词——“exact”(精确价)、“from”(起售价)、“on_application”(联系获取),还有“unknown”。这个函数一上来就判断是否属于“价格待询”模式,是就直接打标。否则,提取数字,过滤逗号等非数字符号。接着还要识别周租标识,把周租自动换算为月租,因为爱尔兰市场习惯用月租,原始记录里偶尔蹦出的周租会造成至少30%的偏差。那些“from”前缀也会被抓出来,因为“起售价”与“确切月租”在对比视图里必须区别显示,否则会误导价格排序。

卧室数的处理用了一套文本到数字的映射,同时把“+1”的那种杂物间单独标记,这样用户可以选择只看实际卧室,还是把兼做书房的杂物间也算进去。地理位置部分才是真正耗时的一关。我的做法是先尝试从原始地址字段里抽出都柏林的邮编,如果抽得到,就把提取到的邮编作为主键;如果抽不到,就把社区名、街道信息清洗后,去匹配一个预先维护的邮编-社区映射表。对那些社区名和邮编都不完整的记录,就根据街道地址来补全。最后所有记录都统一到邮编层级,确保不同的写法和来源能对上号。

回过头看,这套标准化流水线最吃力的地方,不是代码逻辑,而是对数据里那些“沉默的约定”的识别。比如英镑标价、不含税的价格、“2+1”背后那个含糊的房间功能——这些东西如果不显式地写成规则,就会悄无声息地扭曲比较结果。聚合只是给了你一堆料,标准化才让这堆料变得可比、可筛,最终让用户不必自己去做信息侦探。