目标

利用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

话不多说,开始操作!

爬虫阶段

1. 获取网页源码

首先我们要爬取的网址是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

2. 解析HTML

我们在浏览器中,右击网页点击‘检查’选项,进入开发者模式。我们可在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循环 将每一页的内容可以爬取下来了。

现在,我们还需要将结果保存下来。

3. 保存数据到csv文件

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文件的函数,以便将所有的回复读取出来

4. 读取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

5.执行代码

到这里,爬虫阶段结束。我们还要执行以下代码段以保存所有数据:

for i in range(15):

write_csv(parse_one(get_one(i * 100)))

查看保存的文件:

词云图阶段

1.分词

因为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

2.wordcloud 制作词云图

准备工作做完了,接下来只需要利用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() # 显示图片

结束

运行以上代码可以在当前文件夹查看已经生成好的词云图。

同学们学会了吗?

Logo

加入社区!打开量化的大门,首批课程上线啦!

更多推荐