Pythonr基于selenium如何实现不同商城的商品价格差异分析系统
前言标题里的「Pythonr」是原文的笔误正确写法是「Python」但本文的标题按要求原样保留。比这个笔误更值得先说的是这套需求本身的前提问题。「用 Selenium 去各个商城抓商品价格然后做价格差异分析」——这个设想看起来顺理成章实际上前半段几乎行不通而且不合规。原因有三层。第一层是登录墙多数商城的商品详情、价格往往要求登录后才能完整查看交易类数据更是绑定账号。第二层是风控与反自动化平台普遍会识别自动化访问行为特征、频率、会话校验把它当成异常流量处理轻则限流、返回不完整页面重则封禁账号。第三层是合规平台的服务条款通常明确禁止未经许可的自动化采集你即使技术上做得到也未必被允许做。所以本文给出的正确路径是只要平台提供官方开放平台 API就通过它授权取数——申请开发者账号、按文档授权的接口、遵守它的调用频率与数据使用条款。这条路拿到的是结构化、稳定、合规的数据。如果拿不到授权那就不做真实站点的采集而是用你自己构造的本地数据完整演示「价格差异分析」这后半段——多平台价格对齐、比价表、涨跌与离散度统计。本文全部基于本地构造数据不含任何绕过登录、验证码、风控的做法。先明确一件事分析能力是可以独立练习和交付的采集权限则取决于平台。把两者分开需求就成立了。一、两种取数路径以及本文的取舍把取数这件事的选择摊开看路径前提合规性本文是否演示官方开放平台 API取得开发者授权高按条款用讲思路不写具体接口手工/人工整理的价格表你有权使用该数据取决于数据来源演示分析部分自己构造的本地数据无无风险完整演示直接抓商城页面——通常违反条款不做仅说明为何不可行本文选第三条自己构造的本地数据。这不是退而求其次——价格差异分析的核心算法对齐、比价、统计与数据来自哪里无关。你在本地把方法跑通将来真拿到官方数据把数据源一换即可。反之如果一开始就把精力花在「怎么把页面抓下来」上方向就偏了。那么 Selenium 在这套系统里还有什么正当位置有的。当你对自己拥有管理权的内部系统做 UI 自动化比如企业内部采购后台的价格核对或者当你获得了平台明确许可做 UI 层操作时Selenium 才派得上用场。它的角色是「驱动一个受你控制的浏览器」不是「绕过别人的防护」。二、数据结构设计先想清楚「可比」做多平台比价第一个坎不是算法而是商品的对齐同一个商品在不同平台叫法不同、编号不同、规格单位不同。不解决对齐价格根本没法比。本文的数据结构设计成「一个商品在一个平台上的一条报价」三个关键字段# 适用于 Python 3.8# 本地构造数据不指向任何真实站点SAMPLE_ROWS [{sku: SKU-1001, platform: 平台A, title: 无线鼠标 静音版,price: 79.0, date: 2026-03-01},{sku: SKU-1001, platform: 平台B, title: 无线鼠标静音,price: 85.0, date: 2026-03-01},{sku: SKU-1001, platform: 平台C, title: 静音无线鼠标,price: 76.5, date: 2026-03-01},{sku: SKU-1002, platform: 平台A, title: 机械键盘 87键,price: 259.0, date: 2026-03-01},{sku: SKU-1002, platform: 平台B, title: 机械键盘87键,price: 249.0, date: 2026-03-01},]关键是那个sku它是你自己的对齐主键把「无线鼠标 静音版」「无线鼠标静音」「静音无线鼠标」这三种叫法归到同一个SKU-1001名下。现实中这个对齐往往需要一张映射表每个平台的关键词、规格到你的 sku 的对照这正是比价系统里最费功夫、也最有价值的部分。对齐的原则是用稳定的标识而不是模糊的标题匹配。标题匹配去掉空格、统一大小写后比较只能作为辅助型号、规格、容量这些确定性字段才是主键。三、价格对齐与比价表对齐之后把同一 sku 在各平台的价格汇总起来就能算出一张比价表。# 适用于 Python 3.8from collections import defaultdictdef build_price_table(rows):按 sku 汇总各平台价格返回 {sku: {platform: price}}table defaultdict(dict)for r in rows:# 同一 sku平台 若有多条取该日最新一条示例按日期比较table[r[sku]][r[platform]] r[price]return {sku: dict(plat) for sku, plat in table.items()}def spans(table):对每个 sku 计算最高价、最低价与价差result []for sku, prices in table.items():if not prices:continuelo min(prices.values())hi max(prices.values())lo_plat [p for p, v in prices.items() if v lo]hi_plat [p for p, v in prices.items() if v hi]result.append({sku: sku,最低价: lo,最低价平台: /.join(sorted(lo_plat)),最高价: hi,最高价平台: /.join(sorted(hi_plat)),价差: round(hi - lo, 2),})return resultif __name__ __main__:t build_price_table(SAMPLE_ROWS)for row in spans(t):print(row)这张表就是「价格差异分析」最直接的产出同款商品在哪个平台最便宜、差多少。注意处理「多个平台并列最低」的情况——用列表再拼接而不是只取第一个否则报表会漏掉并列的情况这在选品决策里可能是要紧的信息。四、涨跌与离散度统计比价表只看「当前」但价格是随时间变的。真正有分析价值的是趋势涨跌和离散度各平台价格有多分散。标准库statistics就能算均值和标准差。# 适用于 Python 3.8import statisticsfrom collections import defaultdictdef price_volatility(rows):按 sku 计算各平台价格的均值、标准差与极差by_sku defaultdict(list)for r in rows:by_sku[r[sku]].append(r[price])out []for sku, prices in by_sku.items():if len(prices) 2:# 样本不足如实标注别硬算标准差out.append({sku: sku, 样本数: len(prices),均值: prices[0] if prices else None,标准差: None, 极差: 0})continueout.append({sku: sku,样本数: len(prices),均值: round(statistics.mean(prices), 2),标准差: round(statistics.stdev(prices), 2), # 样本标准差极差: round(max(prices) - min(prices), 2),})return out两个细节要点。第一statistics.stdev()算的是样本标准差除以 n-1pstdev()才是总体标准差除以 n只有一条数据时无法计算标准差应当返回None并如实标注样本不足不要拿 0 冒充「分散度为 0」。第二离散度大不等于有问题——它可能反映各平台促销节奏不同也可能反映规格没对齐好。分析结论必须结合业务判断不能只看一个数字下结论。涨跌则要把同一 sku 在不同日期的价格排好序再比较# 适用于 Python 3.8def price_change(rows):按 sku平台 找出最早与最晚报价计算涨跌series {}for r in rows:key (r[sku], r[platform])series.setdefault(key, []).append((r[date], r[price]))changes []for (sku, plat), items in series.items():items.sort(keylambda x: x[0]) # 按日期升序first_price items[0][1]last_price items[-1][1]changes.append({sku: sku, 平台: plat,首次: first_price, 最新: last_price,涨跌额: round(last_price - first_price, 2),})return changes排序依据是日期字符串——只有当日期是YYYY-MM-DD这种字典序等于时间序的格式时才成立。如果用3/1/2026这种格式字符串排序会出错必须先转成datetime.date再比。五、什么时候才轮到 Selenium回到标题。如果你确实拿到了官方授权或者操作的是你自己有管理权的内部系统那么 Selenium 可以作为取数的一环驱动一个受控浏览器在你被允许的页面上取数据。此时的写法要守住几条用显式等待而非硬睡、控制访问频率、只在你被授权的范围内操作。但要注意官方的开放平台 API 通常比 UI 自动化更适合取数——它返回结构化数据、有稳定的字段契约、有明确的频率说明不像页面那样说改就改。所以即便有授权优先级也应是「API 优先UI 自动化兜底」。至于「绕过登录墙、破解验证码、伪装正常用户来采集」本文不做也不建议做技术上的短暂成功换来的是账号封禁与法律风险性价比极低。常见坑点❌ 以为「能打开页面就能抓到价格」忽略了登录墙与风控的存在。✅ 先确认平台是否提供官方 API没有授权就不采改用自有数据。❌ 用商品标题模糊匹配来对齐不同平台的同款商品。✅ 用型号、规格等确定性字段做对齐主键标题匹配只作辅助。❌ 只取第一个最低价平台漏掉多个平台并列最低的情况。✅ 收集所有并列项再展示避免报表丢信息。❌ 只有一条价格就调statistics.stdev或算不出就填 0。✅ 样本不足时返回None并如实标注不拿 0 冒充「无波动」。❌ 用非YYYY-MM-DD的日期字符串排序涨跌算反。✅ 先把日期转成datetime.date再排序比较。❌ 离散度一大就断定「平台在乱定价」忽略规格未对齐或促销差异。✅ 把统计量当线索结合业务与数据质量一起判断。❌ 觉得「反正只是看看」就去抓真实商城页面触犯条款。✅ 分析能力用本地数据练真实数据只从官方授权渠道取。❌ 拿到官方数据接口后仍坚持用 Selenium 抓页面舍近求远。✅ API 优先UI 自动化只在无 API 且有授权时兜底。总结环节推荐做法红线取数官方 API 授权取数不绕登录/验证码/风控无授权时用自己构造的本地数据不碰真实站点对齐型号/规格做主键不靠模糊标题匹配比价均价、极差、并列最低不臆造缺失值趋势按日期排序算涨跌日期格式要可排序Selenium自有系统或已授权场景只做受控、合规的操作这个标题的两种前提——「合规取数」和「价格差异分析」——前者的可行性取决于平台授权后者的能力可以立刻开始练。正确的做法是把它们拆开分析部分今天就能用本地数据完整做出来对齐、比价、涨跌、离散度取数部分则老老实实走官方开放平台拿不到授权就不做。守住这条线系统才既站得住技术也站得住合规。