手动监测的坑:月均200条到12000条,我换了工具链

2023年以前,我靠百度搜索+Excel表手动记录视频平台提及。每天打开B站、抖音、快手、小红书、视频号,一个个搜品牌词,复制链接,粘贴到表格,标注平台和发布时间。一天3小时打底,一个月撑死200条,还经常漏掉半夜发的视频。去年接了个教育客户,他们的品牌词在B站一天就能冒50条,我手动根本追不上。

我花了2天写了个Python脚本。核心逻辑很简单:用requests库(版本2.31.0)调百度搜索API,qps限制10次/秒,我配了8个线程并发跑。每个线程负责一个平台的关键词轮询,脚本每10分钟自动扫一轮。抓到的结果直接写进SQLite数据库,字段就四个:关键词、平台、链接、发布时间。代码不长,100行不到,关键的搜索函数就这玩意:

import requests
import threading
import sqlite3
from queue import Queue

def search_platform(keyword, platform, api_key):
    url = f"https://api.baidu.com/json/s/2.0/search?q={keyword}+site:{platform}"
    headers = {"Authorization": f"Bearer {api_key}"}
    try:
        resp = requests.get(url, headers=headers, timeout=5)
        data = resp.json()
        for item in data.get("results", []):
            db_cursor.execute(
                "INSERT OR IGNORE INTO mentions VALUES (?, ?, ?, ?)",
                (keyword, platform, item["url"], item["pub_date"])
            )
        db_conn.commit()
        return len(data.get("results", []))
    except Exception as e:
        print(f"平台{platform}请求失败: {e}")
        return 0

# 线程池处理
q = Queue()
for plat in ["bilibili.com", "douyin.com", "kuaishou.com", "xiaohongshu.com"]:
    q.put(("品牌词A", plat))
    q.put(("品牌词B", plat))

def worker():
    while not q.empty():
        kw, plat = q.get()
        search_platform(kw, plat, "你的API_KEY")

threads = [threading.Thread(target=worker) for _ in range(8)]
for t in threads:
    t.start()
for t in threads:
    t.join()

别看我写得轻巧,API费用每月300块,百度搜索API按调用量计费,100万次/月刚好够用。实测数据:脚本跑了一个月,系统日志显示抓取量从200条直接跳到12000条,平均每天400条。最狠的一天B站单平台抓了180条,手动根本不可能。但有个坑:百度搜索API对B站和抖音的覆盖率不够全,大概漏抓15%的短视频,尤其那些标题不规范的。我后来补了个备用方案,用各平台自己的开放API兜底。

避坑清单

  • 线程数别超过8,我试过16线程,被百度API限流封了两次IP
  • API密钥别硬编码在脚本里,用环境变量加载,我吃过泄露的亏
  • 数据库字段一定要加UNIQUE约束,不然重复数据能让你崩溃
  • 备用方案必须准备,单靠百度API会漏掉15%的短视频提及

数据清洗:用正则过滤90%垃圾信息,准确率从45%提到92%

我去年给一个短视频舆情监测站做优化,客户每天从抖音、快手、B站扒下来20万条评论。原始数据里啥都有:卖课的、刷粉的、表情包刷屏的、完全无关的“路过”“顶一下”。我第一版没做清洗,直接跑情感分析,准确率只有45%。客户指着屏幕说“你这AI是不是瞎了”,我脸都绿了。

后来我写了个正则过滤器,核心逻辑就两条。第一,过滤37个垃圾关键词,包括“购买”“加V”“代发”“私聊”“点击链接”“免费领取”“V我”这些,我实测发现光“V我”一个词就能干掉12%的营销帖。第二,长度<10字或>500字的帖子直接扔掉,抖音评论区多的是“666”“哈哈哈哈”这种无意义内容,占总量17%左右。正则表达式我用Python 3.9编译的,单条处理耗时0.03ms,20万条数据6秒跑完。

代码长这样,直接复制就能用:

import re
import time

# 37个垃圾关键词,按危害程度排序
garbage_pattern = re.compile(
    r'(购买|加V|代发|私聊|点击链接|免费领取|V我|微信|QQ群|'
    r'刷赞|刷粉|代运营|包过|保过|内部渠道|限时优惠|'
    r'名额有限|前10名|立即下单|扫码|二维码|加好友|'
    r'转发抽奖|点赞抽奖|送手机|送红包|现金奖励|'
    r'日赚|月入|兼职|学生党|宝妈|在家可做|'
    r'无需经验|一对一指导|手把手|包教包会)',
    re.IGNORECASE
)

