import time
import jieba
from snownlp import SnowNLP
import requests
from bs4 import BeautifulSoup
from wordcloud import WordCloud
from PIL import Image
import numpy as np
# 此函数实现爬取豆瓣top250总榜单
def top_spider():
for i in range(0, 250, 25):
num = str(i)
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/76.0.3809.132 Safari/537.36 '
} # 请求头模拟真人访问
url1 = 'https://movie.douban.com/top250?start='
url2 = '&filter='
url = url1 + num + url2 # 拼接,形成完整的链接
time.sleep(1) # 调用sleep(),令每轮爬取之间暂停一点时间,防止被豆瓣逮住
req = requests.get(url, headers=headers) # requests的get方法爬取
html = req.text
bs = BeautifulSoup(html, 'lxml') # 将爬取的数据放入‘美丽汤’
texts1 = list(bs.findAll('div', class_="pic")) # 获取所有<div class="pic"></div>标签的内容,此标签存储了所有排名
texts2 = list(bs.findAll('div', class_='hd')) # 获取所有<div class="hd"></div>标签的内容,此标签存储了所有电影名
texts3 = list(bs.findAll('span', class_='title')) # 获取所有<span class="title"></span>标签的内容,此标签存储了所有电影的单独页面链接
new_rank, new_name, new_m_url = [], [], [] # 创建空列表,存储每一轮得到的电影排行、电影名和单独页面链接
for j in texts1:
rank = str(j).split('<em class="">')[1].split('<') # 筛选掉多余内容,只留下排行的数字
rank = 'top' + str(rank[0])
new_rank.append(rank)
for k in texts3:
cut = str(k).replace('<span class="title">', '').replace('</span>', '') # 筛选掉多余内容,只留下电影的名称
# 外国电影有外文原名,这里我们就不记录了,将其筛掉
if cut[0] != ' ':
new_name.append(cut)
for u in texts2:
mu = str(u).split('href="')[1].split('">') # 筛选掉多余内容,只留下单独页面的链接
mu = str(mu[0])
new_m_url.append(mu)
for h in range(0,25):
total.append(new_rank[h] + ' ' + new_name[h] + ' ' + new_m_url[h] + '\n') # 将排行、电影名和链接,按行放入total[]中
with open('Top.txt', 'a', encoding='utf-8') as r:
r.write(new_rank[h] + ' ' + new_name[h] + ' ' + new_m_url[h] + '\n') # 写入.txt文件
r.close()
time.sleep(1)
s = (i / 25) + 1
print("已写入Top.txt中")
print('第' + str(s) + '轮榜单爬取完成')
# 此函数实现爬取一个排名为top(用户输入)的电影的全部热门短评
def short_spider(top):
dtop = int(top) - 1
comment = str(total[dtop]).split() # comment是分割total[]后,存储了一行 排行、电影名和链接 的列表
print('正在爬取电影:' + str(comment[1]) + ' 的短评......')
f_url = comment[2] + 'comments?' # 拼接,形成显示全部短评的页面的链接的前半部分
for i in range(0, 240, 20):
if i < 20:
num = ''
else:
num = 'start=' + str(i)
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/76.0.3809.132 Safari/537.36 '
}
f_url2 = '&limit=20&status=P&sort=new_score'
url = f_url + num + f_url2 # 拼接,形成完整的显示全部短评的页面的链接
time.sleep(1)
req = requests.get(url, headers=headers) # requests的get方法爬取
html = req.text
bs = BeautifulSoup(html, 'lxml') # 放入’美丽汤‘
texts = list(bs.findAll('span', class_="short")) # 获得所有<span class="short"></span>标签的内容
for n in texts:
shortP = str(n).replace('<span class="short">', '').replace('</span>', '') # 筛选出短评文字
shortQ = SnowNLP(shortP) # 用snowNLP库,进行简单的中文情感分析,
a = '情感分析:'
if shortQ.sentiments > 0.6000: # snowNLP分析出来一个数字,越接近1,越有可能是正面情感;越接近0,越有可能是负面情感
b = '可能为正面情感'
else:
b = '可能为负面情感'
filename = '短评.txt'
with open(filename, 'a', encoding='utf-8') as r:
r.write(shortP + '\n')
r.write(a + b + '\n\n')
r.close()
print(str(comment[1]) + ' 的短评已写入文件中!')
p = (i / 20) + 1
print('第' + str(p) + '轮短评爬取完成')
time.sleep(1)
# 此函数实现将爬取的短评进行简单的情感分析;然后分词,统计高频词;利用高频词,制作出词云
def main_wordcloud():
# 统计词频
filename = open('短评.txt', 'r', encoding='utf-8')
s = filename.read() # 读取短评文件
words = jieba.cut(s, cut_all=False) # 使用jieba进行分词
word_dict = {} # word_list用于保存每个词语及其频率
word_list = '' # word_list用于保存jieba分出来的全部词语,用于词云制作
for word in words:
# 不统计一个字的词,和情感分析的固定词
if len(word) > 1 and word != '情感' and word != '正面' and word != '可能' and word != '分析' and word != '负面':
word_list = word_list + ' ' + word # 保存进word_list中
if word_dict.get(word):
word_dict[word] = word_dict[word] + 1 # 保存进word_dict中,每有重复的,频率+1
else:
word_dict[word] = 1
# 按频率进行排序
sort_words = sorted(word_dict.items(), key=lambda x: x[1], reverse=True)
print('高频词如下:')
print(sort_words[0:101]) # 输出频率前0-100的词
# 创建一个词云对象
# 讀取欲做掩膜的圖片
mask = np.array(Image.open(r"C:\Users\Yeerealrainstar\Desktop\papa\tree.jpg"))
wc = WordCloud(
background_color="white", # 背景颜色白色
font_path="C:\Windows\Fonts\FZSTK.TTF", # 使用系统自带的中文字体
mask=mask,max_words=4000
)
wc.generate(word_list)
wc.to_file("WorldCloud.png") # 保存词云图像
print('词云已绘制完成,图片保存在项目根目录')
total = [] # 存储榜单信息
top_spider()
top = input('请输入你想爬取的电影的排名,之后会爬取其短评:')
print('开始爬取短评。')
short_spider(top)
main_wordcloud()