您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:python爬取晋江文学城小说评论(情绪分析)

51自学网 2021-10-30 22:44:20
  python
这篇教程python爬取晋江文学城小说评论(情绪分析)写得很实用,希望能帮到您。

1. 收集数据

1.1 爬取晋江文学城收藏排行榜前50页的小说信息

获取收藏榜前50页的小说列表,第一页网址为 ‘http://www.jjwxc.net/bookbase.php?fw0=0&fbsj=0&ycx0=0&xx2=2&mainview0=0&sd0=0&lx0=0&fg0=0&sortType=0&isfinish=0&collectiontypes=ors&searchkeywords=&page=1' , 第二页网址中page=2,以此类推,直到第50页中page=50。爬取每个小说的ID,小说名字,小说作者。将爬取到的信息存储到晋江排行榜【按收藏数】.txt文件中。

import requestsfrom bs4 import BeautifulSoupimport bs4import reimport csvimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport jiebaimport seaborn as snsimport xlrdfrom xlutils.copy import copy# 一些魔法命令,使得matplotlib画图时嵌入单元中而不是新开一个窗口%matplotlib inlineplt.rcParams['figure.figsize'] = (10.0, 8.0) # set default size of plotsplt.rcParams['image.interpolation'] = 'nearest'plt.rcParams['image.cmap'] = 'gray'%load_ext autoreload%autoreload 2from sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.naive_bayes import MultinomialNBfrom sklearn import metricsfrom sklearn.model_selection  import train_test_split
  1. 爬取小说基本信息 ,主要思路;
  2. 找到需要爬取的所有信息主体tbody;
  3. 分别找到每个信息对应的小标签td(a),数清楚在所有标签中的顺序;
  4. 存进txt文档时按顺序存储。
headers = {"User-Agent": "Mozilla/5.0"}for n in range(1,50):    url = 'http://www.jjwxc.net/bookbase.php?fw0=0&fbsj=0&ycx0=0&xx2=2&mainview0=0&sd0=0&lx0=0&fg0=0&sortType=0&isfinish=0&collectiontypes=ors&searchkeywords=&page={}'.format(n)    html = requests.get(url,headers=headers)    html.encoding = html.apparent_encoding    soup = BeautifulSoup(html.text, 'html.parser')    for tr in soup.find_all('tbody'):            tds=tr('td')              a = tr('a')             count=0            id=[]            for u in tr.find_all('a'):                    count=count+1                    book_url=u.get('href') # 获取小说主页的url                    p = re.compile(r'/d+')                    book_id = p.findall(book_url)[0]  # 获取小说ID                    if(count%2==0):                        id.append(book_id)            for n in range(0,100):                    with open('./data/晋江排行榜【按收藏数】.txt','a+',encoding='utf-8') as f:                            print("{0}/t{1}/t{2}".format(id[n],a[n*2+1].string,a[n*2].string),file=f)  # 序号 书名 作者

1.2 查看爬虫结果 

分别查看前8部小说的ID和名字

# 查看收藏榜前8部小说的IDwith open('./data/晋江排行榜【按收藏数】.txt','r',encoding='utf-8',errors='ignore') as f:    book_list = f.readlines()    id_list = [item.split('/t')[0] for item in book_list]print(id_list[:8])
# 查看收藏榜前8部小说的名字name_list = [item.split('/t')[1] for item in book_list]print(name_list[:8])

收藏榜前8部小说名字

1.3 ** 爬取每部小说的评论** 。

找到小说的评论区,第一部小说《天官赐福》的第一页评论网址为 ‘http://www.jjwxc.net/comment.php?novelid=3200611&huati=1' ,3200611是小说ID,1是评论页数,这部小说第二页网址为'http://www.jjwxc.net/comment.php?novelid=3200611&huati=2' 。下一部小说《撒野》的ID是2956313,它的第一页评论网址为'http://www.jjwxc.net/comment.php?novelid=2956313&huati=1' ,以此类推,爬取所有小说的评论和打分。为了避免有一些小说评论数不够多,自己设定每部小说只爬取5页的评论。

爬取思路与爬取小说信息大致相同,不同的是将爬取到的信息存储到xls文件中。

