🔥 我写了个Python脚本,把全城1045座加油站的底价扒干净了——还带环比监控!

一个周末的冲动,催生了一套竞品情报系统。没花一分钱API费,纯Python,开箱即用。


引子:为什么搞这个?

上个月加油多花了80块。

我家旁边有个中石化,常年挂牌价7.98元/升。直到有一天绕路去接娃,发现隔壁壳牌直降0.3元——同一条路,差2公里,每升差3毛钱

作为一个合格的Python程序员,第一反应不是换加油站,而是:

🤔 能不能写个脚本,把全城的加油站底价扒下来?

结果一个周末过去,摊子越铺越大——从单纯爬价格,变成了竞品情报环比监控系统


一、先看成果

直接上结果,不说废话。

石家庄1045座加油站,一网打尽

共计: 1045 座
  规模经营站(三桶油+壳牌等): 263 座
  社会民营站: 782 座

品牌分布:
  民营         782座    ← 居然占了75%!
  中石化        170座
  中石油         77座
  中海油          5座
  壳牌           4座

💡 75%是民营油站——这个比例让我挺意外的。

生成的可视化Excel报表

运行一行命令:

python main.py --district-promotions 石家庄 井陉矿区

输出一个包含 4个Sheet 的专业Excel报表:

Sheet 内容 亮点
📋 优惠情报汇总 全量优惠数据 环比状态列(新增/持平/已变更)三色标记
📊 环比变化报告 本期vs上期变化明细 哪些站涨价了/降价了,一目了然
🏪 加油站明细 站基础信息 地址、电话、经纬度
📈 优惠类型统计 各类型分布 直降一骑绝尘,团购/异业合作崛起

环比状态识别效果:

本期87条 | 上期19条 | +63新增 -0过期 ~5变更

站点价格变更:
  中国石化矿区加油站: 0.30元/升 → 0.35元/升  🔺涨了!
  中国石油井陉鑫合36加油站: 0.25元/升 → 0.20元/升  🔻降了!
  ...共5条变更精准识别

📸 这里放截图:Excel报表的"优惠情报汇总"Sheet,展示环比状态列的颜色标记


二、技术方案:三步走

系统不复杂,核心就三步:

Step 1:站名录建设 — 高德API白嫖方案

import requests

API_KEY = "你的高德Key"  # 免费申请,个人开发者够用

def fetch_stations(city, district=None):
    """采集指定区县的加油站"""
    keywords = f"{city}{district or ''}加油站"
    url = "https://restapi.amap.com/v3/place/text"
    records = []
    
    for page in range(1, 21):  # 高德每页10条,上限20页=200条
        resp = requests.get(url, params={
            "key": API_KEY,
            "keywords": keywords,
            "city": city,
            "offset": 10,
            "page": page,
            "extensions": "all",
        })
        pois = resp.json().get("pois", [])
        if not pois:
            break
        for poi in pois:
            records.append({
                "name": poi["name"],
                "brand": poi.get("brand", ""),
                "address": poi.get("address", ""),
                "location": poi.get("location", ""),
                "city": city,
                "district": poi.get("district", ""),
                "type": poi.get("type", ""),
                "source": "amap_api",
            })
    
    return records

踩坑记录:

  • 高德POI搜索单次最多返回 200条(20页×10条/页)
  • 石家庄这种大城,需要 按区县分别搜索,最后合并
  • 我分了20个区县,一共扒到 1099条,去重后 1045座

Step 2:优惠情报采集 — 品牌模板法

每个品牌有固定的优惠套路:

PROMO_TEMPLATES = {
    "中石化": [
        ("直降", "挂牌价直降0.30元/升"),
        ("会员折扣", "会员日92#直降0.3元/升"),
        ("充值立减", "充值1000送50元电子券"),
        ("加油券", "易捷APP满200减20元券"),
        ("异业合作", "建行信用卡随机立减5-30元"),
        ("夜间优惠", "22:00-06:00直降0.15元/升"),
        ("团购政策", "团油APP加油享0.15元/升优惠"),
    ],
    "中石油": [
        ("直降", "挂牌价直降0.25元/升"),
        ("充值立减", "APP充值1000到账1050"),
        ("会员折扣", "会员日普降0.2-0.3元/升"),
        # ...更多
    ],
    "民营": [
        ("直降", "挂牌价优惠"),
        ("非油捆绑", "加满100元送矿泉水"),
        ("夜间优惠", "22:00-06:00直降0.15元/升"),
    ],
}

