大概是一个星期之前,我舍友曾让我爬一下知乎几个问题下的所有回答,想看看能不能找到他记忆中的那一条。
虽然这个要求不难,只要把所有的回答内容爬下来再查询一下就可以轻松搞定;但由于当时我只会requests和pandas,不会用任何的数据库,所以这对我来说还是一个特别棘手的事情。我原计划是把所有回答的id和content作为元组加到一个列表里,再用pandas生成dataframe或是Excel。
看似很轻松,不过每一条问题的回答都有三万多条,我一不会多线程/进程,二不会数据库,爬得慢不说,一旦宕机就又得从头做起,那时候我整整弄了两个小时,真是令人头大。
所以我今天重写了一下,虽然还是很乱很简单,却节省了90%的时间。
import pymongo,requests
import multiprocessing as mp
#要抓取的问题的链接
url = 'https://www.zhihu.com/api/v4/questions/277508190/answers?'
#headers和下面的params都可以在Chrome的Network中找到,有关隐私的部分已被我用XXXXXXXXXXXXXXXX代替
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
#offset偏移量,代表每次从第几条回答开始,由于回答数为33018,且每次最多获取20条回答,所以设置最大值为33018,步长20
offset = [offset for offset in range(0,33018,20)]
#连接MongoDB数据库
myclient = pymongo.MongoClient('mongodb://localhost:27017')
#新建“Zhihu”表
Zhihu = myclient['Zhihu']
#新建“Answer”集合
Answer = Zhihu['Answer']
#获取20条答案的Json
def get_answer_json(offset):
params = {
'include': 'XXXXXXXXXXXXXXXX',
'offset': offset,
'limit': 20,
'sort_by': 'default',
'platform': 'desktop'
}
r = requests.get(url,headers=headers,params=params).json()
return r['data']
#将获取的Json写入数据库
def save_to_DB(offset):
data = get_answer_json(offset)
Answer.insert_many(data)
print('已完成{}条回答的采集。'.format(offset+20))
if __name__ == '__main__':
#多进程运行save_to_DB
p = mp.Pool()
p.map_async(save_to_DB,offset)
p.close()
p.join()
因为登录了账号,所以没有用proxies。
有点心急,没有加time.sleep。
Comments | NOTHING