Python爬蟲實戰,requests+xpath模塊,Python實現爬取豆瓣影評 前言 開發工具 環境搭建 前期準備 數據可視化

前言

利用利用requests+xpath爬取豆瓣影評,廢話不多說。

讓我們愉快地開始吧~

開發工具

Python版本:3.6.4

相關模塊:

requests模塊;

jieba模塊;

pandas模塊

numpy模塊

pyecharts模塊;

以及一些Python自帶的模塊。

環境搭建

安裝Python並添加到環境變量,pip安裝需要的相關模塊即可。

前期準備

1.獲取頁面內容

# 爬取頁面 url\
douban_url = 'https://movie.douban.com/subject/26647117/comments?status=P'\
# requests 發送請求\
get_response = requests.get(douban_url)\
# 將返回的響應碼轉換成文本(整個網頁)\
get_data = get_response.text

2.分析頁面內容,獲取我們想要的內容

  • 瀏覽器中打開我們要爬取的頁面
  • 按F12進入開發者工具,查看我們想要的數據在哪裏
  • 這裏我們只要 評論人+評論內
  • 分析我們獲取的 xpath值
'/html/body/div[3]/div[1]/div/div[1]/div[4]/**div[1]** /div[2]/h3/span[2]/a'
'/html/body/div[3]/div[1]/div/div[1]/div[4]/**div[2]** /div[2]/h3/span[2]/a'
'/html/body/div[3]/div[1]/div/div[1]/div[4]/**div[3]** /div[2]/h3/span[2]/a'
  • 通過觀察我們發現,這幾個xpath只有細微不同,上面加粗的部分已數加的格式改變,所以我們要爬取所有的 commentator(評論者),只需把xpath改爲:
'/html/body/div[3]/div[1]/div/div[1]/div[4]/**div**/div[2]/h3/span[2]/a'

即不要後面的序號,當我們查詢時,會自動捕獲類似的xpath。

  • 同樣的分析,我們可以得到評論內容的xpath爲:
'/html/body/div[3]/div[1]/div/div[1]/div[4]/**div**/div[2]/p'
# (跟在上面代碼後)解析頁面,並輸出獲取內容\
a = etree.HTML(get_data)\
commentator = s.xpath('/html/body/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/h3/span[2]/a/text()')\
comment_content = a.xpath('/html/body/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/p/text()')\
# 解析獲取內容,去除多餘內容\
for i in range(0,len(files)):\
   print(commentator[i]+'說:')\
   files[i].strip(r'\n')\
   files[i].strip(' ')\
   print(comment_content[i])

運行結果

Oriol Paulo說: 'Wrath of silence' is quite different from the crime movies I've seen. It's a mix of genres. It's a crime movie,a mystery movie,an action movie,it's also a social realistic movie. Xin Yu Kun plays very well the mix of different genres in this film,and it has a powerful ending.

文文周說: 對於平均水準以上的年輕導演,應毫不吝嗇予以鼓勵,對於年齡一大把了還言之無物的導演,纔要無情打擊。

西樓塵說: 老闆兒子喫真空羊肉,貪婪絞入碎肉機;屠夫兒子喝污染井水,正義只在電視屏。戳瞎左眼,被戳傷的同鄉都能包庇;咬斷舌頭,被救助的律師卻不敢發聲。憑蠻力壘不成金字塔,靠假聲變不成兔子媽。超人面具如同良心咒,送不回原主;尋子告示像是招魂符,在風裏飄搖。真相埋進泥土,藏入山洞,終於再無人知。

#85說: 忻鈺坤第二部作品不是一部秀操作的《心迷宮2.0》,要說風格像誰,都像也都不像:凝視山洞的庫布里克單點透視、像科恩兄弟一樣塑造的神經質殺手、《老男孩》一樣的長廊Fight…不一樣的是,不只是想告訴你兇手是誰,而是他的選擇,以及像手術刀一樣劃開上層失態、中層失德、底層失語、人間失格的社會癥結

一口喫掉小蛋糕說: 結尾太贊,配樂非常喜歡,如果能去掉字幕就好了。從姜武拿起菸灰缸的時候就猜到了結尾。只不過細思極恐,井水爲什麼越來越鹹?爲什麼那麼多人都水腫?村長是知道的,不然不會喝礦泉水。然而這個梗,最後卻沒有過多的交代

