项目背景
如今知识付费产品是越来越多,因为对知识的焦虑,所以我们会买很多知识。但知识我们都没有来得及消化。像我自己加入了70多个知识星球,其实平时很多星球我都没有去看他们的内容,所以我最近决定把这些一些内容好好看一下,但是这些内容生产的可能层次不齐,我可能只看那些精华帖,因为精华帖还算质量算比较高了,所以我就想把这些精华帖作为一个电子书去制作起来方便查看,这就是我做这个项目的初衷。
因为大家都知道这里有一些版权的问题,所以这些知识内容我电子书我是不能去分享出来的,所以大家也不要找我要什么电子书。但是大家可以通过我这个源码去自己去制作一份电子书是可以的,你把自己登陆自己的微信,然后去查看自己加入的星球,然后去下载这些精华帖。
声明:本知识只用于自己技术研究,不参与任何商业行为所获取的知识星球内容,请不要到处传播,违者后果自负
先看一下效果图,今天只是小试牛刀,只制作了txt版本的电子书,因为txt中插入不了图片与链接,所以这个问题留在下一篇文章进行优化.制作成pdf版本 支持链接,图片,目录等,所以大家记得关注.
先看一下效果图,我加入了那些知识星球.以及电子书的内容.
部分星球节选
生成的txt电子书内容格式
开始分析
一开始我是准备用charles 来通过手机App来抓取知识星球数据,但发现链接不上,数据一直是unkonw,我只能放弃了. 我用的是iOS 11.4.1。然后我就打算从网页端入手, 登录知识星球web端,然后按F12进入开发者模式.然后发现所有的数据一目了然,然后我进行深入分析了.
登录知识星球网页端
浏览器输入网址: https://wx.zsxq.com/dweb/#/login 这里直接是扫码登录,登录后我把浏览器中的cookie复制出来,因为后面做Python请求要做请求头会用到. 登录之后就可以获取到我们加入了那些知识星球的相关信息.
这里直接复制了开发者模式下的response中请求头的信息,而且其实所有的请求头信息都是一样的,这里可以直接放在全局里.
代码语言:javascript复制 headers_group = {
'Accept': 'application/json, text/plain, */*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Cookie': self.my_cookie,
'Host': 'api.zsxq.com',
'Origin': 'https://wx.zsxq.com',
'Referer': 'https://wx.zsxq.com/dweb/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36',
}
获取当前用户进入了那些知识星球的名称与群组
因为我加的星球比较多,所以我需要获取这些星球的名称与编号,因为尤其是名称,在我制作电子书的书名会用到,另外编号是我要做请求的时候要获取具体某个星球的内容.
可以在开发者模式中看到获取精华贴的请求用到的接口. 下面我这里展示了一下关键代码.
代码语言:javascript复制 url_groups = 'https://api.zsxq.com/v1.10/groups'
response = requests.get(url=url_groups, headers=headers_group) # 一定要加headers,规范写法,就像过马路一样穿红灯有时没事,有时要命!
if response.status_code == 200: # 注意:这里一定要做200判断,
datas = json.loads(response.text, encoding="utf-8").get('resp_data').get('groups') # 把unicode 编码改成中文 ,所以这里编码方式要用到utf-8
for data in datas:
self.zsxq_group_id.append(data.get('group_id'))
self.zsxq_group_name.append(data.get('name'))
获取精华贴内容
点击获取知识星球的精华选项,可以找到获取精华贴的请求,根据精华贴的请求,可以获取到精华内容.
分析可以得到内容分为三种类型: talk ,q&a,jpg 这三种类型,而今天我暂时只分析前面两种的类型.
代码语言:javascript复制 url_content = 'https://api.zsxq.com/v1.10/groups/{}/topics?scope=digests&count=20&end_time={}'.format(
group_id,
self.end_time)
print(url_content)
response = requests.get(url=url_content, headers=content_group) # 一定要加headers,规范写法,就像过马路一样穿红灯有时没事,有时要命!
if response.status_code == 200: # 注意:这里一定要做200判断,
topics = json.loads(response.text, encoding="utf-8").get("resp_data").get(
"topics") # 把unicode 编码成 utf-8
获取每个帖子的具体内容
其实帖子分三种模式:talk,q&a,jpg 三种模式,我这里由于是要制作txt电子书,所以我忽略了图片模式的处理,也没有把图片插入文件中,下一篇文章会优化一下.
代码语言:javascript复制 for topic in topics:
try:
if topic.get('type') == 'talk' and topic.get('talk'): # 会话模式的
text = topic.get('talk').get('text').replace('n', '') # 获取正文内容
title = text[0:10] if len(text) > 10 else text
author = topic.get('talk').get('owner').get('name') # 获取作者名称
create_time = topic.get('create_time')[:10] # 获取最后更新时间
# images = topic.get('talk').get('images') # 获取图片列表
self.save_zsxq_txt(group_name, title, author.strip(), create_time, text)
# if images is not None:
# for image in images:
# imgUrl = image.get('large').get('url')
# print(imgUrl)
# else:
# print('没有图片')
# print(author, text, modify_time)
elif topic.get('type') == 'q&a' and topic.get('question'):
author_question = topic.get('question').get('owner').get('name') # 获取提问者的名称
author_answer = topic.get('answer').get('owner').get('name') # 获取回答者的名称
text_question = topic.get('question').get('text').replace('n', '') # 获取提问正文
text_answer = topic.get('answer').get('text').replace('n', '') # 获取回答正文内容
title = text_question[0:10] if len(text_question) > 10 else text_question # 标题
text = '{}的提问:{}nn{}的回答:{}'.format(author_question, text_question, author_answer,
text_answer) # 获取正文内容
author = author_question '&' author_answer
create_time = topic.get('create_time')[:10] # 获取最后更新时间
# images = topic.get('question').get('images') # 获取图片列表
self.save_zsxq_txt(group_name, title, author.strip(), create_time, text)
# if images is not None:
# for image in images:
# imgUrl = image.get('large').get('url')
# print(imgUrl)
# else:
# print('没有图片')
# print(author, text, modify_time)
except Exception as e:
print(e.args)
帖子标题
一般帖子可能没有标题,所以我取文字的前面10个文字为标题, 实在没有的,就是无标题. 因为我这里暂时没有处理内容模式为图片模式的,后面文章要进一步优化
代码语言:javascript复制 text = topic.get('talk').get('text').replace('n', '') # 获取正文内容
title = text[0:10] if len(text) > 10 else text
翻页问题
代码语言:javascript复制精华页的翻页尤其注意这个end_time
url_content = 'https://api.zsxq.com/v1.10/groups/{}/topics?scope=digests&count=20&end_time={}'.format(
group_id,
self.end_time)
经观察发现,每页最后一条内容的创建时间与下一个时间戳有关,
代码语言:javascript复制 first_time = create_time[:10] # 前一部分时间
middle_time = create_time[10:-4] # 中间一部分时间
last_time = create_time[-4:] # 最后一部分时间
change_middle_time = middle_time.replace(middle_time[-4:-1], str(int(middle_time[-4:-1]) - 1).zfill(
3)) # 1. 网页列表的时间戳,发现规律,时间戳倒数第5位会比前面最后一页的时间戳少1 2. zfill方法可以在左边补0 凑成3位
self.end_time = first_time urllib.parse.quote(change_middle_time) last_time
每个知识星球生成txt文件
把内容写入文件中,并设定好内容格式,效果图见文章头部的效果图,暂时只做了txt ,后续文章会优化.
代码语言:javascript复制 def save_zsxq_txt(self, group_name, title, author, create_time, content):
try:
txt_path = u'd:/zsxq'
txt_name = u'{}.txt'.format(group_name)
# 写入txt文本
with open(txt_path '/' txt_name, 'a', encoding='utf-8') as f:
msg = '标题: {}n作者:{}n创建时间:{}nn{}nnnnn'.format(title, author, create_time, content)
f.write(msg)
except Exception as e:
print(e.message)
最后
核心代码已经提供了,另外要注意里面的异常处理情况,因为我要获取我所有的星球内容,所以记得遍历一下群组.
遗留问题:这里只是txt 文件,放在kindle阅读还不错,但帖子中的链接,图片没有办法展示,所以下一篇会优化一下,另外还想生成目录,方便查阅,敬请关注.