最近宮鬥劇《延禧攻略》大火,大家稱贊的原因除了劇情,演員的演技之外,還有精良的製作,甚至有人給出了高顏值的歷史教科書的評價,初次之外,某些反派角色的飾演者的微博更是被“正義”的觀眾給攻陷了。本文將通過爬取評論區的評論,來看看小伙伴都在熱議啥。 本文分兩大部分,第一部分是爬蟲部分,爬取評論區信息;第二 ...
最近宮鬥劇《延禧攻略》大火,大家稱贊的原因除了劇情,演員的演技之外,還有精良的製作,甚至有人給出了高顏值的歷史教科書的評價,初次之外,某些反派角色的飾演者的微博更是被“正義”的觀眾給攻陷了。本文將通過爬取評論區的評論,來看看小伙伴都在熱議啥。
本文分兩大部分,第一部分是爬蟲部分,爬取評論區信息;第二部分對數據進行分析。
爬蟲部分
前期分析
這裡我們選取豆瓣上的評論作為目標,與一般的爬蟲無異,首先是分析網站信息,分析的方法與之前的爬蟲例子一樣:廣西某211高校新聞爬取,城市空氣質量爬取。
經過分析,發現評論區每個頁面存放20條評論,每條評論有一個單獨的頁面,因此採取的方法位逐一獲取每個頁面的評論列表,提取每條評論的鏈接,再獲取其評論內容。這裡我們選擇爬取前150頁的評論信息。
經過以上分析,可以確定程式需要做的工作如下:從第1頁到第150頁逐一獲取評論列表,接著逐一獲取每條評論的文本內容。因逐一獲取評論列表內容較多,因此考慮採取多線程的爬取方式,每30頁為一個線程進行爬取。
代碼編寫
- 小編在此謝謝大家的觀看!Python很容易學!所以小編有弄一個交流,互問互答,資源共用的交流學習基地,如果你也是Python的學習者或者大牛都歡迎你來!㪊:548+377+875!一起 學習共同進步!
接著開始編寫代碼的基本框架,首先需要有一個向頁面發起請求的函數;接著需要有解析評論列表頁面的函數,用來獲取每個評論的鏈接;對於每一個評論頁面,也需要進行解析;對於獲取到的評論內容,需要進行保存。因此,整個函數的基本結構應該如下:
get_html()函數用於需要發起url請求獲取信息,這裡用到requests庫的get方法:
def get_html(url):
# 構造請求頭
headers = {'User-Agent':'Mozilla/5.0'}
# 隨機暫停
t = random.randint(2,15)
print(' 暫停{}s'.format(t))
time.sleep(t)
# 發起請求獲取html
r = requests.get(url,headers=headers)
html = r.text
return html
我們首先需要獲取的是評論列表的頁面,先獲取每條評論的鏈接才能獲取評論內容。因此,我們使用parser_page_list()函數解析評論列表頁面的信息,使用parser_per_comment()函數解析每條評論的信息:
# 解析每條評論的網頁,獲取評論內容
def parser_per_commet(html,from_page,end_page):
# 保存每一個評論頁面的評論標題以及內容
soup = BeautifulSoup(html,'html.parser')
title = soup.find('div',{'id':'content'}).find('h1').text.strip()
p = soup.find('div',{'id':'link-report'}).find('span',{'class':''}).find_all('p')
content = ''
for i in range(len(p)):
content += p[i].text.strip()
save_file(title,content,from_page,end_page)
# 解析每個評論列表頁面,獲取每條評論的鏈接
def parser_page_list(html,from_page,end_page):
# 獲取每個評論列表頁面的href鏈接
soup = BeautifulSoup(html,'html.parser')
tr = soup.find('table',{'class':'olt'}).find_all('tr')
hrefs = []
for i in range(1,len(tr)):
href = tr[i].find('a').get('href')
hrefs.append(href)
# print(hrefs)
for href in hrefs:
try:
# 每隔若幹秒開始爬取評論的標題和內容
time.sleep(random.randint(3,15))
html = get_html(href)
parser_per_commet(html,from_page,end_page)
except:
continue
由於加了延時爬取,單線程爬取150個頁面的評論會變慢,除此之外,由於一個IP地址頻繁的訪問網站,很容易會出髮網站的反爬機制。因此,加入了多線程,每個線程爬取30頁的評論內容:
# 每條線程的開始頁面以及結束頁面
def from_to_thread(from_page,end_page):
for i in range(from_page,end_page):
yx_dicussion_url = 'https://movie.douban.com/subject/26999852/discussion/?start={}&sort_by=time'.format(i*20)
time.sleep(random.randint(5,20))
html = get_html(yx_dicussion_url)
parser_page_list(html,from_page,end_page)
if __name__ == '__main__':
for i in range(0,150,30):
from_to_ = threading.Thread(target=from_to_thread,args=(i,i+29))
from_to_.start()
最後的文件保存,為避免多線程之間讀寫同一變數造成不可預知的錯誤,因此保存文件時,採取了一個線程對應保存一個文件的方式:
# 保存評論內容
def save_file(title,content,from_page,end_page):
with open('yxgl_{}_{}.txt'.format(from_page,end_page),'a',encoding='utf-8') as f:
f.write(title + ' ' + content + ' ')
分析統計
詞雲分析
對於文本內容的分析,採取詞雲的方式直觀展示。詞雲的用法可以參照之前的例子:《核安全法》詞雲統計,以下為實現代碼:
# 獲取所有txt文件,讀入內容
def get_word():
files = []
for file in os.listdir('.'):
if file.endswith('.txt'):
files.append(file)
total_content = ''
for file_num in range(len(files)):
with open(files[file_num],'rb') as f:
txt = f.read()
decode_txt = txt.decode('utf-8')
total_content += decode_txt
words_ls = jieba.lcut(total_content)
return words_ls
# 生成詞雲
def ciyun():
mk = imread('qianlong.jpg')
words_ls = get_word()
words = ' '.join(words_ls)
w = wordcloud.WordCloud(mask=mk,font_path='msyh.ttc',background_color='white')
w.generate(words)
w.to_file('延禧詞雲.png')
print('詞雲生成成功!')
以下為詞雲效果,主角永遠都是討論的焦點:
詞頻統計
評論區大家討論最多的是哪些角色呢?我們通過詞頻統計來看下。詞頻統計採取字典的get方法,詳細可見前面的介紹:《水滸傳》詞頻統計,組合數據類型(2)。我們統計出現最多的前十名,以下為實現代碼:
def ciping():
words = get_word()
# print(words)
counter = {}
del_words = [
' ','一個','沒有','自己','就是','覺得','這個','真的','...','什麼','不是','還是',
'喜歡','延禧','但是','攻略','知道','看到','劇情','這麼','可以','時候','最後','怎麼','感覺',
'演技','那麼','所以','其實','為什麼','這樣','為了','還有'
]
for word in words:
if len(word) == 1:
continue
elif word == '女主':
return_word = '瓔珞'
elif word == '乾隆' or word == '皇帝':
return_word = '皇上'
else:
return_word = word
counter[return_word] = counter.get(return_word,0) + 1
for word in del_words:
del counter[word]
ls = list(counter.items())
ls.sort(key=lambda x:x[1],reverse=True)
for i in range(10):
print(ls[i])
運行後的結果為:
可以看到主角毫無疑問的第一位,接下來就是大豬蹄子乾隆皇帝,溫文爾雅的皇後位居第三,袁春望出現在前十有點意外。不知道《延禧》,你給幾分?