获取知乎回答内容及答主信息

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: 围观几个知乎话题

爱写bug(ID:iCodeBugs)

前言:

围观几个知乎话题:

(https://www.zhihu.com/question/328457531)https://www.zhihu.com/question/328457531

(https://www.zhihu.com/question/297715922):https://www.zhihu.com/question/297715922

(https://www.zhihu.com/question/313825759):https://www.zhihu.com/question/313825759

点开一个问题看一下答主的回答.

点开一个话题,进入开发者工具,刷新页面,在xhr栏目下,会发现很多请求,左上角过滤一下,只有以 answers? 开头的才是回答内容,分析一下请求头:

zhihu_XHR

知乎的请求结构出奇的简单,很意外。关键信息已在图片标明。基础URL是:https://www.zhihu.com/api/v4/questions/313825759/answers?include= 后面全都是根据 Query String Parameters 构造出来的。

然后我们分析一下答主的回答内容:

这里回答内容有可能是引用其他话题 拥有一双大长腿是怎样的体验? 的图片,也就是说,我们只要再把这个引用的话题地址获取下来,再根据新获取的地址构造请求URL, 得到该话题的请求地址,这样就可以顺着一条回答把所有引用的相似问题其他答主的图片全部下载下来。。。

点击引用的其他话题,切换知乎话题 拥有一双大长腿是怎样的体验?

同样看一下该话题的 Query String Parameters 只有 limit 、offset两个属性会变,而limit 为限制当页显示的回答数量,offset 为偏移量,就是本页从第几条回答开始显示,其他属性全是相同的(知乎页面限制显示回答数最大20)。这意味着不管知乎哪个问题都可由该问题的地址以相同的方法构造请求URL:

param = {
        'include': '',#太长了,不展示了
        'limit': '20',  # 限制当页显示的回答数,知乎最大20
        'offset': offset,  # 偏移量
        'platform': 'desktop',
        'sort_by': 'default',
    }
base_URL = 'https://www.zhihu.com/api/v4/questions/297715922/answers?include='  # 基础 url 用来构造请求url
    url = base_URL + urllib.parse.urlencode(param)  # 构造请求地址

再点击 preview 看返回的 json 格式的信息:
zhihu_preview

有个totals,是该话题下总回答数,可以根据这个计算多少次可以遍历全部回答,考虑到后面回答内容质量就跟不上了,我们只获取前800条回答。

展开一条回答:

zhihu_xhr_ans

所有的信息包括答主信息和回答的信息都在了,content内容就是回答内容,复制下来,格式化发现这是css渲染的内容,也能理解,知乎回答必须要用富文本方式编辑,返回的内容必然是这种格式。看一下回答内容:

zhihu_content_xml

这个层次很明了,a 节点的 href 属性就是引用的相关问题的地址。figure 节点 下 noscript 节点下 img节点的 src 属性就是图片地址。用 pyquery 解析:

    for answer in json['data']:
        answer_info = {}
        # 获取作者信息
        author_info = answer['author']
        author = {}
        author['follower_count'] = author_info['follower_count']  # 作者被关注数量
        author['headline'] = author_info['headline']  # 个性签名
        author['name'] = author_info['name']  # 昵称
        author['index_url'] = author_info['url']  # 主页地址
        # 获取回答信息
        voteup_count = answer['voteup_count']  # 赞同数
        comment_count = answer['comment_count']  # 评论数
        # 解析回答内容
        content = pq(answer['content'])  # content 内容为 xml 格式的网页,用pyquery解析
        imgs_url = []
        imgs = content('figure noscript img').items()
        for img_url in imgs:
            imgs_url.append(img_url.attr('src'))  # 获取每个图片地址
        # 获取回答内容引用的其他相似问题
        question_info = content('a').items()
 ......太多不全部展示了,有兴趣可以看一下文末完整源代码

饮水思源保存文件以答主昵称命名,以示尊敬:

def save_to_img(imgs_url, author_name, base_path):
    path = base_path + author_name
    if not os.path.exists(path):  # 判断路径文件夹是否已存在
        os.mkdir(path)
        for url in imgs_url:
            try:
                response = requests.get(url)
                if response.status_code == 200:
                    img_path = '{0}/{1}.{2}'.format(path,
                                                    md5(response.content).hexdigest(), 'jpg')  # 以图片的md5字符串命名防止重复图片
                    if not os.path.exists(img_path):
                        with open(img_path, 'wb') as jpg:
                            jpg.write(response.content)
                    else:
                        print('图片已存在,跳过该图片')
            except requests.ConnectionError:
                print('图片链接失效,下载失败,跳过该图片')
        print('已保存答主:' + author_name + ' 回答内容的所有图片')

以图片内容的 md5 编码命名可以防止重复图片,如果图片被其他人下载之后加水印再上传,图片内容是不同的,所以可能有重复照片。

如果有需要可以把这些数据存到数据库,这里我以mongoDB为例:

#存储在mongoDB
client = MongoClient(host='localhost')
print(client)
db = client['zhihu']
collection = db['zhihu']
def save_to_mongodb(answer_info):
    if collection.insert(answer_info):
        print('已存储一条回答到MongoDB')

zhihu_mongoDB

图中存储了答主引用的其他话题标题及地址,可以把这个地址传回去循环获取,直到所有类似话题图片全部下载。

结语:

​ 大家可根据情况加些判断函数,例如图片中间大概位置的像素点是否相同,来真正的把重复图片去掉。加些人体身材特征值对比,去掉男士的图片和表情图。这个太慢了,有时间的朋友自行发挥

源码地址:https://github.com/zhangzhe532/icodebugs/tree/master/DataAnalysis/zhihu_get_pic

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
6月前
持续输出:自媒体持续输出文字内容、视音频创作(视频课程、书籍章节)
持续输出:自媒体持续输出文字内容、视音频创作(视频课程、书籍章节)
|
6月前
|
前端开发
到 2023年3月17日为止 Jerry 尚未回答或者写作的问题文章列表
到 2023年3月17日为止 Jerry 尚未回答或者写作的问题文章列表
38 0
|
10月前
|
SQL XML 前端开发
怎么做社区网站的首页帖子展示?
要进行首页帖子展示,就必须学会分页,而在创建分页之前,我们得先认识到,为什么要进行分页?一个大型网站的数据库将容纳大量的数据,而我们进行展示某部分数据时,为了保证浏览速度,不可能一次性地将所有数据进行传输,更何况,不是全部传输过去的数据第一时间就能有效利用,所以,只要每次将需要的数据传输过去就好,即使是后续需要的数据,那也是后面时间点需要完成的工作,为了做到这一点,必须对一个数据整体进行划分,合理地传输并展示给用户,其中,划分出来的每一部分可被称为一页数据,完成划分工作的就是分页操作。而分页操作在 spingboot 及 mybatis 的环境下,可被分为以下几种分页情况:
88 0
怎么做社区网站的首页帖子展示?
|
数据采集
【安排】23行代码爬取知乎全部回答(内附源码和应用程序)
上个月行哥为了给大家推荐书单,1分钟爬取了知乎5646个回答,并统计出前十名推荐量最高的书单给大家分享,并且为了大家使用方便将该篇推文中的代码转成应用程序给大家使用,但是万万没想到 居然有小伙伴要求能不能直接让爬虫代码回答爬取下来做成应用程序
228 0
【安排】23行代码爬取知乎全部回答(内附源码和应用程序)
|
NoSQL Java 应用服务中间件
[技术杂谈]最近一段时间值得分享的内容(3)
[技术杂谈]最近一段时间值得分享的内容(3)
142 0
[技术杂谈]最近一段时间值得分享的内容(3)
|
消息中间件 JavaScript Java
[技术杂谈]最近一段时间值得分享的内容(1)
[技术杂谈]最近一段时间值得分享的内容(1)
144 0
[技术杂谈]最近一段时间值得分享的内容(1)
|
消息中间件 Java Docker
[技术杂谈]最近一段时间值得分享的内容(2)
[技术杂谈]最近一段时间值得分享的内容(2)
462 0
[技术杂谈]最近一段时间值得分享的内容(2)
|
JavaScript 前端开发 jenkins
[技术杂谈]最近一段时间值得分享的内容(4)
[技术杂谈]最近一段时间值得分享的内容(4)
204 0
[技术杂谈]最近一段时间值得分享的内容(4)
|
设计模式 运维 架构师
春节假期跟冰河学这些内容(建议收藏)
很多小伙伴问我进大厂到底需要怎样的技术能力,经过几天的思考和总结,终于梳理出一份相对比较完整的技能清单,小伙伴们可以对照清单提前准备相关的技能,在平时的工作中注意积累和总结。
143 0
春节假期跟冰河学这些内容(建议收藏)