大大肉罐說: 上層僞善殘暴,中層冷漠自私,下層失語無力。

武俠小王子說: 當年摩托羅拉的電量還是大大不如諾基亞。

劉瀟陽說: 僅僅是80%成片,已經精彩絕倫。中國類型片就該這麼拍。良好的多線敘事控制力,深穴映射人性,爆炸增長的經濟,暴裂難控的社會問題,男人無聲的憤恨和傷痛,就像無法發聲的底層人民。黑暗結尾,孩子沒有尋回,真相沒有昭顯,這卻是社會真相。有時惡人作惡,僅是爲了與相同利益者變成真正的同盟。

木衛二說: 不斷向下,墮入黑暗的那種片子,鞭撻了社會主要矛盾,且不負責提供解謎快感,所以看完會很沉,很堵。如果《心迷宮》還是手工時代的自發創作,《暴裂無聲》明顯是工業時代(卡司動作特效)的考量,三人較勁,律師一角太弱,宋洋戰力太強,姜武模式化。優點和缺陷都比較明顯。

巴伐利亞酒神說: 結局太他媽的屌了,看完在影院倒吸一口涼氣。影射也很牛逼啊,1984的摩托牌照,一個底層屌絲的人設爲啞巴(沒有話語權),律師(代表中產和法律)和煤老闆(代表權貴和黑惡勢力)的相互勾結。所以即便張保民擁有《黃海》裏綿正赫那樣爆表的武力值,也只能淪爲這個殘酷社會的犧牲品。

凌睿說: 當你望着深淵的時候,深淵也在望着你。

frozenmoon說: 昌萬年是食肉者,徐文傑是喝湯的,而張保民本人就是“肉”,原本他們在食物鏈的一個位置安之若素的扮演自己的角色,但意外沖垮了一切。失控之後,每個人都發現自己不過都是“肉”,昌摘下假髮和西裝,也得臣服於暴力和運氣,徐走出金錢和言辭的保護也要面對殘酷,張的代價或許更大。人性暴裂的悶響。

無恥不混蛋說: 影片最打動我的,不是那些顯而易見、甚至昭然若揭的隱喻,而是整部影片的“失語”。我們屬於“失語的一代”,對應片中,不僅僅只是表層的啞巴張保民的“生理性失語”,更是,精英階層律師在片尾所選擇的“主動性失語”。而影片對“失語”的精準展示,不僅敏感捕捉到了時代痛點,而且極爲戳痛人心。

3.實現翻頁,並把評論人和評論內容存入csv文件

  • 翻頁1

和前面分析xpath不同,我們只要找出每頁之間url的不同之處和規律即可。

# start 屬性表示開始位置\
turn_page1 = 'https://movie.douban.com/subject/26647117/comments?status=P'\
turn_page2 = 'https://movie.douban.com/subject/26647117/comments?start=20&limit=20&sort=new_score&status=P'\
turn_page3 = 'https://movie.douban.com/subject/26647117/comments?start=40&limit=20&sort=new_score&status=P'\
turn_page4 = 'https://movie.douban.com/subject/26647117/comments?start=60&limit=20&sort=new_score&status=P'

觀察發現,除了第一個,每個url就只有 start的值不同,而且每次增加20,上面已經說了start屬性,通過觀察我們也不難發現,每個頁面只有20條評論,這個是由 limit這個屬性控制的(小編已經試過,人爲改動是沒有用的,估計是豆瓣的反爬,但並不影響我們),我這裏想說明的是這個start的值之所以會以20爲增量,就是這個 limit 控制的。

  • 翻頁2
# 獲取評論總數\
 comment_counts = a.xpath('/html/body/div[3]/div[1]/div/div[1]/div[1]/ul/li[1]/span/text()')\
 comment_counts = int(comment_counts[0].strip("看過()"))\
 # 計算出總的的頁面數(每頁有20條評論)\
 page_counts = int(comment_counts/20)\
 # 請求訪問,並把爬取數據存入csv文件\
 for i in range(0,page_counts):\
    turn_page_url = 'https://movie.douban.com/subject/26647117/comments?start={}&limit=20&sort=new_score&status=P'.format(i*20)\
    get_respones_data(turn_page_url)