headers = {"User-Agent": "Mozilla/5.0"}with open('./data/晋江排行榜【按收藏数】.txt','r',encoding='utf-8') as f:            book_list = f.readlines()            id_list = [item.split('/t')[0] for item in book_list]for book_id in id_list:    for page in range(1,6):        url="http://www.jjwxc.net/comment.php?novelid={}&huati=1&page={}".format(book_id,page)        html = requests.get(url,headers=headers)        html.encoding = html.apparent_encoding        soup = BeautifulSoup(html.text, 'html.parser')        scores=[]        comments=[]        for item1 in soup.find_all('span',"coltext"):            score=item1('span')            scores.append(score[2].string)        for item2 in soup.find_all('div',"readbody"):            comment=item2('span')            comments.append(comment[0].string)        for i in range(0,len(comments)):            excel = xlrd.open_workbook('./data/jjwxc1.xls')            wb = copy(excel)            w_sheet = wb.get_sheet(0)            sheet = excel.sheets()[0]            nrow = sheet.nrows # 文件行数            w_sheet.write(nrow, 0, book_id)            w_sheet.write(nrow, 1, comments[i])            w_sheet.write(nrow, 2, scores[i])            wb.save('./data/jjwxc1.xls')

2. 数据加载和预处理

预处理包括:

  • 格式转化;上一步将爬取信息存到了xls文件,将xls格式文件转化为csv格式文件方便下一步加载。
  • 数据去重;爬取过程中某些页面爬取了多次,导致csv文件包含重复的行。
  • 短评去重;对同一部小说,或者不同的小说,可能存在评论内容相同的行。
  • 添加情绪标签
  • 去除停用词和分词
  • 短评可视化

2.1 格式转化

使用pandas模块可以快速将xls文件转换为.csv

# 格式转化ex=pd.read_excel("./data/jjwxc.xls")ex.to_csv("./data/jjwxc.csv",encoding="gb18030")
# 加载评论review = pd.read_csv("./data/jjwxc.csv",names=['ID','comment','score'],encoding='gb18030')

2.2 数据去重

去除重复的行

# 去重review = review.drop_duplicates()

2.3 短评去重

去除评论相同的行

# 删除评论内容重复的行review= review.drop_duplicates('comment')review.shape

2.4 添加情绪标签

根据打分的分数来添加情绪标签,观察晋江文学城的打分机制发现,打分区间在[-2,2]内,且打2分的人数占大多数,于是将分数为2的评论看作是好评,情绪标签为1,而低于2分的看作是差评,情绪标签为0。

# 添加情绪标签review['emotion'] = (review.score ==2) * 1
# 打乱顺序review = review.sample(frac=1).reset_index(drop=True)print(review.shape)

2.5 去除停用词和分词

短评内容进行分词并去掉停用词

def review_without_stop(review):    # 打开停用词文件    with open("./data/emotion_stopwords.txt","r",encoding="utf-8") as f:        stop_word = [x.strip() for x in f.readlines()]     all_stop_words = set(stop_word) # 删除停用词中重复的项    # 短评中的非中文字符替换为''    review = re.sub("[^/u4e00-/u9fa5]",'',review)    # 去除全角空白字符    review = review.replace("/u3000","")     # 分词    review = jieba.cut(review)    # 过滤一个字的词    review = filter(lambda x: len(x)>1,review)    # 去除停用词    review = filter(lambda x: x not in all_stop_words,review)    return ' '.join(review)
# 自定义分词字典jieba.load_userdict("./data/emotion_userdict.txt")review['cut_jieba'] = review.comment.apply(review_without_stop)

【注】停用词和分词文件需要自己定义

# 查看一些评论review.head()

查看一些打乱后的评论

# 好评中一些评论包含“不想”,“不喜欢”review[(review['cut_jieba'] == '不想') & (review['emotion'] == 1)]
review[(review['cut_jieba'] == '不喜欢') & (review['emotion'] == 1)]
# 好评中出现的消极情绪词,去除这些评论def change_negtive_like(cut_text):    word_list = cut_text.split()    if "不喜欢" in word_list:        for i in range(len(word_list)):            if word_list[i] == "不喜欢":                word_list[i] = ""        return " ".join(word_list)    elif "不想" in word_list:        for i in range(len(word_list)):            if word_list[i] == "不想":                word_list[i] = ""        return " ".join(word_list)    else:        return cut_text
review.loc[review['emotion'] == 1,'cut_jieba'] = review[review['emotion'] == 1].cut_jieba.apply(change_negtive_like)
# 一些评论内容为空,去除这些为空的评论review = review[~(review['cut_jieba'] == '')]review.shape

2.6 短评可视化

对所有短评进行可视化