def clean_post(post_text):
    text = post_text.strip()
    # 长度过滤
    if len(text) < 10 or len(text) > 500:
        return None
    # 关键词过滤
    if garbage_pattern.search(text):
        return None
    return text

# 实测性能
start = time.time()
for i in range(200000):
    clean_post("这条评论是正常的,讨论产品实际体验")
print(f"20万条总耗时: {time.time() - start:.2f}s")

这个参数我调了三天才摸清楚。一开始我设置了60个关键词,结果把“免费试用”这种正常讨论也误杀了。后来砍到37个,去掉“免费”“试用”“活动”这些中性词,准确率从45%跳到78%。再加长度过滤,跳到92%。代价是漏掉了一些短评(比如“牛逼”),但短视频评论区里正常短评占比不到3%,可以接受。

边界条件得说清楚。这个方案只适合中文UGC场景,英文评论得换另一套词库。如果是长文评论区(比如知乎、豆瓣),长度阈值要改到100-2000字。别像我当初那样,拿抖音的规则硬套知乎,结果把80%的正常长文都扔了。

避坑清单

  • 正则编译要加re.IGNORECASE,不然“购买”和“购买”大小写不统一会漏
  • 关键词别超过50个,越多误杀率越高,我试过70个直接掉到82%
  • 长度过滤前先strip(),不然空格算字符会把短评都卡死

百度收录优化:把提及内容做成专题页,索引量从3200涨到18900

去年我给一个数码评测站做优化,检测到“小米14 Ultra”在抖音被疯狂提及,但百度搜这个关键词,首页全是新闻,没一个专题页。我直接拿WordPress 6.4 + Elementor Pro 3.18搭了个动态专题站,流程走通后索引量从3200干到18900,3个月翻了5.9倍。服务器成本每月200块,开发2周。

专题页结构:标题必须含关键词,比如“抖音热议:小米14 Ultra的相机到底多强?”,正文3段,每段100-150字——第一段引述视频原话,第二段做技术分析,第三段给用户建议。底部放原始视频链接,用<a rel="nofollow" href="抖音链接">,别直接嵌入iframe,百度蜘蛛不抓那玩意儿。模板用Elementor的“专题页”容器,固定布局:标题用H1,正文用P标签,链接用a标签,别用任何JS渲染。

sitemap每天更新一次:我用Python脚本跑,每天凌晨2点触发cron job,脚本读MySQL里新生成的专题页,输出XML。代码贴出来:

import mysql.connector
from datetime import datetime

conn = mysql.connector.connect(
    host="localhost",
    user="root",
    password="your_password",
    database="wordpress"
)
cursor = conn.cursor()
cursor.execute("SELECT post_name, post_date FROM wp_posts WHERE post_type='post' AND post_status='publish'")

xml = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
for slug, date in cursor.fetchall():
    url = f"https://yourdomain.com/{slug}/"
    lastmod = date.strftime("%Y-%m-%d")
    xml += f"<url><loc>{url}</loc><lastmod>{lastmod}</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>"
xml += "</urlset>"

with open("/var/www/html/sitemap.xml", "w") as f:
    f.write(xml)

cursor.close()
conn.close()

然后nginx里配好sitemap的缓存和压缩,别让蜘蛛等太久:

server {
    listen 443 ssl;
    server_name yourdomain.com;
    location /sitemap.xml {
        root /var/www/html;
        expires 1h;
        gzip on;
        gzip_types text/xml;
    }
}

实测索引量变化曲线:第1个月从3200涨到5800,第2个月冲到12000,第3个月站上18900。坑在哪?别一次性生成太多专题页,第一天我只发了5篇,第二天看收录正常才加到15篇。百度对“批量内容”有审核延迟,我试过一天发50篇,直接三天不收录,血泪教训。成本就服务器200块/月+我2周开发时间,其他零成本。

避坑清单

  • 专题页正文必须原创,至少30%的句子和视频文案不同,不然百度判定低质
  • sitemap每天更新一次,别设成每小时,蜘蛛会怀疑你刷量
  • 服务器带宽要够,专题页带视频链接时别让用户点击后卡死,我用的腾讯云轻量2核4G,峰值带宽5Mbps,跑2000个专题页没崩

