微信公众号数据采集完整指南:3个实战场景玩转搜狗微信搜索爬虫
微信公众号数据采集完整指南:3个实战场景玩转搜狗微信搜索爬虫
【免费下载链接】WechatSogou基于搜狗微信搜索的微信公众号爬虫接口项目地址: https://gitcode.com/gh_mirrors/we/WechatSogou
微信公众号数据采集,是内容运营、竞品调研和行业分析绕不开的一步。本文以开源库 WechatSogou(一个基于搜狗微信搜索的 Python 爬虫接口)为主线,从一次"手动搬运文章翻车"的真实经历讲起,带你完成环境搭建、跑通首个采集脚本,再分别用竞品动态监控、选题灵感挖掘、行业趋势量化三个实战场景串起核心 API,最后补充请求频率控制、失败重试、结果缓存与验证码处理等避坑技巧。全程代码可复制可运行,读完你就能搭建一套属于自己的公众号数据采集管道。
先讲一次"手动采集"的惨痛经历
前两年我负责给团队做内容竞品周报,手头盯着 12 个行业公众号。每周五下午的固定动作是:挨个打开公众号主页 → 复制最新文章标题 → 粘贴到 Excel → 再手动统计"谁发了原创、谁更新最勤"。两小时下来,脖子酸、眼睛花,表格里还总混进格式不一致的脏数据。
更崩溃的是,领导临时要看"过去一个月这 12 家的发文时间分布",我对着几十条手动记录差点当场辞职。那一刻我意识到:数据采集这件事,靠人肉永远不可持续。于是我开始找自动化方案,最终遇到了 WechatSogou。
它的核心思路很朴素:搜狗微信搜索本身已经聚合了海量公众号和文章,WechatSogou 只是把"人在浏览器里做的搜索动作"封装成了十几个 Python 方法。搜索公众号、查公众号档案、检索文章、翻历史群发、看热门榜单、取联想词,每个动作一行代码。你不需要懂 HTML 解析,也不需要维护 Cookie 池,接口直接返回结构化字典。
三步完成环境配置,跑通第一个采集脚本
先把环境准备好。WechatSogou 依赖requests,Python 2.7 和 3.5+ 都支持,安装只有一条命令:
pip install wechatsogou --upgrade接着初始化客户端。构造函数暴露了三个常用参数,我建议你至少在本地配置一下timeout,避免网络抖动时脚本长时间卡死:
import wechatsogou # 直连,什么参数都不传也能跑 ws_api = wechatsogou.WechatSogouAPI() # 带超时与代理,生产环境推荐 ws_api = wechatsogou.WechatSogouAPI( timeout=10, proxies={ "http": "127.0.0.1:8888", "https": "127.0.0.1:8888", }, ) # captcha_break_time 表示验证码输错允许重试的次数,默认 1 ws_api = wechatsogou.WechatSogouAPI(captcha_break_time=3)现在跑一个最简单的查询:输入公众号名称,拿回它的完整档案。这里用get_gzh_info,它内部会先搜索再取第一条结果,刚好适合验证环境是否畅通:
profile = ws_api.get_gzh_info('南航青年志愿者') print('公众号名称:', profile['wechat_name']) print('微信号:', profile['wechat_id']) print('认证信息:', profile.get('authentication', '未认证')) print('简介:', profile['introduction']) print('最近一月群发数:', profile.get('post_perm', 0)) print('最近一月阅读量:', profile.get('view_perm', 0))输出是一个字段完整的字典,头像、二维码、简介、认证、近一月群发数、近一月阅读量都在里面。三行代码拿到一份"公众号身份证",你的采集之旅就此起步。
实战一:给竞品建一座"动态雷达",盯住历史群发
回到我开头的痛点:每周手抄竞品标题。现在我们用get_gzh_article_by_history一次性解决。这个接口只需传公众号名称,它会自动完成"搜索公众号 → 拿最近群发页链接 → 解析页面"的完整链路,返回gzh(公众号信息)和article(最近 10 条群发明细)两个部分。
import json from datetime import datetime class CompetitorRadar: """竞品动态雷达:批量扫描目标公众号,产出周报快照""" def __init__(self, client, targets): self.client = client self.targets = targets def scan_once(self): snapshot = {} for name in self.targets: try: history = self.client.get_gzh_article_by_history(name) articles = history.get('article', []) latest = articles[0] if articles else None snapshot[name] = { 'scanned_at': datetime.now().strftime('%Y-%m-%d %H:%M'), 'article_count': len(articles), 'latest_title': latest['title'] if latest else '本周无更新', 'latest_date': datetime.fromtimestamp(latest['datetime']).strftime('%Y-%m-%d') if latest else '-', } except Exception as exc: print(f'采集 {name} 失败: {exc}') return snapshot def save(self, snapshot, path='radar_report.json'): with open(path, 'w', encoding='utf-8') as f: json.dump(snapshot, f, ensure_ascii=False, indent=2) radar = CompetitorRadar(wechatsogou.WechatSogouAPI(), ['南航青年志愿者', '南京航空航天大学']) radar.save(radar.scan_once())效果如何?把脚本挂到服务器定时任务里,每周自动生成一份 JSON 周报,谁更了、更了几篇、最新标题是什么,一目了然。每条文章明细还自带content_url、cover封面、author作者、copyright_stat原创标识,想做深度分析也有素材。
一个小提醒:send_id是群发批次 ID,同一次群发多条消息时 ID 相同,统计"发布频率"时记得按它去重。
实战二:热门榜单加联想词,搭一个选题灵感池
内容团队最怕的不是不会写,而是"今天写什么"。WechatSogou 提供了两个绝佳的选题工具:get_gzh_article_by_hot按分类拉取搜狗首页热门文章,get_sugg返回某个关键词的联想词列表。
from wechatsogou import WechatSogouConst class TopicMiner: """选题灵感池:从热门榜与联想词中持续产出话题""" def __init__(self, client): self.client = client def hot_picks(self, category, limit=10): rows = self.client.get_gzh_article_by_hot(category) return [ { 'title': item['article']['title'], 'summary': item['article']['abstract'][:60], 'source': item['gzh']['wechat_name'], 'url': item['article']['url'], } for item in rows[:limit] ] def related_words(self, seed): return self.client.get_sugg(seed) miner = TopicMiner(wechatsogou.WechatSogouAPI()) print('—— 科技类热门文章 ——') for pick in miner.hot_picks(WechatSogouConst.hot_index.technology): print('•', pick['title']) print('—— 「高考」联想词 ——') for word in miner.related_words('高考')[:5]: print('•', word)热门榜的分类常量很丰富:hot_index下内置了科技、财经、美食、教育、旅行、萌宠、军事等二十多个方向,任取一个即可。联想词接口对 SEO 和内容策划尤其有用——你想搜"高考",它会告诉你用户实际在搜"高考志愿填报""高考早知道"等长尾话题,这些正是写标题的好素材。
实战三:跨公众号关键词检索,量化行业风向
如果说前两个场景解决"看谁"和"写什么",那第三个场景解决"行业在往哪走"。search_article支持按关键词搜索文章,还能叠加时间窗口和内容形态筛选,非常适合做趋势量化。
from collections import Counter from datetime import datetime def keyword_trend(client, words, window=WechatSogouConst.search_article_time.week): """统计一批关键词在指定时间窗内的文章热度分布""" result = {} for word in words: items = client.search_article(word, timesn=window) daily = Counter() sources = Counter() for item in items: ts = item['article']['time'] daily[datetime.fromtimestamp(ts).strftime('%m-%d')] += 1 sources[item['gzh']['wechat_name']] += 1 result[word] = { 'hits': len(items), 'daily_distribution': dict(sorted(daily.items())), 'top_sources': sources.most_common(3), } return result trend = keyword_trend(wechatsogou.WechatSogouAPI(), ['机器学习', '大模型']) print(trend)search_article_time提供了day / week / month / year等窗口,还能用specific配合ft、et指定起止日期,做历史回测。search_article_type则可以筛"有图""有视频""图文视频都有"的内容形态。想先圈定领域内有哪些公众号,再用search_gzh拿到列表、用get_gzh_info逐个建档,整套"找号 → 建档 → 追文章"的流程也就完整闭环了。
进阶技巧:怎样让公众号数据采集更稳、更体面
新手把接口跑通只是第一步,真正决定采集任务能否长期运转的,是下面几个工程化细节。
第一,控制请求节奏。搜狗对请求频率敏感,短时间高频访问容易触发风控。一个简单的做法是把每次调用包装成带随机间隔的"慢速请求":
import time import random def paced_client(client, low=2.0, high=4.0): """为任意 API 调用附加 2~4 秒随机延迟,模拟人工节奏""" def call(method, *args, **kwargs): time.sleep(random.uniform(low, high)) return getattr(client, method)(*args, **kwargs) return call slow_api = paced_client(wechatsogou.WechatSogouAPI()) profile = slow_api('get_gzh_info', '南航青年志愿者')第二,给请求加上失败重试。网络抖动、偶发风控页面都可能导致单次失败,写一个重试装饰器,任务就不会因为一次抖动整批中断:
import time from functools import wraps def retry(times=3, pause=3): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): for attempt in range(1, times + 1): try: return func(*args, **kwargs) except Exception as exc: if attempt == times: raise print(f'第 {attempt} 次失败({exc}),{pause} 秒后重试…') time.sleep(pause) return wrapper return decorator @retry(times=3, pause=5) def fetch_history(client, name): return client.get_gzh_article_by_history(name)第三,用缓存给重复查询提速。公众号档案、热门榜单这类数据短时间内不会变,缓存一天能省下大量请求:
import json import hashlib import time from pathlib import Path class SimpleCache: """按参数指纹缓存采集结果,默认保鲜一天""" def __init__(self, folder='.ws_cache', ttl=86400): self.dir = Path(folder) self.dir.mkdir(exist_ok=True) self.ttl = ttl def _path(self, func, *args, **kwargs): raw = f'{func}|{args}|{kwargs}' digest = hashlib.md5(raw.encode()).hexdigest() return self.dir / f'{digest}.json' def get(self, func, *args, **kwargs): path = self._path(func, *args, **kwargs) if not path.exists(): return None try: record = json.loads(path.read_text(encoding='utf-8')) except (ValueError, OSError): return None if time.time() - record['time'] > self.ttl: return None return record['data'] def put(self, func, data, *args, **kwargs): path = self._path(func, *args, **kwargs) path.write_text( json.dumps({'time': time.time(), 'data': data}, ensure_ascii=False), encoding='utf-8')第四,正视验证码。触发验证码时,库内置的identify_image_callback_by_hand会弹出提示让你手动输入,你也可以接入第三方 OCR 服务自动识别。相关的解锁逻辑集中在 wechatsogou/identify_image.py,api.py里每个公开方法都预留了unlock_callback和identify_image_callback两个钩子,方便你做定制。
第五,及时保存文章正文。微信文章临时链接会过期。拿到链接后尽快用get_article_content抓取正文和图片列表存到本地,否则隔几天再回放就会撞上"链接已过期"。该方法还支持hosting_callback,可以把文章图片一键托管到七牛、阿里云 OSS 之类的图床。
高频问答:新手最容易踩的 5 个坑
Q1:为什么接口只能拿到最近 10 篇文章?这是微信平台的限制,搜狗微信搜索只对外暴露最近 10 条群发。想要更长历史,建议定期采集并增量落库,靠时间积累出自己的完整档案。
Q2:文章链接会不会突然失效?会。临时链接有有效期,建议采集后立即用get_article_content抓正文存库,或至少保存标题、摘要、封面等结构化字段。
Q3:触发验证码后怎么办?WechatSogou 内置验证码识别钩子,默认弹窗手工输入;需要自动化的话,把验证码图片交给第三方识别服务,再通过identify_image_callback回调注入即可。
Q4:项目支持哪些 Python 版本?Python 2.7 与 Python 3.5+ 均兼容,遇到异常可以到项目 issue 区反馈。
Q5:请求频率控制在多少比较安全?建议单次请求间隔 3~5 秒,配合随机抖动更贴近真人操作;大批量任务尽量错峰、加代理,并做好上面说的缓存与重试。
如果还想深入阅读源码,核心逻辑分别落在wechatsogou/api.py(接口层)、wechatsogou/structuring.py(页面解析)、wechatsogou/request.py(URL 生成与请求)、wechatsogou/const.py(分类与时间常量)、wechatsogou/tools.py(辅助工具)这几个模块里,结构清晰,适合边读边改。
现在,轮到你了
这篇文章里出现的每段代码,都是可以直接跑起来的。我的建议是:先装好库,跑通get_gzh_info;然后选一个你最关心的竞品公众号,把"动态雷达"搭起来;跑顺之后,再逐步加上限速、重试和缓存,让脚本从"能跑"进化到"能长期跑"。
想一下:如果每周五的那份竞品周报,从"两小时手动搬运"变成"三分钟脚本自动生成",你能省下多少时间去做真正有价值的事?
你的第一座"公众号数据雷达",打算从监控哪个账号开始呢?
【免费下载链接】WechatSogou基于搜狗微信搜索的微信公众号爬虫接口项目地址: https://gitcode.com/gh_mirrors/we/WechatSogou
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