在完成上面之前,我們肯定要把之前寫的代碼進行修改,讓代碼看起,我們可以把前面寫的代碼封裝成一個函數get_respones_data(),傳入一個訪問url參數,獲得返回的HTML。

代碼實現

import requests\
from lxml import etree\
import pandas as pd\
def get_respones_data(douban_url = 'https://movie.douban.com/subject/26647117/comments?status=P'):\
     # requests 發送請求\
     get_response = requests.get(douban_url)\
     # 將返回的響應碼轉換成文本(整個網頁)\
     get_data = get_response.text\
     # 解析頁面\
     a = etree.HTML(get_data)\
     return a\
 first_a = get_respones_data()\
 # 翻頁\
 comment_counts = first_a.xpath('/html/body/div[3]/div[1]/div/div[1]/div[1]/ul/li[1]/span/text()')\
 comment_counts = int(comment_counts[0].strip("看過()"))\
 page_counts = int(comment_counts / 20)\
#小編已經測試過了,如果沒有登入的話最多隻能訪問10個頁面,也就是200條評論\
#下一期小編將教大家如何應對反爬\
 for i in range(0, page_counts+1):\
     turn_page_url = 'https://movie.douban.com/subject/26647117/comments?start={}&limit=20&sort=new_score&status=P'.format(\
         i * 20)\
     print(turn_page_url)\
     a = get_respones_data(turn_page_url)\
     # 獲取評論人和評論內容\
     commentator = a.xpath('/html/body/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/h3/span[2]/a/text()')\
     comment_content = a.xpath('/html/body/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/p/text()')\
     # 解析內容,並存入csv文件\
     content = [' ' for i in range(0, len(commentator))]\
     for i in range(0, len(commentator)):\
         comment_content[i].strip(r'\n')\
         comment_content[i].strip(' ')\
         content_s = [commentator[i],comment_content[i]]\
         content[i] = content_s\
     name = ['評論人','評論內容']\
     file_test = pd.DataFrame(columns=name, data=content)\
     if i == 0:\
         file_test.to_csv(r'H:\PyCoding\FlaskCoding\Test_all\test0609\app\comment_content.cvs',encoding='utf-8',index=False)\
     else:\
         file_test.to_csv(r'H:\PyCoding\FlaskCoding\Test_all\test0609\app\comment_content.cvs',mode='a+',encoding='utf-8',index=False)

數據可視化

安裝新模塊

pip install jieba\
pip install re\
pip install csv\
pip install pyecharts\
pip install numpy

1解析數據

1    with codecs.open(r'H:\PyCoding\FlaskCoding\Test_all\test0609\app\comment_content.cvs', 'r', 'utf-8') as csvfile:\
2        content = ''\
3        reader = csv.reader(csvfile)\
4        i =0\
5        for file1 in reader:\
6            if i == 0 or i ==1:\
7                pass\
8            else:\
9                content =content + file1[1]\
10            i = i +1\
11        # 去除所有評論裏多餘的字符\
12        content = re.sub('[,,。. \r\n]', '', content)

2分析數據

# 切詞,將整個評論分解成一個個的詞語\
segment = jieba.lcut(content)\
words_df = pd.DataFrame({'segment': segment})\
# quoting=3 表示stopwords.txt裏的內容全部不引用\
stopwords = pd.read_csv(r"H:\PyCoding\FlaskCoding\Test_all\test0609\app\stopwords.txt", index_col=False, quoting=3, sep="\t", names=['stopword'], encoding='utf-8')\
words_df = words_df[~words_df.segment.isin(stopwords.stopword)]\
# 計算每個詞語重複出現次數\
words_stat = words_df.groupby(by=['segment'])['segment'].agg({"計數": numpy.size})\
words_stat = words_stat.reset_index().sort_values(by=["計數"], ascending=False)

3數據可視化

1 test = words_stat.head(1000).values\
# 獲取所有詞語\
2 words = [test[i][0] for i in range(0,len(test))]\
# 獲取詞語對於的出現次數\
3 counts = [test[i][1] for i in range(0,len(test))]\
4wordcloud = WordCloud(width=1300, height=620)\
# 生成詞雲圖\
5 wordcloud.add("爆裂無聲", words, counts, word_size_range=[20, 100])\
6 wordcloud.render()

效果展示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章