性能压测:专题页加载从4.5s降到1.2s,用了Redis缓存+CDN

上个月给一个视频平台检测专题页做性能优化,压测后发现TTFB飙到4.5s,跳出率直接干到65%。问题出在数据库查询——每次请求都要查MySQL里近百万条视频关键词匹配记录,索引加满了也没用,并发一上来连接池就炸。

我直接上了Redis 7.2。缓存策略很简单:专题页的关键词匹配结果缓存600s,过期时间设成10分钟。缓存key用video:keyword:{md5(查询词)},value存JSON格式的匹配结果数组。实测缓存命中率从0%直接跳到78%,MySQL查询次数从每分钟3200次降到不到700次。

nginx配置也得跟上。我加了gzip压缩,级别调到5,对text/html和application/json按需压缩。worker_connections设成1024,keepalive_timeout设成65s。完整配置长这样:

http {
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    upstream redis_cache {
        server 127.0.0.1:6379;
    }

    server {
        listen 80;
        server_name example.com;

        location /video-detection/ {
            proxy_pass http://127.0.0.1:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_cache_valid 200 302 10m;
            proxy_cache_use_stale error timeout updating;

            # gzip on for this location
            gzip on;
            gzip_types application/json text/plain;
        }
    }

    events {
        worker_connections 1024;
        multi_accept on;
        use epoll;
    }
}

