- 引言
在电商生态日益繁荣的今天,同一件商品往往同时出现在多个平台,价格、库存、评价却各不相同。消费者在购买前通常需要反复切换多个 App 或网页进行比价,耗时费力。对于导购类应用、价格监测工具或数据分析平台而言,如何高效地获取多平台商品信息并构建统一、结构化的商品数据库,成为一项核心工程挑战。
本文将从工程实践角度,系统介绍如何设计并实现一个商品信息聚合平台。内容涵盖整体架构设计、多平台数据抓取策略、数据清洗与标准化、统一商品数据库建模,以及比价与导购场景下的数据应用,帮助读者掌握从数据采集到业务落地的完整链路。
- 系统整体架构
商品信息聚合平台的核心目标,是将分散在不同电商平台的商品数据汇聚到统一的数据库中,并对外提供一致的查询与比价能力。整体架构通常分为四个层次:数据采集层、数据处理层、数据存储层和应用服务层。
flowchart TD
A[数据采集层] --> B[数据处理层]
B --> C[数据存储层]
C --> D[应用服务层]
A --> A1[平台A抓取任务]
A --> A2[平台B抓取任务]
A --> A3[平台C抓取任务]
B --> B1[数据清洗]
B --> B2[字段标准化]
B --> B3[商品去重与匹配]
C --> C1[商品主数据]
C --> C2[价格历史]
C --> C3[评价快照]
D --> D1[比价接口]
D --> D2[导购推荐]
D --> D3[价格监测]
数据采集层负责对接各电商平台,通过多种方式获取商品页面数据;数据处理层对原始数据进行清洗、解析和标准化,解决多平台数据格式不一致的问题;数据存储层将标准化后的数据写入统一数据库,并维护商品之间的映射关系;应用服务层则面向比价、导购、价格监测等业务场景提供数据服务。
- 多平台数据抓取策略
不同电商平台在页面结构、反爬策略、数据接口开放程度上差异很大,因此抓取策略需要因地制宜。常见的抓取方式包括开放 API、页面解析、移动端接口模拟和第三方数据服务。
3.1 开放 API 优先
部分平台提供官方开放 API,这是最稳定、合规的数据获取方式。通过申请开发者权限,可以获取商品详情、价格、库存等结构化数据。使用 API 时需要注意调用频率限制和授权机制,通常需要配置签名参数和访问令牌。
3.2 页面解析兜底
对于未开放 API 的平台,需要采用页面解析方式。通过分析商品详情页的 HTML 结构,使用 XPath 或 CSS 选择器提取关键字段。现代电商页面大量使用 JavaScript 动态渲染,直接抓取 HTML 往往无法获取完整数据,此时需要借助无头浏览器或分析页面内嵌的 JSON 数据接口。
3.3 移动端接口模拟
部分平台在移动端 App 中提供了比 Web 端更简洁的数据接口。通过抓包分析移动端请求,可以模拟 App 的请求参数和签名逻辑,获取结构化的 JSON 数据。这种方式需要处理签名算法和加密参数,维护成本相对较高。
3.4 抓取任务调度
多平台抓取需要统一的调度系统来管理任务队列、执行频率和失败重试。建议使用分布式任务队列,将不同平台的抓取任务拆分为独立的工作单元,支持按商品、按店铺或按关键词维度触发抓取。
public class CrawlTaskScheduler {
private final TaskQueue taskQueue;
private final ExecutorService executor;
public CrawlTaskScheduler(TaskQueue taskQueue, ExecutorService executor) {
this.taskQueue = taskQueue;
this.executor = executor;
}
public void submitCrawlTask(String platform, String itemId) {
CrawlTask task = new CrawlTask(platform, itemId);
taskQueue.enqueue(task);
executor.submit(() -> processTask(task));
}
private void processTask(CrawlTask task) {
try {
ProductData data = crawlerFactory.getCrawler(task.getPlatform())
.fetchProduct(task.getItemId());
messageProducer.send("product.raw", data);
} catch (Exception e) {
taskQueue.retry(task);
}
}
}
- 数据清洗与标准化
从不同平台抓取到的原始数据格式各异,字段命名、单位、数据类型都不一致,必须经过清洗和标准化才能进入统一数据库。
4.1 字段映射
各平台对同一商品属性的命名可能不同,例如「标题」「商品名称」「产品名」实际都指向同一字段。需要建立字段映射表,将不同平台的原始字段统一映射到标准字段模型上。
标准字段 平台A字段 平台B字段 平台C字段
商品标题 title item_name product_title
商品价格 price sale_price current_price
商品库存 stock inventory quantity
商品图片 image_url main_image pic_url
商品描述 description detail desc
4.2 单位与格式统一
价格单位、重量单位、日期格式等也需要统一处理。例如有的平台价格以「分」为单位,有的以「元」为单位;有的平台日期格式为时间戳,有的为字符串。标准化规则应集中配置,便于维护和调整。
4.3 数据质量校验
抓取过程中可能出现字段缺失、数值异常、图片链接失效等问题。需要建立数据质量校验规则,对关键字段进行完整性检查和合理性校验,不合格的数据进入待修复队列或直接丢弃。
- 商品去重与匹配
同一商品在不同平台可能使用不同的标题、SKU 或商品编码,如何识别并关联这些商品记录,是构建统一商品数据库的关键环节。
5.1 基于商品编码匹配
最可靠的方式是使用平台通用的商品编码进行匹配,例如国际标准商品编码(如 GTIN、UPC、EAN)。当商品存在这些编码时,可以直接建立跨平台关联关系。
5.2 基于标题相似度匹配
对于没有统一编码的商品,需要借助文本相似度算法进行匹配。通常先对标题进行分词和标准化处理,再计算相似度得分,结合品牌、型号、规格等辅助字段综合判断。
5.3 基于图片特征匹配
部分场景下,同一商品在不同平台的图片高度相似。可以通过提取图片感知哈希或深度学习特征向量,计算图片相似度作为匹配依据之一。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
def match_products(title_a, title_b):
vectorizer = TfidfVectorizer(analyzer="char_wb", ngram_range=(2, 3))
vectors = vectorizer.fit_transform([title_a, title_b])
return cosine_similarity(vectors[0], vectors[1])[0][0]
- 统一商品数据库设计
统一商品数据库需要同时支撑商品主数据管理、价格历史追踪和多平台关联查询,因此通常采用关系型数据库与搜索引擎结合的存储方案。
6.1 核心表结构
商品主表存储标准化后的商品核心信息,平台商品映射表维护统一商品与各平台原始商品之间的关联关系,价格历史表记录每次抓取到的价格快照。
CREATE TABLE product_master (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(512) NOT NULL,
brand VARCHAR(128),
category_id BIGINT,
main_image_url VARCHAR(1024),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_category (category_id),
INDEX idx_title (title)
);
CREATE TABLE platform_product_mapping (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
product_id BIGINT NOT NULL,
platform VARCHAR(64) NOT NULL,
platform_item_id VARCHAR(128) NOT NULL,
platform_url VARCHAR(1024),
price DECIMAL(10, 2),
stock INT,
raw_data JSON,
fetched_at DATETIME,
UNIQUE KEY uk_platform_item (platform, platform_item_id),
INDEX idx_product (product_id)
);
CREATE TABLE price_history (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
product_id BIGINT NOT NULL,
platform VARCHAR(64) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
fetched_at DATETIME NOT NULL,
INDEX idx_product_time (product_id, fetched_at)
);
6.2 数据更新策略
商品价格和库存是高频变动数据,需要制定合理的更新频率。热门商品可以缩短抓取间隔,冷门商品适当延长。同时要避免在平台高峰期集中抓取,防止触发反爬机制。
- 比价与导购场景应用
统一商品数据库建成后,可以支撑多种业务场景。比价场景需要快速返回同一商品在各平台的价格和优惠信息;导购场景则需要结合用户偏好和商品评分进行推荐排序。
7.1 比价查询接口
比价接口的核心是根据商品 ID 查询所有关联平台的价格信息,并按价格从低到高排序返回。为了提升查询性能,可以将平台商品映射数据缓存在 Redis 中,减少数据库压力。
public List comparePrice(Long productId) {
List products = platformProductRepository
.findByProductId(productId);
return products.stream()
.map(p -> new PriceComparisonItem(
p.getPlatform(),
p.getPrice(),
p.getPlatformUrl(),
p.getStock()))
.sorted(Comparator.comparing(PriceComparisonItem::getPrice))
.collect(Collectors.toList());
}
7.2 导购推荐逻辑
导购推荐可以综合价格优势、商品评分、销量和用户历史偏好等因素进行排序。对于价格敏感型用户,优先推荐价格最低的平台;对于品质敏感型用户,则综合评分和销量加权排序。
7.3 价格监测与预警
基于价格历史数据,可以分析商品价格走势,并在价格降至用户设定的阈值时触发通知。这一功能对价格监测类工具和购物助手类应用尤为重要。
- 反爬应对与合规注意事项
在实现多平台抓取时,必须重视合规性和技术风险。抓取行为应遵守目标平台的 robots 协议和服务条款,控制请求频率,避免对目标网站造成过大压力。
同时,应优先使用平台官方 API,减少对页面解析的依赖。对于需要登录或涉及用户隐私的数据,不应抓取和存储。在数据使用环节,也要注意遵守相关法律法规,保护消费者权益。
- 总结
构建商品信息聚合平台,核心在于打通「多平台采集、标准化处理、统一存储、业务应用」这条完整链路。采集层需要针对不同平台制定差异化策略,处理层要解决字段映射和数据质量问题,存储层要设计支持多平台关联和价格追踪的数据模型,应用层则围绕比价、导购等场景提供高效的数据服务。
在实际落地过程中,建议先以少量平台和商品品类验证整体流程,再逐步扩展平台覆盖范围和商品规模。同时要持续关注各平台接口和页面结构的变化,建立健壮的异常处理和监控告警机制,确保系统的长期稳定运行。如有任何疑问,欢迎留言探讨!