爬虫实战系列(九):知乎热榜全爬取及词云制作
声明:本博客只是简单的爬虫示范,并不涉及任何商业用途。
一.前言
今天正值国庆中秋双节,但作为一个技术宅的我仍然是在寝室度过,在下午我还是习惯性地打开知乎,结果发现《姜子牙》冲到了知乎热榜第一,而我最近也有意向去看这部国产动漫。于是不了解风评的我准备利用爬虫+词云图对《姜子牙》的评价进行可视化,然后决定一波到底要不要去看,顺带的我也把热榜其他问题和对应的全部回答也扒了下来,下面是热榜全爬取的详细记录。
二.爬虫过程
2.1 所有问题对应回答页面链接获取
首先,进入知乎热榜页面(展示如下图),可以看到热榜中一共包括了50个问题,这些问题的所有回答都是我们要爬取的目标。
随机选中一个问题右键检查即可查看所有的元素都包含在一个<section>...</section>
块中,即:
我们点开其中的一个元素,可以发现对应的问题及其所指向的链接,即我们需要的链接:
2.2 获取单个问题页面的全部回答
在解决了热榜所有问题的链接获取之后,下面的问题就是如何爬取单个页面的所有回答了,我们打开《姜子牙》的链接,可以看到如下页面:
需要注意的是:该页面的所有回答并不会全部显示出来,而是当滚动条滚动到底部后才会出现新的回答,即它采用了Ajax 动态加载的技术。那该问题如何解决呢,我在开发者工具中,选中请求类型为XHR
,结果果然看到了评论数据(json格式):
我又继续滚动滑动条几次,得到如下几个链接:
https://www.zhihu.com/api/v4/questions/337873977/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=5&platform=desktop&sort_by=default
https://www.zhihu.com/api/v4/questions/337873977/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=10&platform=desktop&sort_by=default
https://www.zhihu.com/api/v4/questions/337873977/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=15&platform=desktop&sort_by=default
观察上述链接我们可以看到变化的只有offset
字段,而且是加5递增的,因此我们只需要改变该链接的offset
字段即可获取到对应问题的全部回答所对应的链接。此外,我又打开了其他几个问题得到如下链接:
https://www.zhihu.com/api/v4/questions/337873977/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=5&platform=desktop&sort_by=default
https://www.zhihu.com/api/v4/questions/423719681/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=5&platform=desktop&sort_by=default
https://www.zhihu.com/api/v4/questions/423737325/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=5&platform=desktop&sort_by=default
观察可知,不同问题的回答对应的链接的不同之处只包括问题ID和对应各自问题的offset,因此我们只需要在进入每个问题的回答页面时,将对应的问题ID和回答数获取即可获取包含所有回答的json数据。
注:具体如何从json数据中提取作者和对应的回答的过程就不详细介绍了。
2.3 爬虫结果保存
在爬取的过程中,由于首先要获取到热榜各个问题对应的链接,因此我将各个问题及其对应的回答页面的链接保存了下来,格式为csv,其所包含的字段展示如下:
字段一 | 字段二 |
---|---|
title(问题) | url (问题对应的回答页面) |
另外,对于所有问题的回答都单独存为一个csv文件,每个csv文件包含的字段如下:
字段一 | 字段二 |
---|---|
author(回答者) | content(回答内容,只筛选了其中的中文内容) |
2.4 全过程流程总结
综上,爬虫的全过程已经一目了然了,首先是获取热榜所有问题的链接(顺便可以获取问题ID),然后进入到具体的某个页面获取回答数,然后就可以构造链接来爬取回答了,最后将回答保存为csv格式,即:
三.示例程序及结果展示
import requests
from bs4 import BeautifulSoup
import pandas as pd
import re
import json
import tracebackchinese = '[\u4e00-\u9fa5]+' #提取中文汉字的patternheaders = {'user-agent': '换上自己的User-Agent','cookie': '换上自己的知乎登录cookie'
}def getHots(url='https://www.zhihu.com/hot'):"""功能:获取知乎热榜所有话题的id"""topics = []response = requests.get(url=url,headers=headers)if response.status_code == 200:soup = BeautifulSoup(response.content,'lxml',from_encoding='utf-8')hots = soup.findAll('section',attrs={'class':'HotItem'})for hot in hots:hot_url = hot.find('a').get('href')hot_c = hot.find('a').get('title')print(hot_c,hot_url)topics.append([hot_c,hot_url])Saver(topics,0,['title','url'])return topicsdef getNumber(topic_url):"""功能:获取某个问题的回答数"""response = requests.get(topic_url,headers=headers)if response.status_code == 200:soup = BeautifulSoup(response.content,'lxml',from_encoding='utf-8')string = soup.find('h4',attrs={'class':'List-headerText'}).get_text()number = ''.join([s for s in string if s.isdigit()])return int(number)return 0def getAnswers(question_id,number):"""功能:获取某个问题各个回答question_id:话题idnumber:回答数量"""outcome = []i = 0while i * 5 < number:try:url = 'https://www.zhihu.com/api/v4/questions/{}/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset={}&platform=desktop&sort_by=default'.format(question_id,i*5)response = requests.get(url,headers=headers)if response.status_code == 200:js = json.loads(response.text)for answer in js['data']:author = answer['author']['name']content = ''.join(re.findall(chinese,answer['content']))print(author,content)outcome.append([author,content])i += 1except Exception:i += 1print(traceback.print_exc())print('web spider fails')return outcomedef Saver(datas,idx,columns):"""功能:保存数据为csv格式index:话题索引"""df = pd.DataFrame(datas,columns=columns)df.to_csv('./datas/hot_{}.csv'.format(idx),index=False)def Spider():"""功能:爬虫主函数"""topics = getHots()for idx,topic in enumerate(topics):print('clawling: {} numbers: {}'.format(topic[0],topic[1]))#获取question IDquestion_id = topic[1].split('/')[-1]#获取回答数number = getNumber(topic[1])#爬取对应问题的所有回答datas = getAnswers(question_id,number)#保存回答为.csv格式Saver(datas,idx + 1,['author','content'])if __name__ == "__main__":Spider()
最后爬取的50个问题都保存为了单独的csv文件,然后我分别对其进行了jieba分词,删除停用词,最后利用wordcloud模块都生成了各自的词云图,下面是《姜子牙》的某个问题所对应的词云图:
四.结语
完整项目和数据地址:zhihu_answer_demo
以上便是本文的全部内容,要是觉得不错的话就点个赞或关注一下吧, 你们的支持是博主创作下去的不竭动力,当然若有任何问题敬请批评指正!!!
爬虫实战系列(九):知乎热榜全爬取及词云制作相关推荐
- 爬虫实战(二)—利用requests、selenium爬取王者官网、王者营地APP数据及pymongo详解
概述 可关注微信订阅号 loak 查看实际效果. 代码已托管github,地址为:https://github.com/luozhengszj/LOLGokSpider ,包括了项目的所有代码. 本文 ...
- Python爬虫实战,Request+urllib模块,批量下载爬取飙歌榜所有音乐文件
前言 今天给大家介绍的是Python爬取飙歌榜所有音频数据并保存本地,在这里给需要的小伙伴们代码,并且给出一点小心得. 首先是爬取之前应该尽可能伪装成浏览器而不被识别出来是爬虫,基本的是加请求头,但是 ...
- python爬虫实战笔记---以轮子哥为起点Scrapy爬取知乎用户信息
开发环境:python3.5+Scrapy+pycharm+mongodb 思路: 1.选定起始人:选定一个关注数量或粉丝数量多的大佬 2.获取粉丝和关注列表 3.获取列表用户信息 4.获取每位用户粉 ...
- python爬取知乎热搜_python爬取知乎
大小: 1.59M 文件类型: .zip 金币: 1 下载: 0 次 发布日期: 2021-01-30 资源简介 此项目的功能是爬取知乎用户信息以及人际拓扑关系,爬虫框架使用scrapy,数据存储使用 ...
- Scrapy爬虫实战| 手把手教你使用CrawlSpider框架爬取数码宝贝全图鉴
大家好,之前给大家分享过Scrapy框架各组件的详细配置,今天就来更新一篇实战干货:CrawlSpider框架爬取数码宝贝全图鉴.可能本文爬的这个网站你不感兴趣,但我希望你能通过下面的爬取分析.操作中 ...
- 爬虫实战(一)猫眼电影基础数据爬取
看完爬虫基础,是不是有点心动手痒了呢?那么接下来就让我们一起学习如何爬虫吧. 写在爬虫之前 选这个题目的初衷:本人是一个学生党,经济来源较少但平时又特别爱看电影,又没时间关注电影票价的变动,有了这个爬 ...
- 爬虫实战:嗅事百科段子多页爬取
假如我们想爬取糗事百科( http://ww qiushibaike.com/)上的段子,也可以编写对应的Python网络爬虫实现. 本项目糗事百科网络爬虫的实现思路及步骤如下: 分析各页间的网址规律 ...
- python爬虫动态解析js_Python爬虫实战入门五:获取JS动态内容—爬取今日头条
F12打开网页调试工具: 选择"网络"选项卡后,发现有很多响应,我们筛选一下,只看XHR响应.(XHR是Ajax中的概念,表示XMLHTTPrequest)然后我们发现少了很多链接 ...
- python爬虫爬取今日头条_Python爬虫实战入门五:获取JS动态内容—爬取今日头条...
之前我们爬取的网页,多是HTML静态生成的内容,直接从HTML源码中就能找到看到的数据和内容,然而并不是所有的网页都是这样的. 有一些网站的内容由前端的JS动态生成,由于呈现在网页上的内容是由JS生成 ...
- #私藏项目实操分享#Python爬虫实战,requests+xpath模块,Python实现爬取豆瓣影评
前言 利用利用requests+xpath爬取豆瓣影评,废话不多说. 让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: requests模块: jieba模块: pandas模 ...
最新文章
- Wiley-中国科学院文献情报中心开放科学联合研讨会第一讲:开放科学全球和中国发展态势...
- Yours的Ryan X Charles谈BCH驱动社交媒体
- 如何通过审计安全事件日志检测密码喷洒(Password Spraying)攻击
- #180111mysql启动错误
- mysql主要有什么问题_mysql问题
- python工资一般多少大专学历-这个面试官真霸气 不收大专程序员
- 在.NET环境中实现每日构建--NAnt篇
- 更改boot.ini自动进入DSRM模式
- JSON Web Token从入门到精通
- java导入包srcy有红叉_eclipse导入web项目之后项目中出现小红叉解决办法
- 什么原数据更容易平稳_时序数据处理难题攻略(上)
- css loader.net,css-loader style-loader原理探究
- windows server 2003 asp环境搭建
- python_判断是否回文
- 新能源车企凶猛下沉,“新车商”会是一条捷径吗?
- Netty in Action 翻译说明
- 扫雷小游戏(超详细)
- 密码爆破工具——九头蛇(hydra)
- 迁移过程中出现报错:无法解析的成员访问表达式[USERENV]
- 罗马java_罗马数字转换阿拉伯数字(Java版,考虑较为全面)
热门文章
- GaussDB的行存表与列存表的选择
- CSU 1684-Disastrous Downtime(set+二分)
- 小议:SharePoint 2013不能把Shred Storage Disable的解决方案?
- 基于python的空气质量预测分析可视化系统
- python适用subprocess在ubuntu下运行shell
- Maven mac下载和安装
- python用函数绘制椭圆_python – 通过轨道数据拟合椭圆
- Python从入门到精通 学习教程
- IT人必看 | 2022年春招市场行情报告——高薪职业榜首是这些!
- IIS 之 连接数、并发连接数、最大并发工作线程数、队列长度、最大工作进程数