爬虫系列之知乎
“ 今天要爬取的目标网站是知乎,获取知乎上某个(如何看待山东的合村并居政策?)问题的所有回答,并对回答进行文本分析(分词、词频统计、抽取关键词及生成词云)”
继爬虫系列之大众点评、爬虫系列之微博之后,今天继续推送 有关知乎的爬虫。仍然采用python的requests库发送网络请求,cookies信息依然采用在chrome浏览器F12状态下进行复制粘贴。虽然网上有大量关于使用selenuim自动登录知乎,解决手动复制cookies的缺点,但经过多次尝试发现两点:
1 使用selenuim 工具,手机号+密码方式,点击登录按钮无反映,失败
2 使用selenuim 工具, qq号+密码方式, 登录成功,但是点击搜索问题按钮无反映,失败。因此手动复制cookies是我认为目前较为方便稳妥的方式。后续会针对爬虫自动登录问题进行详细讲解。本文共分为三个部分爬虫步骤、爬虫代码、爬虫结果。
本文的环境配置和之前是一致的(爬虫系列之大众点评),后续推出的网易音乐爬虫、微信公众号爬虫、豆瓣电影爬虫都是使用此配置。
01
—
知乎爬虫步骤
知乎爬虫关键步骤:
登录知乎,明确“如何看待山东的合村并居政策?” 的url
https://www.zhihu.com/question/393313903/answer/1231430180,点击下图中的“查看全部2194个回答”
此时大家会发现,答案会展开,但是不会显示所有的回答。F12进入开发者模式,如下图所示,选择XHR,
其中 answers?********就是返回给我们的数据。
点击第一个answers?*******, 选择headers获取cookies,选择preview获取data信息。如下图。
到这里,我们已经找到了要爬取的信息,同时requests发送请求的url,查询 参数及cookies都可以获得。
下一步就是在data数据中获取需要的字段,可以发现data是json格式,可以直接requests().json进行解析。
继续分析,我们发现知乎回答的页面末端没有页码标记,当我们下拉页面时,回答会自动的增加,这就是ajax技术啦(网址不变,网页内容更新,豆瓣网站也是如此),面对此类网站,我们在构造下一页时,可以观察xhr返回的url规律,在answers?************链接中,每次变动的参数只有 offset 。并且每次移动5个量,即每次下拉答案页面,会增加5个回答。
至此,在经过F12分析后,我们做了明确url地址、详细页解析、下一页url构造的工作。具体的爬虫代码在第二部分。
02
—
爬虫代码
知乎爬虫代码,结果保存在合村并居.xlsx
注意添加自己的cookie信息
# time : 2020/6/24 10:29
# author :wujiajia
# email :aaa@qq.com
# file : gzh_zhihu_requests_v2.py
# Software: PyCharm
# python_version:
# funcation:
# 功能:爬取知乎某个问题下的所有评论
# 知乎评论爬虫特点:ajax响应, 需要解析url 地址。登入知乎账号后,找到某个问题的所有评论,
# <-- 查看network 中的 answers 的 xhr 信息, 解析它的url地址。
import pandas as pd
import requests
import time
zid = [] # 保存用户id
ztime = [] # 保存用户发表评论的时间
zname = [] # 保存用户姓名
zcomment = [] # 保存用户评论内容
totals = [] # 记录评论的总条数
def zhuhuSipder(page):
url = "https://www.zhihu.com/api/v4/questions/393313903/answers" # 合村并居 url
# url = "https://www.zhihu.com/api/v4/questions/264739425/answers" # 全国吃辣排行榜
# 必须添加cookie 信息
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0',
"cookie": '自己的cookies',
}
data = { # 这个data 就是 xhr 中 的查询参数
"include": "data[*].is_normal,admin_closed_comment,reward_info,is_collapsed,annotation_action,annotation_detail,collapse_reason,is_sticky,collapsed_by,suggest_edit,comment_count,can_comment,content,editable_content,voteup_count,reshipment_settings,comment_permission,created_time,updated_time,review_info,relevant_info,question,excerpt,relationship.is_authorized,is_author,voting,is_thanked,is_nothelp,is_labeled,is_recognized,paid_info,paid_info_content;data[*].mark_infos[*].url;data[*].author.follower_count,badge[*].topics",
"limit": "5", #
"offset": str(page),
"platform": "desktop",
"sort_by": "default"
}
data_html = requests.get(url=url, params=data, headers=headers).json() # 返回 json 信息, 5个用户一页
# 将毫秒数变成 日期格式
def timestamp_to_date(time_stamp, format_string="%Y-%m-%d %H:%M:%S"):
time_array = time.localtime(time_stamp)
str_date = time.strftime(format_string, time_array)
return str_date
# print(timestamp_to_date(data_html[0]["created_time"]))
for i in data_html["data"]:
id = i['author']['id']
name = i['author']['name']
comment = i["content"]
time_ = timestamp_to_date(i["created_time"])
# print(name + str(id) + ":" + comment)
zid.append(id)
ztime.append(time_)
zname.append(name)
zcomment.append(comment)
totals_ = data_html["paging"]["totals"] # 评论总条数
totals.append(totals_)
# print(totals[0])
return totals[0]
# 多页爬虫
def mulitypage():
page = 0
zhuhuSipder(page)
time.sleep(10)
while (page < totals[0]):
print("正在抓取第{}页".format(int(page / 5)))
page += 5
zhuhuSipder(page)
# 保存数据
def savedata():
v = list(zip(zid, ztime, zname, zcomment))
print(v)
pd.DataFrame(v, columns=["id", "time", "name", "comment"]).to_excel("合村并居.xlsx")
if __name__ == "__main__":
mulitypage()
savedata()
03
关键词抽取及词云
获取知乎的回答内容后,文本中有大量的html标记。文本分析的首要工作就是数据清洗喽,去除html标记。
下面对excel数据进行清洗,运用jieba对清洗后的数据进行关键词抽取,保存在"关键词.txt"。作为下一步词云的输入数据。
# time : 2020/6/24 13:56
# author :wujiajia
# email :aaa@qq.com
# file : gzh_data_wash.py
# Software: PyCharm
# python_version:
# funcation:
import pandas as pd
import re
import jieba
df = pd.read_excel("合村并居.xlsx")
comment = df["comment"]
# print(comment)
rawdata = []
cut_rawdata = []
for i in comment:
# print(i.replace("<p>",""))
#re.sub 可以使用 或 条件
# print(re.sub("<p>|</p>|<figure.*?</figure>|<p.*?br/>|<br/>|<a .*?</a>|<h2>.*?</h2>|<hr/>|<b>|</b>|<ul>|</ul>","",i))
comment_line = re.sub("<p>|</p>|<figure.*?</figure>|<p.*?br/>|<br/>|<a .*?</a>|<h2>.*?</h2>|<hr/>|<b>|</b>|<ul>|</ul>","",i)
# print(type(comment_line))
rawdata.append(comment_line)
for i in range(0, len(rawdata)):
t = jieba.lcut(rawdata[i])
cut_rawdata.append(" ".join(t))
def savetext(rawdata):
for i in range(0, len(rawdata)):
t = jieba.lcut(rawdata[i])
with open("fenci.txt",'a',encoding="utf-8") as f:
f.write(" ".join(t))
# savetext(rawdata)
# jieba 对抽取关键词
import jieba.analyse
#index =0
se_ = []
for i in range(0, len(cut_rawdata)):
# print(abstract_df["abstract"][index])
abstract_s = "".join(cut_rawdata[i])
# print(" ".join(jieba.analyse.extract_tags(abstract_s,topK=5,withWeight=False)))
names = " ".join(jieba.analyse.extract_tags(abstract_s, topK=10, withWeight=False))
se_.append(names)
with open("关键词.txt",'a',encoding="utf-8") as f:
f.write(names)
# print(se_)
# jieba_tf_idf = pd.DataFrame({"jieba_tfidf": se_})
# print(jieba_tf_idf)
制作词云
from wordcloud import WordCloud
import PIL.Image as image
import numpy as np
with open("关键词.txt",'r',encoding="utf-8") as f:
# print(f.read())
text = f.read()
# 背景图片
mask = np.array(image.open("山东省地图白.jpg")) # 背景图片一定要是白色底。形状为非白色的。
wordcloud = WordCloud(mask=mask,font_path="C:\Windows\Fonts\STXINGKA.TTF").generate(text)
image_produce = wordcloud.to_image()
image_produce.show()
词云结果展示
老规矩代码及数据获取方式,关注公众号回复【知乎】即可领取案例教程。
写在最后:这是爬虫系列的第三篇文章,后续还有网易云音乐、豆瓣电影等。但主要针对的是文本数据,后续将在财经数据进行扩展。爬虫系列完结后,会为大家继续数据挖掘、文本分析的讲解。
欢迎关注转发,用案例教你学python!