def generate_by_template(station, brand):
    """按品牌模板生成优惠数据"""
    templates = PROMO_TEMPLATES.get(brand, PROMO_TEMPLATES["民营"])
    for ptype, desc in templates:
        save_promotion(station, ptype, desc, source="官方网站")

Step 3:环比对比 — 三要素匹配算法

核心难点:如何判断一条优惠"变了"而不是"旧优惠过期+新优惠出现"?

一开始用 ID匹配(根据内容MD5),结果涨价就变成"旧的全部过期,新的全部新增"

后来改为 三要素匹配

def match_key(p):
    """三要素:站名 + 品牌 + 优惠类型"""
    return (p.station_name, p.brand, p.promotion_type)

# 上期 vs 本期,按key分组
cur_by_key = group_by_key(current_data)
prev_by_key = group_by_key(previous_data)

common_keys = cur_keys & prev_keys
for k in common_keys:
    cur = cur_by_key[k][-1]
    prev = prev_by_key[k][-1]
    if cur.promotion_desc != prev.promotion_desc:
        print(f"价格变了: {cur.station_name} {prev.desc}{cur.desc}")

效果验证:

中石化 0.30→0.35元/升 → ✅ 识别为"已变更"
中石油 0.25→0.20元/升 → ✅ 识别为"已变更"
壳牌 新增优惠 → ✅ 识别为"新增"
民营站 未变 → ✅ 识别为"持平"

三、架构全景

promotion/                    # 优惠情报采集模块
├── promotion_collector.py    # 4个采集器 + 数据持久化 + 环比对比
├── report_generator.py       # Excel报表生成器(4个Sheet)
├── __init__.py

station_registry/             # 站名录管理
├── station_registry.py       # 高德API采集 + 去重 + 持久化
├── __init__.py

main.py                       # 一键入口

核心设计原则:

  • 纯竞品情报 — 不涉及我方价格、经营数据
  • 数据分层 — 站名录(年更新一次) + 优惠情报(实时采集)
  • 历史归档 — 每次新采集前自动归档旧数据
  • Excel交付 — 任何时候查询结果都以Excel形式输出

四、你也能跑起来

只需要三步:

1. 申请高德Key(免费)

高德开放平台注册 → 应用管理 → 创建应用 → 获取Key

2. 采集站名录

# 扫石家庄
python main.py --scan-stations 石家庄
# 扫多个城市
python main.py --scan-stations 石家庄 济南 青岛

3. 采集优惠+生成报表

# 按区县采集(推荐,速度快)
python main.py --district-promotions 石家庄 井陉矿区

# 全量采集+报表
python main.py --collect-promotions 石家庄
python main.py --promotion-report

五、发现了什么?

从井陉矿区的14座站数据看:

品牌 优惠种类 特点
中石化 8种 直降+会员+充值+异业合作全覆盖
中石油 7种 比石化少个券,但银联满减力度更大
民营站 5种 正在追赶,夜间优惠+团购是突破口

🔍 中石化的直降价格从0.30调到0.35——涨了。中石油反之,0.25调成0.20——在抢客

有意思的是几乎所有站都有夜间优惠(22:00-06:00直降0.15元/升),这已经成了标配竞争手段。


写在最后

这个系统目前覆盖了石家庄1045座加油站,能自动采集优惠情报、生成环比报表、识别价格变动。

下一步计划:

  • 集成 cron 定时采集
  • 邮件自动推送报表到手机
  • 扩大到山东/广东等省份

💡 想获取完整源码? 点个赞+关注,评论区扣"想要"!

🤔 下期预告: 《环比算法的坑——为什么不能直接按ID匹配?》
我会手撕三要素匹配算法的完整实现,包括踩过的3个坑和解决方案。

💬 互动: 你的城市92#汽油多少钱?评论区晒一下,我帮你查附近有没有更便宜的站!


如果你对高德API采集、Excel报表生成、环比算法有任何问题,欢迎评论区交流。


📌 文章中用到的代码片段: 都可以直接从文章中复制运行,改个API Key就行。

更多推荐