因为订阅的知识星球的信息有点多,而且主要是研报为主,所以用OpenClaw自己每天到上面抓取,看看最新卖方同学们有没有什么新关注的股票、行业会更加有效。
基于这个需求,我研究了下怎么去用AI抓知识星球内的东西。
主要是知识星球没有正式的接口,用模拟浏览的方式也很耗费流量(关键是也有的时候被block),最终找到一个方式,用了一周感觉还可以,做个记录。
当然不用自己看懂,让自己的AI看懂就好了。
原理说明
知识星球提供了移动端API(`api.zsxq.com`),可以通过模拟移动端请求获取数据。核心是:
认证方式:使用Cookie中的`zsxq access token`进行身份验证
签名机制:每个请求需要携带MD5签名,防止请求被伪造
API端点:主要使用`/v2/groups`(星球列表)和`/v2/groups/{group_id}/topics`(主题列表)
获取Cookie
方法:浏览器开发者工具
登录知识星球网页版:https://wx.zsxq.com
打开浏览器开发者工具(F12)
切换到「Network」标签
刷新页面,找到任意请求
在请求头中找到`Cookie`字段,复制完整内容
Cookie关键字段
Cookie中最重要的字段是:
`zsxq access token`:身份令牌,格式如`XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX_XXXXXXXXXXXXXXXX`
` c WBKFRo`:设备标识(可选)
Cookie有效期
通常1-3个月有效
过期后需要重新获取
建议定期检查,避免数据抓取失败
签名算法
知识星球的API签名算法如下:
import hashlib import time from urllib.parse import urlencode def generate_signature(path,params,secret="zsxqapi2020"): # 1. 构造公共参数 common_params={ "app_version":"3.11.0", "platform":"ios", "timestamp":str(int(time.time()*1000)) } # 2. 合并所有参数 all_params={**common_params,**params} # 3. 按参数名排序并拼接 sorted_params=sorted(all_params.items(),key=lambda x: x[0]) params_str=urlencode(sorted_params) # 4. 构造签名字符串:path & params & secret sign_str=f"{path}&{params_str}&{secret}" # 5. MD5加密 signature=hashlib.md5(sign_str.encode()).hexdigest() return signature, common_params["timestamp"]签名字符串示例:
/v2/groups&app_version=3.11.0&count=20&platform=ios×tamp=1713523200000&zsxqapi2020核心API接口
1. 获取星球列表
GET https://api.zsxq.com/v2/groups?count=50请求头:
Cookie: {你的Cookie} X-Signature: {签名} X-Timestamp: {时间戳} User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)...返回示例:
{ "succeeded":true, "resp_data": { "groups": [ { "group_id":5124251821488, "name":"示例星球名称", "type":"paid" } ] } }2. 获取星球主题
GET https://api.zsxq.com/v2/groups/{group_id}/topics?count=20&scope=all参数说明:
`group_id`:星球ID
`count`:返回数量(默认20,最大50)
`scope`:范围(`all`=全部,`digg`=精华)
3. 获取主题详情
GET https://api.zsxq.com/v2/topics/{topic_id}完整代码示例
import requests import hashlib import time from urllib.parse import urlencode class ZsxqApiSpider: def __init__(self,cookie): self.base_url="https://api.zsxq.com" self.secret="zsxqapi2020" self.cookie=cookie self.headers={ "User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15", "Accept":"application/json", "Cookie":self.cookie, "Origin":"https://wx.zsxq.com", "Referer":"https://wx.zsxq.com/" } def generate_signature(self,path,params=None): common_params={ "app_version":"3.11.0", "platform":"ios", "timestamp":str(int(time.time()*1000)) } all_params={**common_params,**(paramsor{})} sorted_params=sorted(all_params.items(),key=lambda x: x[0]) params_str=urlencode(sorted_params) sign_str=f"{path}&{params_str}&{self.secret}" signature=hashlib.md5(sign_str.encode()).hexdigest() return signature, common_params["timestamp"] def request(self,path,params=None): signature, timestamp=self.generate_signature(path, params) headers=self.headers.copy() headers["X-Signature"]=signature headers["X-Timestamp"]=timestamp url=f"{self.base_url}{path}" response=requests.get(url,headers=headers,params=params,timeout=15) return response.json() def get_groups(self): """获取我加入的星球列表""" data=self.request("/v2/groups", {"count":50}) if data.get("succeeded"): return data["resp_data"]["groups"] return [] def get_topics(self,group_id,count=20): """获取星球的最新主题""" data=self.request(f"/v2/groups/{group_id}/topics", {"count": count,"scope":"all"}) if data.get("succeeded"): return data["resp_data"]["topics"] return [] # 使用示例 if __name__=="__main__": # 替换为你的Cookie COOKIE="zsxq_access_token=YOUR_TOKEN_HERE; ..." spider=ZsxqApiSpider(COOKIE) # 获取星球列表 groups=spider.get_groups() for g in groups: print(f"星球:{g['name']}(ID:{g['group_id']})") # 获取第一个星球的最新主题 if groups: topics=spider.get_topics(groups[0]["group_id"]) for t in topics: print(f"主题:{t.get('title','无标题')}")定时任务配置
1. 创建日程任务
使用`calendar_create`工具创建每日定时任务:
# 在主对话中调用 calendar_create( summary="知识星球每日简报", description="通过知识星球API获取最新内容,分析持仓相关信息。执行命令:python3 ~/zsxq_spider/final_crawler.py", dtstart="20260419080000",# 每天早上8点执行 rrule={"freq":"DAILY","interval":1}, time_range={ "earliest_schedule_time":"20260419070000", "latest_schedule_time":"20260419090000" } )2. 任务执行流程
每日触发 → 执行爬虫脚本 → 解析数据 → 生成简报 → 推送到主对话常见问题
Q1: Cookie过期怎么办?
现象:API返回`{"succeeded": false, "code": 1001}`
解决:
重新登录网页版
获取新的Cookie
更新脚本中的COOKIE变量
Q2: 请求频率限制
现象:API返回`{"code": 1059}`
解决:
添加请求间隔:`time.sleep(1)`
减少单次请求数量
实现重试机制
Q3: 内容提取不完整
原因:主题内容存储在不同字段中
解决:按优先级提取
def extract_content(topic): # 1. talk.text(短文/评论) if topic.get('talk', {}).get('text'): return topic['talk']['text'] # 2. article.article_content(长文) if topic.get('article', {}).get('article_content'): return topic['article']['article_content'] # 3. files(附件) if topic.get('files'): return f"[附件]{topic['files'][0].get('name')}" return ""数据存储建议
目录结构
/app/data/所有对话/主对话/zsxq_data/ ├── daily_20260419.json # 每日原始数据 ├── files/ # 下载的文件 │ ├── 研报_20260419.pdf │ └── 音频_20260419.mp3 └── brief_20260419.md # 每日简报数据格式
{ "示例星球名称": [ { "topic_id":88442514812884, "title":"示例主题标题", "content":"示例内容...", "create_time":"2026-04-19T08:30:00.000+0800" } ] }安全提示
Cookie安全:不要将包含Cookie的代码上传到公开仓库
请求频率:避免高频请求,尊重平台规则
数据使用:获取的数据仅供个人学习研究使用
本教程仅供技术学习交流,请遵守知识星球用户协议。
作者:坦桑尼亚老云 | 编辑:栗加
每个视角都是拼凑世界真相的碎片,听真诚的行业观察者讲述独特的故事。
我们有深耕行业的资深顾问,连续跨界探索的未来创业者,专注细节的产品匠人,和许多志同道合的你们,如果你有想要分享的故事或者感想,可以留言或者邮件联系(AiysJY@outlook.com)。
,也欢迎点分享给需要的朋友们,记得点一下在看和星标,期待共同在这个行业的宏大叙事中,留下一句诗。:)
热门跟贴