python爬取晉江文學(xué)城小說(shuō)評(píng)論(情緒分析)
1. 收集數(shù)據(jù)
1.1 爬取晉江文學(xué)城收藏排行榜前50頁(yè)的小說(shuō)信息
獲取收藏榜前50頁(yè)的小說(shuō)列表,第一頁(yè)網(wǎng)址為 ‘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' , 第二頁(yè)網(wǎng)址中page=2,以此類(lèi)推,直到第50頁(yè)中page=50。爬取每個(gè)小說(shuō)的ID,小說(shuō)名字,小說(shuō)作者。將爬取到的信息存儲(chǔ)到晉江排行榜【按收藏?cái)?shù)】.txt文件中。
import requests from bs4 import BeautifulSoup import bs4 import re import csv import pandas as pd import numpy as np import matplotlib.pyplot as plt import jieba import seaborn as sns import xlrd from xlutils.copy import copy # 一些魔法命令,使得matplotlib畫(huà)圖時(shí)嵌入單元中而不是新開(kāi)一個(gè)窗口 %matplotlib inline plt.rcParams['figure.figsize'] = (10.0, 8.0) # set default size of plots plt.rcParams['image.interpolation'] = 'nearest' plt.rcParams['image.cmap'] = 'gray' %load_ext autoreload %autoreload 2 from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn import metrics from sklearn.model_selection import train_test_split
- 爬取小說(shuō)基本信息 ,主要思路;
- 找到需要爬取的所有信息主體tbody;
- 分別找到每個(gè)信息對(duì)應(yīng)的小標(biāo)簽td(a),數(shù)清楚在所有標(biāo)簽中的順序;
- 存進(jìn)txt文檔時(shí)按順序存儲(chǔ)。
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') # 獲取小說(shuō)主頁(yè)的url p = re.compile(r'\d+') book_id = p.findall(book_url)[0] # 獲取小說(shuō)ID if(count%2==0): id.append(book_id) for n in range(0,100): with open('./data/晉江排行榜【按收藏?cái)?shù)】.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) # 序號(hào) 書(shū)名 作者
1.2 查看爬蟲(chóng)結(jié)果
分別查看前8部小說(shuō)的ID和名字
# 查看收藏榜前8部小說(shuō)的ID with open('./data/晉江排行榜【按收藏?cái)?shù)】.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部小說(shuō)的名字 name_list = [item.split('\t')[1] for item in book_list] print(name_list[:8])
1.3 ** 爬取每部小說(shuō)的評(píng)論** 。
找到小說(shuō)的評(píng)論區(qū),第一部小說(shuō)《天官賜?!返牡谝豁?yè)評(píng)論網(wǎng)址為 ‘http://www.jjwxc.net/comment.php?novelid=3200611&huati=1' ,3200611是小說(shuō)ID,1是評(píng)論頁(yè)數(shù),這部小說(shuō)第二頁(yè)網(wǎng)址為'http://www.jjwxc.net/comment.php?novelid=3200611&huati=2' 。下一部小說(shuō)《撒野》的ID是2956313,它的第一頁(yè)評(píng)論網(wǎng)址為'http://www.jjwxc.net/comment.php?novelid=2956313&huati=1' ,以此類(lèi)推,爬取所有小說(shuō)的評(píng)論和打分。為了避免有一些小說(shuō)評(píng)論數(shù)不夠多,自己設(shè)定每部小說(shuō)只爬取5頁(yè)的評(píng)論。
爬取思路與爬取小說(shuō)信息大致相同,不同的是將爬取到的信息存儲(chǔ)到xls文件中。
headers = {"User-Agent": "Mozilla/5.0"} with open('./data/晉江排行榜【按收藏?cái)?shù)】.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 # 文件行數(shù) 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. 數(shù)據(jù)加載和預(yù)處理
預(yù)處理包括:
- 格式轉(zhuǎn)化;上一步將爬取信息存到了xls文件,將xls格式文件轉(zhuǎn)化為csv格式文件方便下一步加載。
- 數(shù)據(jù)去重;爬取過(guò)程中某些頁(yè)面爬取了多次,導(dǎo)致csv文件包含重復(fù)的行。
- 短評(píng)去重;對(duì)同一部小說(shuō),或者不同的小說(shuō),可能存在評(píng)論內(nèi)容相同的行。
- 添加情緒標(biāo)簽
- 去除停用詞和分詞
- 短評(píng)可視化
2.1 格式轉(zhuǎn)化
使用pandas模塊可以快速將xls文件轉(zhuǎn)換為.csv
# 格式轉(zhuǎn)化 ex=pd.read_excel("./data/jjwxc.xls") ex.to_csv("./data/jjwxc.csv",encoding="gb18030")
# 加載評(píng)論 review = pd.read_csv("./data/jjwxc.csv",names=['ID','comment','score'],encoding='gb18030')
2.2 數(shù)據(jù)去重
去除重復(fù)的行
# 去重 review = review.drop_duplicates()
2.3 短評(píng)去重
去除評(píng)論相同的行
# 刪除評(píng)論內(nèi)容重復(fù)的行 review= review.drop_duplicates('comment') review.shape
2.4 添加情緒標(biāo)簽
根據(jù)打分的分?jǐn)?shù)來(lái)添加情緒標(biāo)簽,觀(guān)察晉江文學(xué)城的打分機(jī)制發(fā)現(xiàn),打分區(qū)間在[-2,2]內(nèi),且打2分的人數(shù)占大多數(shù),于是將分?jǐn)?shù)為2的評(píng)論看作是好評(píng),情緒標(biāo)簽為1,而低于2分的看作是差評(píng),情緒標(biāo)簽為0。
# 添加情緒標(biāo)簽 review['emotion'] = (review.score ==2) * 1
# 打亂順序 review = review.sample(frac=1).reset_index(drop=True) print(review.shape)
2.5 去除停用詞和分詞
短評(píng)內(nèi)容進(jìn)行分詞并去掉停用詞
def review_without_stop(review): # 打開(kāi)停用詞文件 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) # 刪除停用詞中重復(fù)的項(xiàng) # 短評(píng)中的非中文字符替換為'' review = re.sub("[^\u4e00-\u9fa5]",'',review) # 去除全角空白字符 review = review.replace("\u3000","") # 分詞 review = jieba.cut(review) # 過(guò)濾一個(gè)字的詞 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)
【注】停用詞和分詞文件需要自己定義
# 查看一些評(píng)論 review.head()
# 好評(píng)中一些評(píng)論包含“不想”,“不喜歡” review[(review['cut_jieba'] == '不想') & (review['emotion'] == 1)]
review[(review['cut_jieba'] == '不喜歡') & (review['emotion'] == 1)]
# 好評(píng)中出現(xiàn)的消極情緒詞,去除這些評(píng)論 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)
# 一些評(píng)論內(nèi)容為空,去除這些為空的評(píng)論 review = review[~(review['cut_jieba'] == '')] review.shape
2.6 短評(píng)可視化
對(duì)所有短評(píng)進(jìn)行可視化
from wordcloud import WordCloud from imageio import imread mask = imread("./data/cloud.jpg") font = './data/FZSTK.TTF' wc = WordCloud( font_path= font, max_words=2000, # 設(shè)置最大現(xiàn)實(shí)的字?jǐn)?shù) max_font_size=250,# 設(shè)置字體最大值 background_color = "white", random_state=30, mask = mask) wc.generate(''.join(review['cut_jieba'])) # 生成詞云 plt.imshow(wc) plt.axis('off')
對(duì)emotion為1的短評(píng)進(jìn)行可視化
from wordcloud import WordCloud from imageio import imread mask = imread("./data/piggy.jpg") font = './data/FZSTK.TTF' wc1 = WordCloud( font_path= font, max_words=2000, # 設(shè)置最大現(xiàn)實(shí)的字?jǐn)?shù) max_font_size=300,# 設(shè)置字體最大值 background_color = "white", random_state=30, mask = mask) wc1.generate(''.join(review['cut_jieba'][review['emotion']==1])) plt.imshow(wc1) plt.axis('off')
對(duì)score為-2的短評(píng)進(jìn)行可視化
wc1.generate(''.join(review['cut_jieba'][review['score']==-2])) # 生成詞云 plt.imshow(wc1) plt.axis('off')
【注】詞云和字體自己定義
3. 訓(xùn)練模型
3.1 建立訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集
由于已經(jīng)為分析準(zhǔn)備好了數(shù)據(jù),所以現(xiàn)在需要將數(shù)據(jù)分成訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集。將數(shù)據(jù)分成兩部分:75%的訓(xùn)練數(shù)據(jù)和25%的測(cè)試數(shù)據(jù)。
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 方法進(jìn)行特征提取。
from sklearn.feature_extraction.text import TfidfVectorizer tfidf_vect = TfidfVectorizer(decode_error='ignore', token_pattern=r"\b[^\d\W]\w+\b", # 剔除向量化結(jié)果中的數(shù)字 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 用樸素貝葉斯完成中文文本分類(lèi)器
from sklearn.naive_bayes import MultinomialNB
review_classifier = MultinomialNB() review_classifier.fit(Xtrain,y_train)
# 對(duì)測(cè)試集的樣本進(jìn)行預(yù)測(cè) y_pred = review_classifier.predict(Xtest) metrics.confusion_matrix(y_test, y_pred) # 混淆矩陣
# 利用 sns 模塊查看測(cè)試值和預(yù)測(cè)值構(gòu)成的熱圖 colorMetrics = metrics.confusion_matrix(y_test, y_pred) sns.heatmap(colorMetrics,annot=True,fmt='d')
# 分類(lèi)報(bào)告 # 給出每個(gè)類(lèi)的準(zhǔn)確率,召回率和F值,以及這三個(gè)參數(shù)和宏平均值 print(metrics.classification_report(y_test,y_pred))
print(metrics.accuracy_score(y_test,y_pred))
from sklearn.model_selection import cross_val_score score1 = cross_val_score(review_classifier,Xtrain,y_train,cv=10,scoring="accuracy").mean() print(score1)
3.4 用邏輯回歸完成中文文本分類(lèi)
from sklearn.linear_model import LogisticRegression LR_model = LogisticRegression(penalty='l2',max_iter=3000) LR_model.fit(Xtrain,y_train)
# 對(duì)測(cè)試集的樣本進(jìn)行預(yù)測(cè) y_pred = LR_model.predict(Xtest) metrics.confusion_matrix(y_test, y_pred) # 混淆矩陣
print(LR_model.score(Xtest,y_test))
# 給出每個(gè)類(lèi)的準(zhǔn)確率,召回率和F值,以及這三個(gè)參數(shù)和宏平均值 print(metrics.classification_report(y_test,y_pred))
4. 結(jié)果分析
(1)詞云分析:
- 詞云1中最明顯的詞匯是“喜歡”;
- 詞云2中的詞匯與詞云1區(qū)別不大,因?yàn)樗卸淘u(píng)中好評(píng)占大多數(shù);
- 由差評(píng)生成的詞云3出現(xiàn)了“不好”、“一般”、“硬傷”等負(fù)面色彩的詞語(yǔ)。
(2)影響情感分析準(zhǔn)確性的原因:
- 獲取到的短評(píng)數(shù)量比較少;
- 由于小說(shuō)中對(duì)主角討論比較多,一些小說(shuō)角色名字會(huì)重復(fù)出現(xiàn)在短評(píng)內(nèi),一定程度影響對(duì)評(píng)論的感情分析;
- 沒(méi)有刪除過(guò)于短小的評(píng)論;
- 分詞后中發(fā)現(xiàn)代表積極或消極情緒的詞匯往往不會(huì)成為單獨(dú)短評(píng),而是和別的詞一起出現(xiàn),對(duì)于查找差評(píng)中的積極詞匯和好評(píng)中的消極詞匯造成一定困難。
- 短評(píng)中出現(xiàn)明顯代表正面色彩和負(fù)面色彩的詞匯較少。
到此這篇關(guān)于爬取晉江文學(xué)城小說(shuō)評(píng)論(情緒分析)的文章就介紹到這了,希望對(duì)你有所幫助,更多相關(guān)python爬取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
- python爬取豆瓣評(píng)論制作詞云代碼
- 基于Python實(shí)現(xiàn)評(píng)論區(qū)抽獎(jiǎng)功能詳解
- 用Python寫(xiě)一個(gè)球球大作戰(zhàn)小游戲
- Python爬蟲(chóng)實(shí)戰(zhàn)之爬取攜程評(píng)論
- python 爬取華為應(yīng)用市場(chǎng)評(píng)論
- python 爬取京東指定商品評(píng)論并進(jìn)行情感分析
- 利用Python網(wǎng)絡(luò)爬蟲(chóng)爬取各大音樂(lè)評(píng)論的代碼
- python 爬取騰訊視頻評(píng)論的實(shí)現(xiàn)步驟
- Python?抖音評(píng)論數(shù)據(jù)抓取分析
相關(guān)文章
采用python實(shí)現(xiàn)簡(jiǎn)單QQ單用戶(hù)機(jī)器人的方法
這篇文章主要介紹了采用python實(shí)現(xiàn)簡(jiǎn)單QQ單用戶(hù)機(jī)器人的方法,需要的朋友可以參考下2014-07-07Tensor 和 NumPy 相互轉(zhuǎn)換的實(shí)現(xiàn)
本文主要介紹了Tensor 和 NumPy 相互轉(zhuǎn)換的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02Python代碼庫(kù)之Tuple如何append添加元素問(wèn)題
這篇文章主要介紹了Python代碼庫(kù)之Tuple如何append添加元素問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01淺談python3發(fā)送post請(qǐng)求參數(shù)為空的情況
今天小編就為大家分享一篇淺談python3發(fā)送post請(qǐng)求參數(shù)為空的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12使用pycharm將自己項(xiàng)目代碼上傳github(小白教程)
github是一個(gè)代碼托管平臺(tái),本文主要介紹了使用pycharm將自己項(xiàng)目代碼上傳github,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Python 3.6 中使用pdfminer解析pdf文件的實(shí)現(xiàn)
這篇文章主要介紹了Python 3.6 中使用pdfminer解析pdf文件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09