根据关键词组合,爬取知乎某个问题下所有含有关键词的回答

   在浏览知乎问题过程中,为了通过关键字快速定位到自己想要的回答,写了这个爬虫程序。可以根据问题ID和关键词组合,保存所有含有关键词的回答。源代码下载:Luoxiaoxu’s github

  其中,必须含有的关键词以空格间隔,或含有的关键词以+间隔,例如,查找知乎ID为23437659的问题:“国内你最喜欢的城市(除家乡外生活过的城市)是哪里?为什么?”,要求回答中含有杭州,同时含有南京或武汉,则输入关键词为“杭州 南京+武汉”。其中,问题ID从问题链接中即可得到,如上述问题链接为https://www.zhihu.com/question/23437659,问题ID即为链接后面的数字。

1
2
请输入问题编号:23437659
请输入关键字(同时含有以空格间隔,或含有用+间隔):杭州 南京+武汉

  符合条件的回答保存在csv文件和txt文件中,其中,csv文件只含有所有符合条件的回答的链接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/user/bin/python
#-*-coding:utf-8-*-
#author:luoxiaoxu
#blog:xiaoxu.online
#Filename: ZhihuSpider_keywords.py
#Function: 爬取知乎问题中含有特定关键词的回答

from bs4 import BeautifulSoup
import requests
import os
import re
import time
import csv
import json

def GetAnswer(*Question_ID):
if len(Question_ID)==0:
Question_ID=input("请输入问题编号:")
keyword=input('请输入关键字(同时含有以空格间隔,或含有用+间隔):') # 例如,必须含有杭州,同时含有武汉或南京,输入“杭州 武汉+南京”
keywords=keyword.split() #下载全部答案,直接enter
if keyword=='':
keyword='无'
headers = {'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"\
" AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"}
limit=10 #每次显示的答案个数
offset=0 #下一次显示的回答偏移量
total_num=10 #答案个数,初始设为limit
browse_num=0 #已经遍历的回答个数
record_num=0 #含关键字的回答个数
title=''
if not os.path.exists('知乎下载/'):
os.makedirs('知乎下载/')
print('\n正在爬取……\n')
while browse_num<total_num:
url = "https://www.zhihu.com/api/v4/questions/{Question_ID}/answers?include=content&limit="\
"{limit}&offset={offset}&platform=desktop&sort_by=default"\
.format(Question_ID=str(Question_ID),limit=str(limit),offset=str(offset))
res=requests.get(url,headers=headers)
try:
res=json.loads(res.content)
except:
print('问题编号输入错误!\n')
return None
total_num=res['paging']['totals']
cons=res['data']

if cons is not None:
if total_num<=0:
print('该问题暂时无答案!')
break
if title=='':
title=cons[0]['question']['title']
path_csv,path_txt=CreativeFile(title,keyword) #创建csv和txt文件,csv文件为保存所有含有关键词回答的链接列表
for con in cons:
browse_num+=1
Re=re.compile(r'<[^>]+>',re.S)
answer_detail=Re.sub('',con['content']) #获取具体回答内容
flag=True
if len(keywords)>0:
flag=HasKeywords(answer_detail,keyword) #查询是否有关键词
if flag:
record_num+=1
author_name=con['author']['name']
author_url='https://www.zhihu.com/people/'+con['author']['url_token'] if not author_name=='匿名用户' else ' '
answer_url='https://www.zhihu.com/question/'+str(Question_ID)+'/answer/'+str(con['id'])
Save2File_csv(path_csv,[str(record_num)+'.',author_name,answer_url,author_url])
answer_txt=[str(record_num)+'.',author_name+' 主页:'+author_url]
answer_txt.append('\n\n链接:'+answer_url+'\n')
answer_txt.append('\n'+answer_detail+\
'\n-------------------------------------------------------------------------------\n')
Save2File_txt(path_txt,answer_txt)
print('已保存第%d个回答\n'%record_num)
offset+=len(cons)
if len(cons)<limit: #已爬取到最后一页
break
if len(keywords)==0:
print('爬取完成,已保存全部%d个回答!\n'%record_num)
elif record_num>0:
print('爬取完成,已保存%d个与关键词有关的回答!\n'%record_num)
else:
os.remove(path_csv)
os.remove(path_txt)
print('未找到与关键词有关的答案\n')



def Save2File_csv(path,content):
f=open(path,'a+')
writer=csv.writer(f)
writer.writerow(content)
f.close()

def Save2File_txt(path,contents):
f=open(path,'a+',encoding='utf-8')
for content in contents:
f.writelines(content)
f.writelines('\n')

def HasKeywords(answer_detail,keyword): #判断是否含有所有关键词
flag=True
for key in keyword.split():
flag2=False
for sub_key in key.split('+'):
flag2=flag2 or answer_detail.find(sub_key)>0
if flag2:
break
flag=flag and flag2
if not flag:
return False
return True

def CreativeFile(title,keyword):
path_csv='知乎下载/'+title+'.csv'
path_txt='知乎下载/'+title+'.txt'
if os.path.exists(path_csv): #若文件存在,清空
f=open(path_csv,'w')
f.seek(0)
f.truncate()
f.close()
if os.path.exists(path_txt):
f=open(path_txt,'w')
f.seek(0)
f.truncate()
f.close()
Save2File_csv(path_csv,[title])
Save2File_csv(path_csv,['关键字:'+keyword])
Save2File_csv(path_csv,['序号','作者昵称','回答链接','主页链接'])
Save2File_txt(path_txt,[title,'关键字:'+keyword+'\n'])
return path_csv,path_txt


if __name__=='__main__':
GetAnswer()