使用python3爬取知乎用户信息并分析
参考了:呓语 » 如何写一个简单的分布式知乎爬虫?打算自己做一个python3的分布式爬虫
想要抓取数据,首先分析用户信息页面的构成,以轮子哥为例
红框里的便我们要抓取的用户关键信息(的一部分)。
最上面是我们的目标URL:https://www.zhihu.com/people/excited-vczh/answers。
观察一下这个URL的组成:
http://www.zhihu.com + /people + /excited-vczh + /answer
可以发现只有 excited-vczh 这部分是会变化的,它代表着知乎用户的唯一ID,在知乎的数据格式中,它的键名叫做 urlToken。
所以我们可以用拼接字符串的形式,得到我们待抓取页面的URL:
url='%s/people/%s/answers'%(host,urlToken)
页面URL有了,而且从上图我们可以发现 不登录 也可以访问用户主页,这说明我们可以不用考虑模拟登陆的问题,可以自由的获取用户主页面源码。
那么我们如何从用户主页的源码中获取用户的数据呢?一开始我以为需要挨个匹配页面中对应的部分,但我查看源码的时候发现知乎把用户数据集集中放到了源码的一个地方,那就是 id="data" 的 div 的 data-state 属性的值中,看下图:
从上图我们可以发现,date-state 的属性值中藏有用户的信息,比如我们可以依次找到用户的教育经历(educations)、简介(headline)、参与的 Live 数量(participatedLiveCount)、关注的收藏夹数量(followingFavlistsCount)、被收藏的次数(favoritedCount)、关注他的用户数(followerCount)、关注的话题数量(followingTopicCount)、用户描述(description)等信息。通过观察我们也可以发现,数据应该是以 JSON 格式存储。
知道了用户数据都藏在 date-state 中,我们 用 lxml
把该属性的值取出来,然后作为 JSON 格式读取,再把数据集中存储用户数据的部分提取出来即可,看代码:
html = etree.HTML(request.text)
result = html.xpath("//div[@id='data']/@data-state")
result = json.loads(result[0])
print(result['entities']['users'][urlToken])
选择抓取用户的关注者(follower)列表,我们可以根据知乎的api来抓取用户的关注者列表
关注者列表api: https://www.zhihu.com/api/v4/members/excited-vczh/followers?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset='+str(offset)+'&limit=20'
关注列表api: https://www.zhihu.com/api/v4/members/excited-vczh/followees?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset='+str(offset)+'&limit=20'
每页默认显示20个用户
代码如下:
def getFollowers(self,offset):
getFolloweesUrl ='https://www.zhihu.com/api/v4/members/excited-vczh/followers?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset='+str(offset)+'&limit=20'
req =self.session.get(url=getFolloweesUrl,headers=headers)
hjson = json.loads(req.text)
flag = hjson['paging']['is_end'] #is_end为true结束
for i in range(0,20):
print(hjson['data'][i]['url_token']) #打印用户url_token
offsetFlag= offsetFlag+20 #下一页
注意:使用api获取关注者或关注列表必须登陆,不登陆会报错误代码
关于登录请查看我的GitHub