然后上了Cloudflare免费版CDN。这个坑我踩过——默认缓存策略只缓存静态资源,对动态内容根本不碰。我手动在Cloudflare的Page Rules里加了一条:/video-detection/* 缓存级别设成”Cache Everything”,Edge Cache TTL设成600s。同时把浏览器缓存TTL设成300s,防止用户端缓存太久导致数据滞后。

优化后压测数据:TTFB从4.5s降到1.2s,首屏加载时间从6.8s降到2.3s,跳出率从65%降到31%。最爽的是服务器CPU占用率从85%掉到22%,一台4核8G的机器扛住了原来三台都扛不住的并发量。

避坑清单

  • Redis缓存key别用原始查询参数直接拼接,要md5哈希,否则key太长占用内存还容易触发bug
  • Cloudflare免费版Page Rules只有3条,别浪费在不需要缓存的路径上
  • gzip级别别设太高,5级以上压缩率提升不明显但CPU消耗翻倍
  • 缓存过期时间别设成整点(比如3600s),容易造成缓存雪崩,用随机偏移量

变现路径:把监测数据卖给竞品分析公司,月入5000块

数据攒了3个月后,我盯着那堆提及记录突然开窍——这玩意儿能卖钱。别整那些虚的,直接打包成CSV,里头四列:视频URL、提及量、情感分析得分、抓取时间戳。情感分析我用VADER库,版本3.3.2,这个库对中文支持还行,跑一个视频15秒搞定。实测数据量:每天抓5000条提及,CSV文件也就4.2MB,服务器费用忽略不计,一台48元/月的轻量云服务器扛得住。

我挑了10家竞品分析公司,挨个发邮件,直接报价2000块/月,按月订阅。3家当场签约,剩下7家嫌贵,但我没降价。为啥?这数据他们自己抓不来,爬虫封IP、接口限流、分词精度差,我全踩过坑。签约后每月跑一次导出脚本,耗时15秒,纯利润6000块。成本?就那个VADER库每次加载模型要2.1秒,我优化成预加载,现在导出时间从17.3秒压到15秒整。

别以为SEO只能搞排名,数据就是钱。我去年给一个美妆站做监测,发现某竞品在小红书被骂了3000条,我把这数据卖给那竞品的对手,单次交易收了800块。但这行有边界:别卖假数据,别泄露客户隐私,我每份CSV都脱敏处理,视频URL只保留ID,不存用户信息。代码放这:

import csv
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
analyzer = SentimentIntensityAnalyzer()
def export_to_csv(rows, filename="mentions.csv"):
    with open(filename, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(["video_url", "mention_count", "sentiment_score", "timestamp"])
        for row in rows:
            score = analyzer.polarity_scores(row['text'])['compound']
            writer.writerow([row['url'], row['count'], score, row['ts']])
    print(f"导出完成,耗时{time.time()-start:.1f}秒")

下一步干什么

马上跑一遍你的历史数据,算出情感得分,别等数据凉了再卖。定价按2000块/月起,低于这个数不签,值这个价。

避坑清单

做视频平台提及检测这几年,踩过的坑比吃过的盐还多。我直接列出来,你对照着改,别走弯路。

坑1:只盯着抖音关键词,忽略B站长尾词
我去年帮一个美妆品牌做检测,光盯着“粉底液”这个词在抖音的提及量,结果B站上一条“干皮救星粉底液测评”视频播放量170万,评论里骂品牌色号假白的有300多条。我愣是2个月后才看到,品牌公关都来不及。后果:品牌口碑直接跌了15%,转化率掉到1.2%。现在我把B站、小红书、快手全加上,每天扫一遍长尾词,用Python脚本跑,关键词库从200个扩充到1200个,才没漏过。

坑2:用免费工具检测,数据不准还限流
有一次我用某免费平台查“某新茶饮品牌”在抖音的提及,显示日均200条,我信了。结果甲方自己用付费工具跑,数据是日均1700条,差了8.5倍。免费工具抓取深度只有3页,还限制IP,根本看不到真实数据。我后来换成付费API(月费3800元),配合自建爬虫,数据偏差控制在5%以内。别省那点钱,数据不准等于白干。

坑3:只检测视频标题,忽略评论区
我有个客户做智能家居,一条测评视频标题没提品牌,但评论区有470条在讨论“他家的帐篷收纳太差了”,我漏了。后果:竞品趁机在评论区做广告,3天内截流了23%的潜在客户。现在我强制爬虫抓评论区,用正则匹配品牌词+情感词,准确率从62%提到91%。代码我放这:

import re
def extract_comment_mentions(comments, brand):
    pattern = re.compile(rf'{brand}.*?(好|差|垃圾|坑|推荐|别买)', re.IGNORECASE)
    return [c for c in comments if pattern.search(c)]

坑4:不设时间窗口,被旧视频数据污染
有次检测一个游戏品牌,爬出来“提及量涨了300%”,我兴奋地汇报。结果发现是3年前的老视频突然被算法推荐,讨论的版本早过时了。后果:甲方多花了8万做无效投放。现在我只抓7天内的视频,用created_at > datetime.now() - timedelta(days=7)过滤,同时标记播放量>10万的旧视频,单独分析。

坑5:忽略跨平台的情感歧义
B站上“这个品牌又翻车了”可能是反讽,抖音上“绝了”可能是正面。有次我没做情感分类,把一条“这个包装设计绝了(丑到绝)”算成正面,报告里写好评率98%。后果:甲方按这个数据调整了包装,结果退货率暴涨到34%。现在我必须用BERT模型做情感分析,准确率到89%,不靠关键词硬匹配。

坑6:检测频率设成每天1次,错过爆发期
一个母婴品牌在抖音突然爆火,我早上8点跑的数据显示200条提及,下午3点已经冲到6700条。我隔了24小时才更新,竞品早就截了流量。后果:品牌自己花了2倍预算打补丁。现在我用异步爬虫,每15分钟扫一次,配合WebSocket推送到群,响应时间从24小时缩到18分钟。

坑7:只查正面词,不查负面词
我犯过最蠢的错:只搜“推荐”“好用”,结果漏了“垃圾”“智商税”。一个数码品牌被骂“发热严重”,2000条负面讨论在评论区发酵了3天,我都没报。后果:品牌销量周环比跌了41%。现在我把负面词库从30个扩充到150个,包括“割韭菜”“翻车”“退货”,每发现负面>10条就自动报警。

坑8:不检测视频的“关联推荐”区域
抖音的关联推荐里经常带竞品视频。有次我查“某咖啡品牌”提及,发现关联推荐里竞品的视频占比37%,用户点过去就跑了。后果:品牌7天流失了2400个潜在客户。现在我用Selenium模拟用户滚动,把关联推荐区域的视频标题、作者全抓下来,对比竞品提及率,实时调整投放。

别嫌麻烦,这些坑每个都让我亏过5位数以上。现在我的检测系统跑一次要2小时,但数据靠谱,甲方续约率93%。你照着改,至少少踩一半坑。