餐饮选址分析与出图
面向餐饮创业者与品牌方的选址决策支持。产出:结构化评分报告(JSON + Markdown)+ 选址分析图(PNG)。
核心特性:业态 × 经营模式双驱动。 每个业态有独立的客单/面积/竞争半径/警戒距离/评分权重/检索关键词/需求锚点;每个店型有独立的面积与结构覆盖、权重偏移、成本特别提示、专属选址因子与风险。两者任意组合——选了店型,评分尺度、缺省成本参数、风险提示都会随之改变。
环境准备
依赖仅 requests + pillow(无需 numpy/matplotlib/pyproj)。
# 任选 Python 3.10+;建议在技能目录之外建独立 venv,避免污染发布包
python -m venv ~/.venvs/restaurant-site
~/.venvs/restaurant-site/bin/pip install requests pillow # Windows: ~/.venvs/restaurant-site/Scripts/pip.exe
下文命令中的 python 指已安装依赖的解释器:激活 venv 后可直接调用,或写解释器全路径。
Key 配置(重要)
- Key 从 环境变量
TENCENT_MAP_KEY或项目根目录.env读取,也可--key临时传入;脚本内不内置任何 Key - 腾讯地图服务端 WebService Key 须在控制台配置「授权 IP/白名单」含当前出口 IP,否则报 110/113;自检:
python scripts/tx_fetch.py --key <KEY> check - 应用类型须为「服务端」WebServiceAPI(浏览器端 Key 服务端调用必失败);IP 白名单含当前出口 IP(
curl myip.ipip.net查询) - 无 Key 不阻塞:用
assets/example_poi.json演练流程,或让用户提供自备 POI 数据(格式见下)
三步流水线
第 1 步 · 取数(tx_fetch.py,腾讯地图)
# 地理编码:地址/商圈名 → 经纬度(选址点定位)
python scripts/tx_fetch.py --key <KEY> geocode --keyword "武汉市洪山区光谷广场"
# 周边竞品检索(核心):--mode 自动展开该业态的检索关键词(与 --keyword 叠加,去重翻页)
python scripts/tx_fetch.py --key <KEY> around \
--mode hotpot --lon 114.4189 --lat 30.5186 \
--radius 1000 --max 100 --out poi.json
# 也可显式给词:--keyword "火锅,串串香,麻辣烫"
# 需求锚点检索:按业态档案需求锚点(住宅/写字楼/学校/地铁等)自动展开,供业态对比与需求匹配
python scripts/tx_fetch.py --key <KEY> demand --mode tea \
--lon 114.4189 --lat 30.5186 --radius 1000 --out demand.json
# 查看全部业态/店型档案与检索关键词
python scripts/site_analyze.py --list-profiles
# Key 自检
python scripts/tx_fetch.py --key <KEY> check
注意 --key 是 argparse 全局参数,须放子命令前(如 tx_fetch.py --key <KEY> around ...)。
坐标自动转 WGS84:腾讯地图返回 GCJ-02(火星坐标),tx_fetch.py 已在输出前统一转 WGS84 再落盘,与出图底图 Esri WebMercator(WGS84)对齐,下游 site_analyze.py / make_site_map.py 零改动。--lon/--lat 中心点须传 GCJ-02(腾讯 boundary 参数要求系),输出中心与 POI 已是 WGS84。
输出 JSON 结构:{success, mode, center, radius, keywords, count, pois:[{name,lon,lat,address,phone,category,distance}], source:"tencent"}。
失败时输出 error + code + hint(110/113 等附可执行排查建议,原样转告用户)。
第 2 步 · 分析(site_analyze.py,业态/店型驱动)
# 单业态 + 店型
python scripts/site_analyze.py \
--center "114.4189,30.5186" --poi poi.json --demand-poi demand.json \
--name "XX点位" --mode hotpot --format dine_in --radius 1000 \
--rent 150 --area 200 --capex 600000 --staff 10 --wage 4500 \
--ticket 85 --margin 0.62 --expected-daily 90 \
--out report.json --md report.md
# 不指定业态:用通用口径,并反向推荐「该点位最适合做什么业态」
python scripts/site_analyze.py \
--center "114.4189,30.5186" --poi poi.json --demand-poi demand.json \
--compare --name "XX点位" --radius 1000 --rent 150 --wage 4500 --out c.json --md c.md
--mode三级匹配(id → 别名 → 名称包含):如hotpot/火锅/奶茶/tea都认--format同三级匹配:satellite/外卖店/mall/校园店/加盟店等 14 种--compare不指定业态时,同一点位套全部 11 业态各自竞争半径/权重/需求锚点,排序给出"最适配业态";相关样本 < 3 条的业态标「数据不足」不参与推荐(避免用错竞品集算假分)- 评分规则、权重、成本测算公式全部在
references/scoring_model.md,口径可复算,禁止脱离该文档另创口径 - 未提供的成本参数不做臆测,报告标注"未测算"并列出缺失项;套用的业态经验值会显式标"参数占位提示"
- 客流维度是供给代理指标 + 业态锚点可达性,报告固定带"须现场校验"声明
第 3 步 · 出图(make_site_map.py)
python scripts/make_site_map.py \
--center "114.4189,30.5186" --poi poi.json \
--radius "300,500,1000" --name "XX点位" --unit "制图单位" \
--paper A3 --out 选址分析图.png
版面(项目成果版):双线图框 + 顶部居中标题带 + 右侧竖栏(传统指北针/比例尺/图例)+ 图框外右下落款。
A3 横版 300dpi(4961×3508)。zoom 自动按短边约束计算,保证最外缓冲圈完整入图。
底图 Esri World Imagery(免 Key,带本地瓦片缓存 tiles_cache)。
图名/制图单位非必填,留空则不落款,不阻塞出图。
自备 POI 数据格式(无 Key 备用路线)
{"success": true, "pois": [
{"name": "某火锅", "lon": 114.42, "lat": 30.52, "address": "xx路x号", "category": "火锅"}
]}
--poi 可传多个文件合并分析;category 用于分色与图例。
业态 / 经营模式档案(references/business_profiles.json)
全部数值为行业公开经验区间,仅用于「用户未给参数时占位」与「标定评分尺度」,出正式结论前须以实勘/询价/实测替换,报告内自动标注占位来源。
11 个业态(--mode):hotpot 火锅串串麻辣烫 / chinese 中式正餐酒楼 / fastfood 快餐简餐连锁 / snack 小吃粉面早餐 / tea 茶饮咖啡烘焙 / bbq 烧烤宵夜小龙虾 / buffet 自助餐大型餐饮 / western 西餐日韩异国料理 / wfast 西式快餐炸鸡汉堡披萨 / canteen 团餐食堂配餐 / special 清真素食地方细分特色。
各自带:客单区间、面积区间、员工区间、堂食/外卖占比、竞争半径、贴身竞争警戒距离、峰谷特征、POI 检索关键词、需求锚点关键词、四维权重、选址因子、硬约束(证照)、固有风险。
14 种店型(--format,可与业态任意组合):dine_in 堂食主力店 / dual 堂食+外卖双线 / satellite 纯外卖卫星店 / stall 档口美食城 / grab 外带窗口快取 / community 社区便民店 / mall 购物中心店 / office 写字楼园区店 / campus 校园店 / scenic 景区文旅店 / transit 交通枢纽店 / hospital 医院院区店 / night 夜经济店 / franchise 加盟连锁标准店。
店型如何改变分析:
- overrides:面积/堂食外卖占比/竞争半径/杂费率等覆盖业态同名字段(如 satellite 杂费率 0.22、竞争半径 3000m、堂食占比 0 均生效)
- weights_shift:权重偏移(如 dual traffic+0.05/competition-0.05,satellite traffic+0.10)已接入评分权重,组合后归一化
- cost_note / traffic_logic:写入报告"成本特别提示/客流逻辑"
- site_factors / risks / hard_constraints:并入报告清单与风险,店型风险标注 [店型固有]
franchise 店型无 overrides 字段(仅 traffic_logic/cost_note/weights_shift),解析逻辑已容错,不会因缺字段报错。
查看完整档案:python scripts/site_analyze.py --list-profiles(--mode tea 可看单条完整 JSON)。
工作要求(对 Agent 的约束)
- 结论先行:报告第一部分就是综合得分与评级,之后才是依据
- 量化优先:竞品密度、最近距离、盈亏平衡客流必须给出数字;"竞争激烈"这类模糊表述禁止出现
- 假设显式化:取不到的数据(人流、租金)要么向用户要,要么标注"经验估算",不得冒充实测
- 风险固定项:排烟/燃气/消防/证照提示必须包含(见 scoring_model.md 第五节)
- 演示数据(assets/example_poi.json)仅限流程演练,禁止用于真实选址结论
已知坑(实测记录)
--center格式是lon,lat(经度在前),与 lat,lon 习惯相反,注意校验- 出图 zoom 自动计算用 floor(ceil 会把最外圈裁掉);地图内容先画在独立画布再 paste 主图,否则缓冲圈会溢出压到竖栏
- Windows 下字体走 msyh.ttc / simhei.ttf,缺字体自动降级默认字体
- 空 POI(无 Key/Key 失效)= 框架模式:分析脚本将竞争/商圈/客流三维度置空(不给假分),
grade强制为「数据不足(缺竞品数据,评分不完整)」,incomplete=true;出图只画目标点+缓冲圈,图例加「竞品·待采集」。严禁在此状态下把任何分数当结论报给用户。 - 店型权重偏移必须注入
prof["_shifts"](compose_profile 内)才生效;早期漏了这步,14 个店型的 weights_shift 全是空转,已修。若改 compose_profile 务必保留这段 --compare横向对比:每个业态只用自己poi_keywords匹配的竞品子集算密度/最近距离(拿火锅竞品评日料无意义);相关样本 < 3 条判数据不足、不参与排序;客流分须注入业态锚点匹配否则各业态趋同- 业态/店型明显错配(如 buffet+grab、bbq+franchise)仅作提示不阻断,命中时报告带「错配提示」
- 坐标系:腾讯地图返回 GCJ-02(火星坐标),tx_fetch.py 已在输出前统一转 WGS84 再落盘,与出图底图 Esri WebMercator(WGS84)对齐,下游 site_analyze/make_site_map 零改动。tx_fetch 的
--lon/--lat中心点须传 GCJ-02(腾讯 boundary 参数要求系),输出中心与 POI 已是 WGS84。