利用PYTHON爬取如下图中所有回答的内容,并且制作词云图。
import requests # import json from PIL import Image from pyquery import PyQuery as pq from requests import RequestException import csv from wordcloud import WordCloud, STOPWORDS import numpy as np # import matplotlib.pyplot as plt import jieba import re
需要确保已经安装好以上几个常用的库。具体的操作直接 pip install xxx 就好了,推荐使用国内源安装,具体的请看我的另一篇博客https://blog.csdn.net/qq_41655933/article/details/89637657
话不多说,开始操作!
首先我们要爬取的网址是https://www.douban.com/group/topic/82916031/?start=0
点看第二面 https://www.douban.com/group/topic/82916031/?start=100
发现start变为了100。这样以来,爬取就有规律了。只要每次爬取一个页面,使start值加100就ok了。
于是写出以下代码。
def get_one(page):
"""
爬取一页
:param page: start数
:return: html源码
"""
try:
headers = {
# 'Cookie': 'bid=kCNfNn6nvxA; __utmz=30149280.1564815097.1.1.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __yadk_uid=CvRkxvch6yW4IwpqONlyGzPCB1GznXLV; douban-fav-remind=1; ap_v=0,6.0; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1568964489%2C%22https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3D2p9zSFnHJuYwVjtaUY6Smc_R8lvOe0b5EatQr75zQywo5qIDZ1s5EUIST8Jw0K3qpAoQXJLWDJHTyx6jNbRq-a9MIbUXwkq4V8vrhxYGdqO%26wd%3D%26eqid%3Dd4a8230500089ac3000000055d452e46%22%5D; _pk_id.100001.8cb4=ef75a07b06bad72b.1564815095.2.1568964489.1564815095.; _pk_ses.100001.8cb4=*; __utma=30149280.546149049.1564815097.1564815097.1568964491.2; __utmc=30149280; __utmt=1; __utmb=30149280.3.8.1568964491',
'Host': 'www.douban.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36', # 浏览器标识
}
url = 'https://www.douban.com/group/topic/82916031/?start={}'.format(page) # url
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
except RequestException:
return None
我们在浏览器中,右击网页点击‘检查’选项,进入开发者模式。我们可在elements找到我们想要找到的对象,如下图
蓝色区域就是我们想要爬取的对象。此处解析要用到pyquery,用css选择器表示该对象的路径为:#comments li .reply-doc。
def parse_one(html):
"""
解析一页源码
:param html:html源码
:return:返回生成器,用于迭代
"""
doc = pq(html) # 初始化
items = doc('#comments li .reply-doc').items() # css选择器选择所有该标签
# print(items.size()) # 评论的个数
for item in items:
yield {
'name': item.find('h4 a').text(), # 用户名
'address': item.find('h4 a').attr('href'), # 用户主页
# 'signature': item.find('h4').text(), # 个性签名
'time': item.find('h4 span').text(), # 回复时间
'reply': item.find('p').text(), # 回复内容
'quote-reply': item.find('.reply-quote .short').text(), # 引用的回复内容
'quote-user': item.find('.reply-quote .pubdate').text(), # 引用的用户名
'quote-user-addr': str(item.find('.reply-quote .pubdate a').attr('href')).strip() if item.find('.reply-quote .pubdate a').attr('href') else '', # 引用的用户的主页
# 'vote': item.find('.comment-vote').text() # 赞
}
至此,用上面两个函数就可以 利用for循环 将每一页的内容可以爬取下来了。
现在,我们还需要将结果保存下来。
def write_csv(contents):
"""
写入数据到csv文件
:param contents: 解析的内容,可迭代
:return:
"""
with open('douban.csv', 'a', encoding='utf-8') as f: # 追加方式写数据
fieldnames = ['name', 'address', 'time', 'reply', 'quote-reply', 'quote-user', 'quote-user-addr'] # 第一行
write = csv.DictWriter(f, fieldnames=fieldnames, lineterminator='\n') # 消除多余的换行,不加lineterminator会出现每写一行空一行的情况。
write.writeheader()
for content in contents:
print(type(content))
write.writerow(content)
同样的,我们还需要写一个读取csv文件的函数,以便将所有的回复读取出来
def read_csv():
"""
将回复的内容保存在列表中并返回
:return:
"""
reply = []
n = 0
with open('douban.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
if row[4] != 'quote-reply':
reply.append(row[3])
return reply
到这里,爬虫阶段结束。我们还要执行以下代码段以保存所有数据:
for i in range(15): write_csv(parse_one(get_one(i * 100)))
查看保存的文件:
因为wordcloud对中文的分词不友好,所以我们在这里使用jieba分词。结巴分词各位同学可以在github上查看它的介绍,链接如下https://github.com/fxsjy/jieba
def text_chinese():
"""
利用jieba进行中文分词
:return: 分词后的字符串
"""
t = read_csv() # 读取回复内容
text = ''.join(t) # 列表拼接成字符串
text = re.sub('[a-zA-Z0-9\s\[\`\~\!\@\#\$\^\&\*\(\)\=\|\{\}\'\:\;\'\,\[\]\.\<\>\/\?\~\。\@\#\\\&\*\%]+', '', text) # 利用正则表达式,去除字符串中的数字英文等字符。
jieba_list = jieba.cut(text) # jieba给字符串分词,得到分词列表
word_list = ' '.join(jieba_list) # 将分词列表,用空格连接成字符串
print(word_list)
return word_list
准备工作做完了,接下来只需要利用wordcloud生成词云图就完事了。
wordcloud参数含义可参考 https://www.cnblogs.com/delav/articles/7837975.html
# 生成词云图
# con = jieba.cut('jieba是什么东西')
# words = ' '.join(con)
# print(words)
words = text_chinese() # 分词后的字符串
font = r'C:\Windows\Fonts\msyh.ttc' # 字体路径
stopword = set(STOPWORDS) #设置停用词,STOPWORDS为wordcloud自带的英文停用词,其他的可以自己添加。
stopword.add('谢谢')
stopword.update({'可以', '谢谢', '楼主', '希望', '中文名', '英文名', '名字'})
# 图片模板 在这里博主设置的图片为湖北地图。
image = np.array(Image.open('hubei.jpg'))
wc = WordCloud(font_path=font, # 中文必须设置字体,不然图片会显示方框
background_color='white', # 背景为白色
# width=800, # 画布宽度
# height=800, # 画布高度
mask=image, # 图片模版,wordcloud会在图片中非白色的那块填充文字。若有该参数则忽略设置的宽高值。
scale=5, # 按照比例放大画布
stopwords=stopword) # 停用词
wc.generate(words) # 根据文本生成词云
wc.to_file('wordCloud.png') # 保存图片
ima = wc.to_image() # 显示图片
ima.show()
# plt.imshow(wc) # 用plt显示图片
# plt.axis('off') # 设置坐标轴不可见
# plt.show() # 显示图片
运行以上代码可以在当前文件夹查看已经生成好的词云图。
同学们学会了吗?