您好,我是 @马哥python说,一枚10年程序猿。
一、爬取目标
前些天我分享过一篇微博的爬虫:
https://www.cnblogs.com/mashukui/p/16414027.html
但是知乎平台和微博平台的不同之处在于,微博平台的数据用于分析社会舆论热点事件是极好的,毕竟是个偏娱乐化的社交平台。但知乎平台的评论更加客观、讨论内容更加有深度,更加有专业性,基于此想法,我开发出了这个知乎评论的爬虫。
二、展示爬取结果
我在知乎上搜索了5个关于”考研“的知乎回答,爬取了回答下方的评论数据,共计2300+条数据。
https://www.zhihu.com/question/291278869/answer/930193847
https://www.zhihu.com/question/291278869/answer/802226501
https://www.zhihu.com/question/291278869/answer/857896805
https://www.zhihu.com/question/291278869/answer/910489150
https://www.zhihu.com/question/291278869/answer/935352960
爬取字段,含:
回答url、页码、评论作者、作者性别、作者主页、作者头像、评论时间、评论内容、评论级别。
部分数据截图:

三、爬虫代码讲解
3.1 分析知乎页面
任意打开一个知乎回答,点开评论界面:

同时打开chrome浏览器的开发者模式,评论往下翻页,就会找到目标链接:

作为爬虫开发者,看到这种0-19的json数据,一定要敏感,这大概率就是评论数据了。猜测一下,每页有20条评论,逐级打开json数据:

基于此数据结构,开发爬虫代码。
3.2 爬虫代码
首先,导入用到的库:- import requests
- import time
- import pandas as pd
- import os
复制代码 从上面的截图可以看到,评论时间created_time是个10位时间戳,因此,定义一个转换时间的函数:- def trans_date(v_timestamp):
- """10位时间戳转换为时间字符串"""
- timeArray = time.localtime(v_timestamp)
- otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
- return otherStyleTime
复制代码 作者的性别gender是0、1,所以也定义一个转换函数:- def tran_gender(gender_tag):
- """转换性别"""
- if gender_tag == 1:
- return '男'
- elif gender_tag == 0:
- return '女'
- else: # -1
- return '未知'
复制代码 准备工作做好了,下面开始写爬虫。
请求地址url,从哪里得到呢?
打开Headers,找到Request URL,直接复制下来,然后替换:

先提取出一共多少评论,用于计算后面的翻页次数:- url0 = 'https://www.zhihu.com/api/v4/answers/{}/root_comments?order=normal&limit=20&offset=0&status=open'.format(answer_id)
- r0 = requests.get(url0, headers=headers) # 发送请求
- total = r0.json()['common_counts'] # 一共多少条评论
- print('一共{}条评论'.format(total))
复制代码 计算翻页次数,直接用评论总数除以20就好了:- # 判断一共多少页(每页20条评论)
- max_page = int(total / 20)
- print('max_page:', max_page)
复制代码 下面,再次发送请求,获取评论数据:- url = 'https://www.zhihu.com/api/v4/answers/{}/root_comments?order=normal&limit=20&offset={}&status=open'.format(answer_id,str(offset))
- r = requests.get(url, headers=headers)
- print('正在爬取第{}页'.format(i + 1))
- j_data = r.json()
- comments = j_data['data']
复制代码 现在,所有数据都在comments里面了,开始for循环遍历处理:
字段过多,这里以评论作者、评论性别为例,其他字段同理:- for c in comments: # 一级评论
- # 评论作者
- author = c['author']['member']['name']
- authors.append(author)
- print('作者:', author)
- # 作者性别
- gender_tag = c['author']['member']['gender']
- genders.append(tran_gender(gender_tag))
复制代码 其他字段不再赘述。
需要注意的是,知乎评论分为一级评论和二级评论(二级评论就是一级评论的回复评论),所以,为了同时爬取到二级评论,开发以下逻辑:(同样以评论作者、评论性别为例,其他字段同理)- if c['child_comments']: # 如果二级评论存在
- for child in c['child_comments']: # 二级评论
- # 评论作者
- print('子评论作者:', child['author']['member']['name'])
- authors.append(child['author']['member']['name'])
- # 作者性别
- genders.append(tran_gender(child['author']['member']['gender']))
复制代码 待所有字段处理好之后,把所有字段的列表数据拼装到DataFrame,to_csv保存到csv文件里,完毕!- df = pd.DataFrame(
- {
- '回答url': answer_urls,
- '页码': [i + 1] * len(answer_urls),
- '评论作者': authors,
- '作者性别': genders,
- '作者主页': author_homepages,
- '作者头像': author_pics,
- '评论时间': create_times,
- '评论内容': contents,
- '评论级别': child_tag,
- }
- )
- # 保存到csv文件
- df.to_csv(v_result_file, mode='a+', index=False, header=header, encoding='utf_8_sig')
复制代码 完整代码中还涉及到避免数据重复、字段值拼接、判断翻页终止等细节逻辑,详细了解请见文末。
四、同步视频
演示视频:
https://www.zhihu.com/zvideo/1545723927430979584
我是 @马哥python说, 感谢您的阅读。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |