整理一篇学习笔记,把看到的一些要点和自己的理解都记下来。
这里写目录标题
二、技术架构与开发准备 三、Instagram 博主数据采集实战 四、TikTok 创作者数据采集实战 五、KOL 评分模型与排名输出 六、成本分析与开源交付 七、总结一、出海 KOL 筛选的痛点:现有工具不够用
1.1 典型翻车案例
美妆出海品牌筛 KOL 翻车是常事。一个典型案例:某品牌预算五万美金砸在 8 个 TikTok 博主身上,视频一发每条几百万播放,团队群里发红包庆祝。一周后看转化——加购 0.3%,退货 40%,ROAS 算下来还不如直接投 Facebook 信息流。
复盘时用Bright Data拉这几个账号的真实数据,麻烦立刻浮出来:一个号称 50 万粉的"美妆头部",最近 90 天只发了 4 条内容,活跃度比普通个人号还低;另外三个账号的粉丝 70% 集中在印尼和巴西——品牌要打北美市场,一个都没对上。
最坑的不是博主骗了团队,是花几千块订阅的 KOL 工具根本没显示这些字段。同样的 8 个账号,Bright Data 5 分钟就跑出所有麻烦——互动率分布、粉丝地区、发文频率,任何一条都能在签约前叫停。
这种翻车本来可以避免。这篇文章交付一套可复用的 KOL 筛选管道:用Bright Data的 Instagram Scraper API 和 TikTok Scraper API 拉真实数据,跑评分模型,5 分钟出排名。代码全开 GitHub,照着跑就行。
1.2 国内外工具对比与局限性
国内 KOL 工具做国内很强,出海基本抓瞎。踩完坑整理一张对照表:
工具月费覆盖平台数据时效核心局限飞瓜数据¥999–¥3,999抖音/快手/B站/小红书较新不覆盖 Instagram/TikTok 海外版新榜¥1,500–¥5,000微信/微博/抖音较新海外博主数据几乎没有卡思数据¥2,000+抖音/快手/B站较新仅国内平台蝉妈妈¥299–¥1,999抖音/TikTok 部分较新TikTok 海外字段有限无法自定义HypeAuditor
99
99
99399IG/TikTok/YouTube月度更新价格高、筛选死板、无中文自建(Bright Data)按用量付费海外全平台,字段自定义实时需要初始配置
飞瓜、卡思、新榜做的是抖音快手生态,找 Instagram、TikTok 海外版、YouTube 博主时要么没数据要么字段少得可怜。HypeAuditor 覆盖海外但订阅贵、更新慢、筛选死板——各位想找"粉丝在东南亚、互动率 >5%、近 30 天发过美妆内容"这种组合,没工具能直接给答案。这也是为什么 Bright Data 更适合作为需要自定义字段、实时数据和规模化采集的海外数据基础设施。
不用 Dify / Coze 零代码干活流去搭,因为 KOL 评分本质是数据科学麻烦,不是流程编排问题。各位要稳定字段、可调权重、可复现排名,每改阈值都要看分布——纯 Python + Bright Data social media scraper API 最直接最可控。
二、技术架构与开发准备
2.1 管道整体架构
一句话:账号清单丢给 Bright Data → 结构化 JSON 扛回来 → 清洗 + 评分 → 排名 CSV。
账号 URL 清单
│
▼
Bright Data Scraper API ──► Instagram Profiles (gd_l1vikfch901nx3by4)
└─► TikTok Profiles (gd_l1villgoiiidt09ci)
│
▼
数据清洗(去重、字段对齐、单位归一)
│
▼
KOL 评分模型(5 维度,权重可调)
│
▼
排名输出 ──► kol_ranked.csv / Google Sheets
中间这段是关键——Bright Data 的数据采集基础设施帮助处理麻烦网页采集中的访问限制、动态内容和数据获取流程,让团队无需自行维护代理池和采集基础设施。各位不用养代理池、不用逆向 X-Gorgon、不用每次平台改版修代码。大家只关心"拿到数据后怎么用"。
整条管道拆成四段,每段一个 Python 脚本,互不依赖、单独跑也行:
脚本干啥输入输出instagram_profile_scraper.py调 IG Scraper API 抓博主资料inputs/urls_instagram.txtoutputs/ig_profiles.csvtiktok_creator_scraper.py调 TikTok Scraper API 抓创作者资料inputs/urls_tiktok.txtoutputs/tt_profiles.csvmerge_profiles.py两平台字段对齐 + 补默认值上面两个 CSVoutputs/merged_profiles.csvexport_to_sheets.py套评分模型 + 排名导出merged_profiles.csvoutputs/kol_ranked.csv
数据流是单向的——前一段的 CSV 是下一段的输入,但脚本本身不强制顺序:只想抓 TikTok 就只跑第 2 个,前面没产出 ig_profiles.csv 也不影响 merge_profiles.py 跳过 IG 直接合并 TikTok 那一份。后面第三、四、五章会逐段展开实现,先把架构和分工记清楚。
2.2 开发环境与账号准备
开始前准备:
如果你还没有 Bright Data 账号,可以先创建账号获取 API Token。免费额度足够完成小规模 KOL 数据测试。
Bright Data 官网:【一键直达】
1. Bright Data 账号:官网注册,新账号会免费信用额度,可以体验跑一下 KOL 数据。
1. API Token:登录后台 → User Settings → API Token → 复制。下文统一用 YOUR_BRIGHTDATA_API_KEY 占位。(每个控制面板用户都可以拥有一个分配给他的 API 密钥。第一个 API 密钥会自动为创建账户的用户生成。具有管理员权限的用户无法以明文形式查看自己的 API 密钥)
1. Python 3.9+:能跑 python 命令就行。
1. 目标账号清单:至少 10–20 个 Instagram/TikTok 账号 URL(也可以先根据关键字抓取内容,在抓取目标账号主页)。
环境变量(选择自己的API Token):
# macOS / Linux
export BRIGHTDATA_TOKEN=YOUR_BRIGHTDATA_API_KEY
# Windows PowerShell
$env:BRIGHTDATA_TOKEN="YOUR_BRIGHTDATA_API_KEY"
三、Instagram 博主数据采集实战
3.1 Instagram Scraper API 接入说明
Instagram Scraper API 给 IG 准备了好几个 dataset,出海筛 KOL 最常用 Profiles 端点,dataset_id 是 gd_l1vikfch901nx3by4。接口要点:
- 同步模式:单次最多 20 个 URL,请求即返回,适合小批量快速验证
- 异步模式(
/trigger端点):单次最多 5000 条,返回snapshot_id后轮询,适合大批量生产 - 请求体:JSON 包成
{"input": [{"url": "...", "country": ""}]}格式,country留空走默认区域 - 计费:按成功返回的 record 数计费,失败不计费
- 同步转异步:同步接口硬上限 60 秒,超时后不报错但响应体变成
{snapshot_id, message}占位符,要拿 snapshot_id 轮询/progress/{id}直到ready再下数据。Repo 脚本已经内置自动轮询逻辑,命令行只会看到状态打印,不用手动调接口
country 字段在 TikTok dataset 上能传,在 IG dataset 上直接被拒(返回 400 + This input should not contain a country field)。Repo 里两个 scraper 各自适配了对应 schema。报错时记得打印响应体,Bright Data 的错误信息写得很清楚,但 raise_for_status() 默认会把它吞掉,所以脚本里加了 if not resp.ok: print(resp.text) 兜底。
3.2 Python 批量采集脚本实现
# instagram_profile_scraper.py
"""
Instagram Profiles Scraper
==========================
调用 Bright Data Instagram Scraper API 抓取账号资料。
同步接口单次最多 20 个 URL,超过走异步 /trigger。
"""
import os
import sys
import json
import time
from pathlib import Path
import requests
import pandas as pd
from dotenv import load_dotenv
# 自动找项目根目录的 .env 文件加载 BRIGHTDATA_TOKEN
# .env 文件需手动创建(参考 .env.example),不要把 token 写进代码
load_dotenv(Path(__file__).resolve().parent.parent / ".env")
# 项目根目录,用于解析 inputs/ 和 outputs/ 路径
PROJECT_ROOT = Path(__file__).resolve().parent.parent
API_TOKEN = os.environ.get("BRIGHTDATA_TOKEN")
if not API_TOKEN:
sys.exit("ERROR: 请先在 kol-pipeline/.env 文件里配置 BRIGHTDATA_TOKEN(参考 .env.example)")
IG_DATASET_ID = "gd_l1vikfch901nx3by4"
API_URL = "https://api.brightdata.com/datasets/v3/scrape"
def _parse_response(resp):
"""解析响应,兼容 JSON 数组和 NDJSON 两种格式。"""
try:
data = resp.json()
if not isinstance(data, list):
data = [data]
except ValueError:
data = [json.loads(line) for line in resp.text.splitlines() if line.strip()]
return data
def _wait_for_snapshot(snapshot_id, headers, timeout=300, interval=5):
"""同步请求超过 60 秒会被自动转异步,返回 snapshot_id 占位符。
拿 snapshot_id 轮询进度,ready 后下载结果。
"""
progress_url = f"https://api.brightdata.com/datasets/v3/progress/{snapshot_id}"
download_url = f"https://api.brightdata.com/datasets/v3/snapshot/{snapshot_id}"
deadline = time.time() + timeout
print(f" 请求被自动转异步,snapshot_id={snapshot_id},开始轮询进度...")
while time.time() < deadline:
prog = requests.get(progress_url, headers=headers, timeout=30).json()
status = prog.get("status", "unknown")
print(f" → 状态: {status}")
if status == "ready":
dl = requests.get(download_url, headers=headers,
params={"format": "json"}, timeout=120)
dl.raise_for_status()
return _parse_response(dl)
if status == "failed":
raise RuntimeError(f"Snapshot 抓取失败: {prog}")
time.sleep(interval)
raise TimeoutError(f"等待 snapshot 超时({timeout}s)")
def scrape_instagram_profiles(urls):
"""同步批量抓取 Instagram 账号资料,超过 60 秒自动轮询 snapshot。"""
if len(urls) > 20:
sys.exit(f"ERROR: 同步接口单次最多 20 个 URL,当前 {len(urls)} 个,请改用异步 /trigger")
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json",
}
# IG dataset 的 payload schema 比 TikTok 严格:不接受 country 字段
payload = {"input": [{"url": u} for u in urls]}
resp = requests.post(
API_URL,
params={
"dataset_id": IG_DATASET_ID,
"notify": "false",
"include_errors": "true",
},
headers=headers,
json=payload,
timeout=120,
)
if not resp.ok:
# 默认 raise_for_status() 会吞掉响应体,主动打印方便定位 400/422 错误
print(f"\n Bright Data API 返回 {resp.status_code}:")
print(f" {resp.text[:2000]}\n")
resp.raise_for_status()
data = _parse_response(resp)
# 检测异步占位响应:返回里只有 snapshot_id 和 message,没有业务字段
if (data and isinstance(data[0], dict)
and "snapshot_id" in data[0] and "message" in data[0]):
data = _wait_for_snapshot(data[0]["snapshot_id"], headers)
df = pd.DataFrame(data)
keep = ["user_name", "full_name", "biography", "followers",
"following", "posts_count", "is_verified", "url"]
return df[[c for c in keep if c in df.columns]]
def load_urls(path):
with open(path, encoding="utf-8") as f:
return [line.strip() for line in f if line.strip() and not line.startswith("#")]
if __name__ == "__main__":
default_urls = PROJECT_ROOT / "inputs" / "urls_instagram.txt"
urls_file = sys.argv[1] if len(sys.argv) > 1 else default_urls
urls = load_urls(urls_file)
print(f"准备抓 {len(urls)} 个 Instagram 账号...")
df = scrape_instagram_profiles(urls)
output_path = PROJECT_ROOT / "outputs" / "ig_profiles.csv"
os.makedirs(output_path.parent, exist_ok=True)
df.to_csv(output_path, index=False, encoding="utf-8-sig")
print("\n抓取成功,前 3 条预览:")
print(df.head(3).to_string())
print(f"\n完整数据已写入 {output_path} ({len(df)} 条)")
3.3 返回字段与数据结构
跑完拿到这种结构(字段已 Bright Data 清洗过):
{
"user_name": "instagram",
"full_name": "Instagram",
"biography": "Discover what's next. ✨",
"followers": 676000000,
"following": 500,
"posts_count": 7800,
"is_verified": true,
"url": "https://www.instagram.com/instagram"
}
字段对应到 KOL 评分维度:followers 是基础规模、posts_count 算发文频率、is_verified 加分粉丝质量、biography 用来文本分析内容方向。
四、TikTok 创作者数据采集实战
4.1 TikTok Scraper API 接入说明
TikTok Scraper API 的 dataset_id 是 gd_l1villgoiiidt09ci,调用方法跟 Instagram 完全一致——同样的 endpoint、同样的 payload 格式、同样的 Bearer 鉴权。区别在返回字段:除了基础资料,TikTok 还带 likes(累计点赞)、videos_count、is_verified,方便直接算"累计互动 ÷ 视频数 = 平均互动"。
接口要点:
- 单次同步最多 20 个 URL,超过走异步
/trigger - 字段比 IG 多
likes和videos_count,可估算账号累计互动密度 - 要拿带货痕迹、平均播放量、近期发文频率,需要叠加 Posts 端点请求(见 4.3)
{snapshot_id, message} 占位符。Repo 脚本里的 _wait_for_snapshot 函数自动处理这套流程,你跑命令只会看到 5 秒一次的状态打印:
请求被自动转异步,snapshot_id=sd_xxx,开始轮询进度...
→ 状态: running
→ 状态: ready
不用管它,等 ready 就自动下数据写 CSV。snapshot 结果保留 16 天,建议拿到立刻消费,超期会自动清理。
4.2 Python 批量采集脚本实现
# tiktok_creator_scraper.py
"""
TikTok Profiles Scraper
=======================
调用 Bright Data TikTok Scraper API 抓取创作者资料。
同步接口单次最多 20 个 URL。
"""
import os
import sys
import json
import time
from pathlib import Path
import requests
import pandas as pd
from dotenv import load_dotenv
# 自动找项目根目录的 .env 文件加载 BRIGHTDATA_TOKEN
load_dotenv(Path(__file__).resolve().parent.parent / ".env")
# 项目根目录(scripts/ 的父目录),用于解析 inputs/ 和 outputs/ 路径
PROJECT_ROOT = Path(__file__).resolve().parent.parent
API_TOKEN = os.environ.get("BRIGHTDATA_TOKEN")
if not API_TOKEN:
sys.exit("ERROR: 请先在 kol-pipeline/.env 文件里配置 BRIGHTDATA_TOKEN(参考 .env.example)")
TT_DATASET_ID = "gd_l1villgoiiidt09ci"
API_URL = "https://api.brightdata.com/datasets/v3/scrape"
def _parse_response(resp):
"""解析响应,兼容 JSON 数组和 NDJSON 两种格式。"""
try:
data = resp.json()
if not isinstance(data, list):
data = [data]
except ValueError:
data = [json.loads(line) for line in resp.text.splitlines() if line.strip()]
return data
def _wait_for_snapshot(snapshot_id, headers, timeout=300, interval=5):
"""同步请求超过 60 秒会被自动转异步,返回 snapshot_id 占位符。
拿 snapshot_id 轮询进度,ready 后下载结果。
"""
progress_url = f"https://api.brightdata.com/datasets/v3/progress/{snapshot_id}"
download_url = f"https://api.brightdata.com/datasets/v3/snapshot/{snapshot_id}"
deadline = time.time() + timeout
print(f" 请求被自动转异步,snapshot_id={snapshot_id},开始轮询进度...")
while time.time() < deadline:
prog = requests.get(progress_url, headers=headers, timeout=30).json()
status = prog.get("status", "unknown")
print(f" → 状态: {status}")
if status == "ready":
dl = requests.get(download_url, headers=headers,
params={"format": "json"}, timeout=120)
dl.raise_for_status()
return _parse_response(dl)
if status == "failed":
raise RuntimeError(f"Snapshot 抓取失败: {prog}")
time.sleep(interval)
raise TimeoutError(f"等待 snapshot 超时({timeout}s)")
def scrape_tiktok_profiles(urls):
"""同步批量抓取 TikTok 创作者资料,超过 60 秒自动轮询 snapshot。"""
if len(urls) > 20:
sys.exit(f"ERROR: 同步接口单次最多 20 个 URL,当前 {len(urls)} 个")
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json",
}
# TikTok dataset 接受 country 字段(IG dataset 不接受,见 3.2 节)
payload = {"input": [{"url": u, "country": ""} for u in urls]}
resp = requests.post(
API_URL,
params={
"dataset_id": TT_DATASET_ID,
"notify": "false",
"include_errors": "true",
},
headers=headers,
json=payload,
timeout=120,
)
if not resp.ok:
print(f"\n Bright Data API 返回 {resp.status_code}:")
print(f" {resp.text[:2000]}\n")
resp.raise_for_status()
data = _parse_response(resp)
# 检测异步占位响应:返回里只有 snapshot_id 和 message,没有业务字段
if (data and isinstance(data[0], dict)
and "snapshot_id" in data[0] and "message" in data[0]):
data = _wait_for_snapshot(data[0]["snapshot_id"], headers)
return pd.DataFrame(data)
def load_urls(path):
with open(path, encoding="utf-8") as f:
return [line.strip() for line in f if line.strip() and not line.startswith("#")]
if __name__ == "__main__":
default_urls = PROJECT_ROOT / "inputs" / "urls_tiktok.txt"
urls_file = sys.argv[1] if len(sys.argv) > 1 else default_urls
urls = load_urls(urls_file)
print(f"准备抓 {len(urls)} 个 TikTok 账号...")
df = scrape_tiktok_profiles(urls)
output_path = PROJECT_ROOT / "outputs" / "tt_profiles.csv"
os.makedirs(output_path.parent, exist_ok=True)
df.to_csv(output_path, index=False, encoding="utf-8-sig")
keep_cols = [c for c in ["nickname", "account_id", "followers",
"likes", "videos_count", "is_verified"]
if c in df.columns]
print("\n抓取成功,前 3 条预览:")
print(df[keep_cols].head(3).to_string())
print(f"\n完整数据已写入 {output_path} ({len(df)} 条)")
下一步:
已经拿到账号数据?
使用 Bright Data 数据接口继续扩展 Posts 数据,分析互动率、内容趋势和商业化潜力。
4.3 扩展端点:抓 Posts 数据补全互动指标
Profiles 端点只返回账号级聚合数据。要拿平均播放量、近期发文频率、带货频率这些精细化指标,需要再调一次 TikTok Posts 端点(按账号主页 URL 抓最近 N 条视频)。Posts 返回字段包括 play_count(单视频播放)、digg_count(点赞)、comment_count、share_count、commerce_info(带货痕迹)、tagged_user(合作品牌)。聚合后能算出平均播放量、平均互动率、带货频率(commerce_info 非空比例)、近 30 天发文数等指标。
另外还有 Discover by keyword 模式(dataset_id gd_lu702nij2f790tmv9h,多带 type=discover_new&discover_by=keyword 两个参数,payload 用 search_keyword 字段),输入 #makeup#skincare 能反查潜在 KOL——这是"找人阶段"的核心能力,可以直接把关键词搜出来的创作者 URL 列表喂给 Profiles 端点做评估。完整 Posts 采集 + 关键词发现代码在 GitHub Repo,文章篇幅原因不展开。
已经拿到账号数据?
使用 Bright Data 数据接口继续扩展 Posts 数据,分析互动率、内容趋势和商业化潜力。
五、KOL 评分模型与排名输出
5.1 数据合并与字段对齐
抓完 IG 和 TikTok 数据后,两份 CSV 还不能直接喂给评分模型——两个平台的字段命名差异很大,必须先做归一化:
含义IG 字段TikTok 字段评分模型期望字段账号标识(从 URL 提取)account_idusername显示名full_namenicknamedisplay_name累计点赞—likesavg_likes(按视频数摊算)视频数—videos_count—帖子数posts_count——是否认证is_verifiedis_verifiedis_verified
merge_profiles.py 的干活就是把这两套字段对齐到统一格式,输出 merged_profiles.csv 作为评分模型的输入。脚本本身不强依赖两个 CSV 都存在——只有 IG 就只合并 IG,只有 TikTok 就只合并 TikTok,方便分阶段验证。
# merge_profiles.py
"""
Merge Profiles
==============
把 Instagram 和 TikTok 的原始数据合并、字段对齐,
补齐 KOL 评分模型需要的输入字段。
"""
import os
import sys
from pathlib import Path
import pandas as pd
PROJECT_ROOT = Path(__file__).resolve().parent.parent
def normalize(df, platform):
"""把不同平台的字段名归一化。"""
df = df.copy()
df["platform"] = platform
# username 归一化:优先用接口直接给的字段,没有就从 URL 末段提取
# (IG 接口不返回 user_name,URL 末段是唯一来源)
if "user_name" in df.columns and df["user_name"].notna().any():
df["username"] = df["user_name"]
elif "account_id" in df.columns:
df["username"] = df["account_id"]
elif "url" in df.columns:
# https://www.instagram.com/nike → nike;https://www.tiktok.com/@tiktok → @tiktok
df["username"] = (df["url"].astype(str)
.str.rstrip("/")
.str.rsplit("/", n=1).str[-1])
df["display_name"] = df.get("full_name", df.get("nickname", ""))
# 平均互动数据:TikTok 的 likes 是累计点赞,按视频数摊到单条
# 真实业务场景下,建议再调 Posts 端点拿最近 30 条视频的真实均值
if "avg_likes" not in df.columns:
# 分母优先用 videos_count(TikTok),其次 posts_count(IG),都没有就当 1
if "videos_count" in df.columns:
denom = df["videos_count"].fillna(1).clip(lower=1).astype(int)
elif "posts_count" in df.columns:
denom = df["posts_count"].fillna(1).clip(lower=1).astype(int)
else:
denom = 1
likes = df["likes"] if "likes" in df.columns else 0
df["avg_likes"] = likes / denom
df["avg_comments"] = df.get("avg_comments", 0)
df["avg_shares"] = df.get("avg_shares", 0)
df["posts_per_week"] = df.get("posts_per_week", 7)
df["recent_posts_30d"] = df.get("recent_posts_30d", 30)
df["geo_tier"] = df.get("geo_tier", "english")
df["has_shop_link"] = df.get("has_shop_link", False)
keep = ["platform", "username", "display_name", "followers", "following",
"posts_count", "videos_count", "is_verified", "url",
"avg_likes", "avg_comments", "avg_shares",
"posts_per_week", "recent_posts_30d", "geo_tier", "has_shop_link"]
return df[[c for c in keep if c in df.columns]]
def merge(ig_path=None,
tt_path=None,
out_path=None):
ig_path = ig_path or PROJECT_ROOT / "outputs" / "ig_profiles.csv"
tt_path = tt_path or PROJECT_ROOT / "outputs" / "tt_profiles.csv"
out_path = out_path or PROJECT_ROOT / "outputs" / "merged_profiles.csv"
frames = []
if os.path.exists(ig_path):
frames.append(normalize(pd.read_csv(ig_path), "instagram"))
print(f" ✓ 读到 Instagram 数据:{ig_path}")
else:
print(f" ⚠ 跳过 Instagram(文件不存在):{ig_path}")
if os.path.exists(tt_path):
frames.append(normalize(pd.read_csv(tt_path), "tiktok"))
print(f" ✓ 读到 TikTok 数据:{tt_path}")
else:
print(f" ⚠ 跳过 TikTok(文件不存在):{tt_path}")
if not frames:
raise SystemExit("ERROR: outputs/ 下既没有 ig_profiles.csv 也没有 tt_profiles.csv,先跑至少一个采集脚本")
merged = pd.concat(frames, ignore_index=True)
os.makedirs(os.path.dirname(out_path), exist_ok=True)
merged.to_csv(out_path, index=False, encoding="utf-8-sig")
print(f"\n合并完成:{len(merged)} 条记录 → {out_path}")
print(merged[["platform", "username", "followers"]].to_string())
return merged
if __name__ == "__main__":
merge()
踩坑提示:Bright Data IG 接口不直接返回 user_name 字段(只给 full_name),所以脚本里写了三层 fallback——优先用 user_name → 其次用 account_id → 最后从 URL 末段提取(https://www.instagram.com/nike → nike)。这种"字段名漂移"在跨平台爬虫里非常常见,解析代码必须有 fallback 链,否则一上线就掉数据。
跑完 merge 会输出 merged_profiles.csv,IG + TikTok 数据合在一张表里,platform 列区分来源:
5.2 五维度评分体系设计
数据拿回来只是起点。真正决定能不能"挑对人"的是评分模型——这就是出海 kol 数据分析跟"随便看看粉丝数"最大的区别。下面这 5 个维度组合,对海外网红筛选最实用:
维度默认权重计算逻辑互动率30%(平均点赞+评论+分享) / 粉丝数粉丝质量20%认证 + 合理发帖频率内容活跃度20%近 30 天发文数 / 12地区匹配15%目标市场 / 英语圈 / 其他商业化潜力15%是否有 TikTok Shop 挂车
权重设计逻辑:互动率权重最高,因为它是判断"粉丝真假"最直接的指标——百万粉账号互动率 <1% 基本是僵尸粉或买量号。粉丝质量排第二,认证 + 合理发帖频率往往意味着 MCN 在背后运营。活跃度排第三,过滤沉睡账号——老账号粉丝几百万但半年不发内容,合作了等于白花钱。地区匹配放第四,因为可以通过"组合查询"提前过滤。商业化垫底但不是不重要——同分时优先选有挂车历史的博主。
templates/kol_scoring_weights.csv 把权重做成可调参数,建议跑过 50–100 个账号后看分布再调。
5.3 评分模型 Python 实现
```
kol_scoring_model.py
"""
KOL Scoring Model
基于互动率、粉丝质量、活跃度、地区匹配、商业化潜力的 5 维度评分。
权重可在 templates/kol_scoring_weights.csv 里调整。
"""
import pandas as pd
DEFAULT_WEIGHTS = {
"engagement": 0.30,
"quality": 0.20,
"activity": 0.20,
"geo": 0.15,
"commerce": 0.15,
}
def load_weights(path="templates/kol_scoring_weights.csv"):
"""从 CSV 读取权重,文件不存在则用默认值。"""
try:
w_df = pd.read_csv(path)
return {row["dimension"]: row["weight"] for _, row in w_df.iterrows()}
except FileNotFoundError:
return DEFAULT_WEIGHTS
def compute_engagement_rate(row):
"""互动率 = (点赞+评论+分享) / 粉丝数 × 100%"""
if row["followers"] == 0:
return 0.0
inter = (row.get("avg_likes", 0)
+ row.get("avg_comments", 0)
+ row.get("avg_shares", 0))
return round(inter / row["followers"] 100, 2)
def score_one(row, weights=None):
w = weights or DEFAULT_WEIGHTS
er_score = min(row["engagement_rate"] / 5.0 100, 100)
quality = 50
if row.get("is_verified"):
quality += 30
if 5
今天的内容大概就这些,实际开发中大家还会遇到更多细节,欢迎留言分享自己的经验。
评论 (0)
暂无评论