from wordcloud import WordCloudfrom imageio import imreadmask = imread("./data/cloud.jpg")font = './data/FZSTK.TTF'wc = WordCloud(    font_path= font,    max_words=2000, # 设置最大现实的字数    max_font_size=250,# 设置字体最大值    background_color = "white",    random_state=30,    mask = mask)wc.generate(''.join(review['cut_jieba'])) # 生成词云plt.imshow(wc)plt.axis('off')

词云1

 对emotion为1的短评进行可视化

from wordcloud import WordCloudfrom imageio import imreadmask = imread("./data/piggy.jpg")font = './data/FZSTK.TTF'wc1 = WordCloud(    font_path= font,    max_words=2000, # 设置最大现实的字数    max_font_size=300,# 设置字体最大值    background_color = "white",    random_state=30,    mask = mask)wc1.generate(''.join(review['cut_jieba'][review['emotion']==1]))plt.imshow(wc1)plt.axis('off')

词云2

对score为-2的短评进行可视化

wc1.generate(''.join(review['cut_jieba'][review['score']==-2])) # 生成词云plt.imshow(wc1)plt.axis('off')

词云3

【注】词云和字体自己定义

3. 训练模型

3.1 建立训练数据集和测试数据集

由于已经为分析准备好了数据,所以现在需要将数据分成训练数据集和测试数据集。将数据分成两部分:75%的训练数据和25%的测试数据。

x, y = review['cut_jieba'], review['emotion']x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.25) 
print(x_train.shape)print(y_train.shape)
print(x_test.shape)print(y_test.shape)

3.2 特征提取

使用 sklearn 包中的 TfidfVectorizer 方法进行特征提取。

from sklearn.feature_extraction.text import TfidfVectorizertfidf_vect = TfidfVectorizer(decode_error='ignore',                             token_pattern=r"/b[^/d/W]/w+/b", # 剔除向量化结果中的数字                             analyzer='word',                             ngram_range=(2,4),                            max_df = 0.8,                            min_df = 3)Xtrain = tfidf_vect.fit_transform(x_train)Xtest = tfidf_vect.transform(x_test)
print(Xtrain.shape)print(Xtest.shape)

3.3 用朴素贝叶斯完成中文文本分类器

from sklearn.naive_bayes import MultinomialNB
review_classifier = MultinomialNB()review_classifier.fit(Xtrain,y_train)
# 对测试集的样本进行预测y_pred = review_classifier.predict(Xtest)metrics.confusion_matrix(y_test, y_pred) # 混淆矩阵
# 利用 sns 模块查看测试值和预测值构成的热图colorMetrics = metrics.confusion_matrix(y_test, y_pred)sns.heatmap(colorMetrics,annot=True,fmt='d')

热图

# 分类报告# 给出每个类的准确率,召回率和F值,以及这三个参数和宏平均值print(metrics.classification_report(y_test,y_pred)) 

print(metrics.accuracy_score(y_test,y_pred))
from sklearn.model_selection import cross_val_scorescore1 = cross_val_score(review_classifier,Xtrain,y_train,cv=10,scoring="accuracy").mean()print(score1)

3.4 用逻辑回归完成中文文本分类

from sklearn.linear_model import LogisticRegression  LR_model = LogisticRegression(penalty='l2',max_iter=3000)  LR_model.fit(Xtrain,y_train)
# 对测试集的样本进行预测y_pred = LR_model.predict(Xtest)metrics.confusion_matrix(y_test, y_pred) # 混淆矩阵
print(LR_model.score(Xtest,y_test))
# 给出每个类的准确率,召回率和F值,以及这三个参数和宏平均值print(metrics.classification_report(y_test,y_pred))

4. 结果分析

(1)词云分析:

  1. 词云1中最明显的词汇是“喜欢”;
  2. 词云2中的词汇与词云1区别不大,因为所有短评中好评占大多数;
  3. 由差评生成的词云3出现了“不好”、“一般”、“硬伤”等负面色彩的词语。

(2)影响情感分析准确性的原因:

  1. 获取到的短评数量比较少;
  2. 由于小说中对主角讨论比较多,一些小说角色名字会重复出现在短评内,一定程度影响对评论的感情分析;
  3. 没有删除过于短小的评论;
  4. 分词后中发现代表积极或消极情绪的词汇往往不会成为单独短评,而是和别的词一起出现,对于查找差评中的积极词汇和好评中的消极词汇造成一定困难。
  5. 短评中出现明显代表正面色彩和负面色彩的词汇较少。

到此这篇关于爬取晋江文学城小说评论(情绪分析)的文章就介绍到这了,希望对你有所帮助,更多相关python爬取内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章,希望大家以后多多支持51zixue.net!


python常见模块与用法
python爬虫之你好,李焕英电影票房数据分析
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。