Skip to content

抖音同城号怎么运营?用 IP 属地分析粉丝城市分布(Python 示例) ​

做本地生意的老板都有这个困惑:账号发了三个月视频,播放量看着还行,就是没有同城客户上门。打开创作者后台看粉丝画像,只有省份维度,连城市都看不全。其实你手上早就有一份比后台更细的数据——访客的 IP。每条访问记录里都带着出口 IP,用 IP 归属地接口把它翻译成「哪个省哪个市」,同城流量的账就算明白了。这篇讲抖音 IP 属地的机制,再给一个 Python 分析访客城市分布的落地脚本。

一、抖音的 IP 属地是怎么算的 ​

抖音在用户主页、评论区展示的「IP 属地」,是平台根据用户出口 IP 推断的,大多数时候到省级,部分场景到城市。它有几个特征,做运营得先搞清楚:

  • 它是「出口 IP」的属地,不是手机定位。用户连着家里宽带,展示的是宽带所在城市;用户挂了 VPN 或代理,展示的就是代理节点的归属地。所以你看到某个粉丝属地是「海外」,不代表他人在海外,可能只是挂了加速器。
  • 经常和「定位」不一致。定位(POI、同城页)走的是 GPS/基站,IP 属地走的是出口网络,两套数据对不上是常态——这也解释了为什么后台有时显示「两个城市」。
  • 对创作者的意义:抖音的同城流量池按位置划分,你的内容想进某个城市的同城页,账号定位、内容标签、粉丝地域分布都起作用。粉丝地域分析是判断「账号在哪个城市有基本盘」最直接的方式。

二、运营者能拿到什么数据 ​

创作者后台的粉丝画像有省份分布,但没有城市维度,直播间的观众来源也只给到看播省份。想拿到城市级数据,有两条路:

  1. 看自己的数据:如果你有小程序、团购页、落地页(本地生活商家最常见),服务端会记录每个访客 IP——这是最干净的数据源。
  2. 看公开数据:自己视频/直播间的评论区 IP 属地、私信对方主页的属地,逐条看效率太低,适合抽样验证。

落地姿势建议:在团购页/落地页埋一条访问日志(Nginx 或接口层记下 IP),定期跑脚本把 IP 翻译成省市,按城市聚合出报表。这份报表直接指导两件事:广告投放在哪几个城市集中投(同城流量),内容选题照顾哪个城市的口味。

三、Python 实现 ​

下面脚本读取访问日志(每行一个 IP,也可以是 CSV),逐 IP 调免费接口查归属地,聚合出「省市 → 访客数」Top N。免费版限 60 次/分钟,脚本里做了限速和内存缓存,几千条日志一两分钟跑完。

python
#!/usr/bin/env python3
"""访客 IP -> 省市分布统计(本地生活/同城运营用)"""
import json
import time
import urllib.request
from collections import Counter

GEO_API = "https://ip9.com.cn/get?ip={ip}"   # 免费版 60 次/分钟,需限速
_CACHE = {}                                   # ip -> 省市,内存缓存去掉重复 IP

def geo(ip: str):
    """查单个 IP 归属地,带缓存与限速"""
    if ip in _CACHE:
        return _CACHE[ip]
    url = GEO_API.format(ip=ip)
    req = urllib.request.Request(url, headers={"User-Agent": "geo-batch/1.0"})
    with urllib.request.urlopen(req, timeout=5) as resp:
        data = json.loads(resp.read().decode("utf-8"))
    if data.get("ret") != 200:
        return ("", "")
    d = data["data"]
    result = (d.get("prov", ""), d.get("city", ""))
    _CACHE[ip] = result
    time.sleep(0.7)          # 限速:免费版 60 次/分钟,留余量
    return result

def load_ips(path):
    """读日志:每行一个 IP(生产环境从 Nginx access.log 提取 $remote_addr)"""
    with open(path, encoding="utf-8") as f:
        return [line.strip() for line in f if line.strip()]

def main():
    ips = load_ips("ips.log")
    print(f"待分析 IP:{len(ips)}(去重后 {len(set(ips))})")
    prov_cnt = Counter()
    city_cnt = Counter()
    for ip in ips:
        prov, city = geo(ip)
        if prov:
            prov_cnt[prov] += 1
        if city:
            city_cnt[f"{prov} {city}"] += 1
    print("\n省份 Top 10:")
    for k, v in prov_cnt.most_common(10):
        print(f"  {k}: {v}")
    print("\n城市 Top 10:")
    for k, v in city_cnt.most_common(10):
        print(f"  {k}: {v}")

if __name__ == "__main__":
    main()

脚本里值得注意的两处:_CACHE 字典把重复 IP 的查询省掉了——同一个用户一天点进来十次,只查一次接口,既省额度又快;time.sleep(0.7) 是免费版限速的保命符,批量场景宁可慢,不要触发 429。生产环境可以考虑把结果落 SQLite 或 ClickHouse 做趋势,脚本只负责把「IP → 省市」这层翻译做好。

四、落地注意事项 ​

  • 先想清楚数据从哪来:实体店用门店 WiFi 的访客 IP 不准(都是运营商 NAT 出口,一个 IP 几百人用),分析口径要用「线上访客」(团购页、小程序、App),它们每个用户独立出口 IP,才分得出城市。
  • 别把省市当精确位置:IP 归属地是城市级(经纬度也是城市中心点),拿去做「同城 3 公里推送」是错的,拿去做「哪个城市有客户」是对的,口径别混。
  • 隐私合规:IP 属于个人信息,只做聚合统计、不留明细表,报表只保留省市维度 + 数量,原始日志设定期清理;不在任何公开页面展示单用户城市。
  • 结合后台数据校准:脚本算出来的分布和创作者后台的省份分布对一下,偏差大就检查是不是埋点采集了代理 IP 或 CDN 的 IP(记得取 X-Forwarded-For 的真实客户端 IP)。
  • 错峰跑批:免费版 60 次/分钟,十万级日志要跑一晚上,建议凌晨低峰跑,或升级 VIP(18 万次/分钟、含区县)当日出结果。

总结 ​

抖音同城运营不缺内容方法论,缺的是「知道客户在哪个城市」的数据底盘。把访问日志里的 IP 用 https://ip9.com.cn/get?ip=<ip> 翻译成省市,聚合出分布报表,投流和选题就都有了依据——这套东西一晚上就能跑起来。免费版适合小体量起量,字段含省份、城市、运营商,足够做地域运营决策;数据量大、要区县粒度再考虑 VIP。数据驱动同城,比拍脑袋选题踏实。