當前位置:
首頁 > 知識 > Python爬蟲實戰:《戰狼2》豆瓣影評分析

Python爬蟲實戰:《戰狼2》豆瓣影評分析

點擊上方

Python開發

」,選擇「置頂公眾號」


關鍵時刻,第一時間送達!



剛接觸python不久,做一個小項目來練練手。前幾天看了《戰狼2》,發現它在最新上映的電影裡面是排行第一的,如下圖所示。準備把豆瓣上對它的影評做一個分析。


目標總覽


主要做了三件事:




  • 抓取網頁數據



  • 清理數據



  • 用詞雲進行展示 
    使用的python版本是3.5.


一、抓取網頁數據


第一步要對網頁進行訪問,python中使用的是urllib庫。代碼如下:

  1. from

    urllib

    import

    request

  2. resp

    =

    request

    .

    urlopen

    (

    "https://movie.douban.com/nowplaying/hangzhou/"

    )

  3. html_data

    =

    resp

    .

    read

    ().

    decode

    (

    "utf-8"

    )


其中https://movie.douban.com/nowp...是豆瓣最新上映的電影頁面,可以在瀏覽器中輸入該網址進行查看。 html_data是字元串類型的變數,裡面存放了網頁的html代碼。 輸入 

print

(

html_data

)

可以查看,如下圖所示:



第二步,需要對得到的html代碼進行解析,得到裡面提取我們需要的數據。

 


在python中使用BeautifulSoup庫進行html代碼的解析。 (註:如果沒有安裝此庫,則使用 

pip install

BeautifulSoup

進行安裝即可!) BeautifulSoup使用的格式如下:

  1. BeautifulSoup

    (

    html

    ,

    "html.parser"

    )


第一個參數為需要提取數據的html,第二個參數是指定解析器,然後使用 

find_all

()

讀取html標籤中的內容。


但是html中有這麼多的標籤,該讀取哪些標籤呢?其實,最簡單的辦法是我們可以打開我們爬取網頁的html代碼,然後查看我們需要的數據在哪個html標籤裡面,再進行讀取就可以了。如下圖所示:


從上圖中可以看出在 

div id

=

"nowplaying"

標籤開始是我們想要的數據,裡面有電影的名稱、評分、主演等信息。所以相應的代碼編寫如下:

  1. from

    bs4

    import

    BeautifulSoup

    as

    bs

  2. soup

    =

    bs

    (

    html_data

    ,

    "html.parser"

    )

       

  3. nowplaying_movie

    =

    soup

    .

    find_all

    (

    "div"

    ,

    id

    =

    "nowplaying"

    )

  4. nowplaying_movie_list

    =

    nowplaying_movie

    [

    0

    ].

    find_all

    (

    "li"

    ,

    class_

    =

    "list-item"

    )


其中 

nowplaying_movie_list

是一個列表,可以用 

print

(

nowplaying_movie_list

[

0

])

查看裡面的內容,如下圖所示:



在上圖中可以看到data-subject屬性裡面放了電影的id號碼,而在img標籤的alt屬性裡面放了電影的名字,因此我們就通過這兩個屬性來得到電影的id和名稱。(註:打開電影短評的網頁時需要用到電影的id,所以需要對它進行解析),編寫代碼如下:

  1. nowplaying_list

    =

    []

  2. for

    item

    in

    nowplaying_movie_list

    :

           

  3.        nowplaying_dict

    =

    {}

           

  4.        nowplaying_dict

    [

    "id"

    ]

    =

    item

    [

    "data-subject"

    ]

         

  5.        

    for

    tag_img_item

    in

    item

    .

    find_all

    (

    "img"

    ):

               

  6.            nowplaying_dict

    [

    "name"

    ]

    =

    tag_img_item

    [

    "alt"

    ]

               

  7.            nowplaying_list

    .

    append

    (

    nowplaying_dict

    )

     


其中列表nowplaying_list中就存放了最新電影的id和名稱,可以使用 

print

(

nowplaying_list

)

進行查看,如下圖所示:



可以看到和豆瓣網址上面是匹配的。這樣就得到了最新電影的信息了。接下來就要進行對最新電影短評進行分析了。例如《戰狼2》的短評網址為: 

https

:

//movie.douban.com/subject/26363254/comments?start=0&limit=20

 
其中 

26363254

就是電影的id, 

start

=

0

表示評論的第0條評論。


接下來接對該網址進行解析了。打開上圖中的短評頁面的html代碼,我們發現關於評論的數據是在 

div

標籤的 

comment

屬性下面,如下圖所示:



因此對此標籤進行解析,代碼如下:

  1. requrl

    =

    "https://movie.douban.com/subject/"

    +

    nowplaying_list

    [

    0

    ][

    "id"

    ]

    +

    "/comments"

    +

    "?"

    +

    "start=0"

    +

    "&limit=20"

  2. resp

    =

    request

    .

    urlopen

    (

    requrl

    )

  3. html_data

    =

    resp

    .

    read

    ().

    decode

    (

    "utf-8"

    )

  4. soup

    =

    bs

    (

    html_data

    ,

    "html.parser"

    )

  5. comment_div_lits

    =

    soup

    .

    find_all

    (

    "div"

    ,

    class_

    =

    "comment"

    )


此時在 

comment_div_lits

列表中存放的就是div標籤和comment屬性下面的html代碼了。在上圖中還可以發現在p標籤下面存放了網友對電影的評論,如下圖所示:



因此對 

comment_div_lits

代碼中的html代碼繼續進行解析,代碼如下:

  1. eachCommentList

    =

    [];

  2. for

    item

    in

    comment_div_lits

    :

  3.        

    if

    item

    .

    find_all

    (

    "p"

    )[

    0

    ].

    string

    is

    not

    None

    :

       

  4.            eachCommentList

    .

    append

    (

    item

    .

    find_all

    (

    "p"

    )[

    0

    ].

    string

    )


使用 

print

(

eachCommentList

)

查看eachCommentList列表中的內容,可以看到裡面存里我們想要的影評。如下圖所示:





好的,至此我們已經爬取了豆瓣最近播放電影的評論數據,接下來就要對數據進行清洗和詞雲顯示了。


二、數據清洗


為了方便進行數據進行清洗,我們將列表中的數據放在一個字元串數組中,代碼如下:

  1. comments

    =

    ""

  2. for

    k

    in

    range

    (

    len

    (

    eachCommentList

    )):

  3.    comments

    =

    comments

    +

    (

    str

    (

    eachCommentList

    [

    k

    ])).

    strip

    ()


使用 

print

(

comments

)

進行查看,如下圖所示:



可以看到所有的評論已經變成一個字元串了,但是我們發現評論中還有不少的標點符號等。這些符號對我們進行詞頻統計時根本沒有用,因此要將它們清除。所用的方法是正則表達式。python中正則表達式是通過re模塊來實現的。代碼如下:

  1. import

    re

  2. pattern

    =

    re

    .

    compile

    (

    r

    "[u4e00-u9fa5]+"

    )

  3. filterdata

    =

    re

    .

    findall

    (

    pattern

    ,

    comments

    )

  4. cleaned_comments

    =

    ""

    .

    join

    (

    filterdata

    )


繼續使用 

print

(

cleaned_comments

)

語句進行查看,如下圖所示:



我們可以看到此時評論數據中已經沒有那些標點符號了,數據變得"乾淨"了很多。


因此要進行詞頻統計,所以先要進行中文分詞操作。在這裡我使用的是結巴分詞。如果沒有安裝結巴分詞,可以在控制台使用 

pip install jieba

進行安裝。(註:可以使用 

pip list

查看是否安裝了這些庫)。代碼如下所示:

  1. import

    jieba    

    #分詞包

  2. import

    pandas

    as

    pd  

  3. segment

    =

    jieba

    .

    lcut

    (

    cleaned_comments

    )

  4. words_df

    =

    pd

    .

    DataFrame

    ({

    "segment"

    :

    segment

    })


因為結巴分詞要用到pandas,所以我們這裡載入了pandas包。可以使用 

words_df

.

head

()

查看分詞之後的結果,如下圖所示:




從上圖可以看到我們的數據中有"看"、"太"、"的"等虛詞(停用詞),而這些詞在任何場景中都是高頻時,並且沒有實際的含義,所以我們要他們進行清除。


我把停用詞放在一個 

stopwords

.

txt

文件中,將我們的數據與停用詞進行比對即可(註:只要在百度中輸入 

stopwords

.

txt

,就可以下載到該文件)。去停用詞代碼如下代碼如下:

  1. stopwords

    =

    pd

    .

    read_csv

    (

    "stopwords.txt"

    ,

    index_col

    =

    False

    ,

    quoting

    =

    3

    ,

    sep

    =

    "t"

    ,

    names

    =[

    "stopword"

    ],

    encoding

    =

    "utf-8"

    )#

    quoting

    =

    3

    全不引用

  2. words_df

    =

    words_df

    [~

    words_df

    .

    segment

    .

    isin

    (

    stopwords

    .

    stopword

    )]


繼續使用 

words_df

.

head

()

語句來查看結果,如下圖所示,停用詞已經被出去了。



接下來就要進行詞頻統計了,代碼如下:

  1. import

    numpy    

    #numpy計算包

  2. words_stat

    =

    words_df

    .

    groupby

    (

    by

    =[

    "segment"

    ])[

    "segment"

    ].

    agg

    ({

    "計數"

    :

    numpy

    .

    size

    })

  3. words_stat

    =

    words_stat

    .

    reset_index

    ().

    sort_values

    (

    by

    =[

    "計數"

    ],

    ascending

    =

    False

    )


用 

words_stat

.

head

()

進行查看,結果如下:



由於我們前面只是爬取了第一頁的評論,所以數據有點少,在最後給出的完整代碼中,我爬取了10頁的評論,所數據還是有參考價值。


三、用詞雲進行顯示


代碼如下:

  1. import

    matplotlib

    .

    pyplot

    as

    plt

  2. %

    matplotlib

    inline

  3. import

    matplotlib

  4. matplotlib

    .

    rcParams

    [

    "figure.figsize"

    ]

    =

    (

    10.0

    ,

    5.0

    )

  5. from

    wordcloud

    import

    WordCloud

    #詞雲包

  6. wordcloud

    =

    WordCloud

    (

    font_path

    =

    "simhei.ttf"

    ,

    background_color

    =

    "white"

    ,

    max_font_size

    =

    80

    )

    #指定字體類型、字體大小和字體顏色

  7. word_frequence

    =

    {

    x

    [

    0

    ]:

    x

    [

    1

    ]

    for

    x

    in

    words_stat

    .

    head

    (

    1000

    ).

    values

    }

  8. word_frequence_list

    =

    []

  9. for

    key

    in

    word_frequence

    :

  10.    temp

    =

    (

    key

    ,

    word_frequence

    [

    key

    ])

  11.    word_frequence_list

    .

    append

    (

    temp

    )

  12. wordcloud

    =

    wordcloud

    .

    fit_words

    (

    word_frequence_list

    )

  13. plt

    .

    imshow

    (

    wordcloud

    )


其中 

simhei

.

ttf

使用來指定字體的,可以在百度上輸入 

simhei

.

ttf

進行下載後,放入程序的根目錄即可。顯示的圖像如下:



到此為止,整個項目的介紹就結束了。由於自己也還是個初學者,接觸python不久,代碼寫的並不好。而且第一次寫技術博客,表達的有些冗餘,請大家多多包涵,有不對的地方,請大家批評指正。以後我也會將自己做的小項目以這種形式寫在博客上和大家一起交流!最後貼上完整的代碼。


完整代碼

  1. #coding:utf-8

  2. __author__

    =

    "hang"

  3. import

    warnings

  4. warnings

    .

    filterwarnings

    (

    "ignore"

    )

  5. import

    jieba    

    #分詞包

  6. import

    numpy    

    #numpy計算包

  7. import

    codecs  

    #codecs提供的open方法來指定打開的文件的語言編碼,它會在讀取的時候自動轉換為內部unicode

  8. import

    re

  9. import

    pandas

    as

    pd  

  10. import

    matplotlib

    .

    pyplot

    as

    plt

  11. from

    urllib

    import

    request

  12. from

    bs4

    import

    BeautifulSoup

    as

    bs

  13. %

    matplotlib

    inline

  14. import

    matplotlib

  15. matplotlib

    .

    rcParams

    [

    "figure.figsize"

    ]

    =

    (

    10.0

    ,

    5.0

    )

  16. from

    wordcloud

    import

    WordCloud

    #詞雲包

  17. #分析網頁函數

  18. def

    getNowPlayingMovie_list

    ():

     

  19.    resp

    =

    request

    .

    urlopen

    (

    "https://movie.douban.com/nowplaying/hangzhou/"

    )

           

  20.    html_data

    =

    resp

    .

    read

    ().

    decode

    (

    "utf-8"

    )

       

  21.    soup

    =

    bs

    (

    html_data

    ,

    "html.parser"

    )

       

  22.    nowplaying_movie

    =

    soup

    .

    find_all

    (

    "div"

    ,

    id

    =

    "nowplaying"

    )

           

  23.    nowplaying_movie_list

    =

    nowplaying_movie

    [

    0

    ].

    find_all

    (

    "li"

    ,

    class_

    =

    "list-item"

    )

       

  24.    nowplaying_list

    =

    []

       

  25.    

    for

    item

    in

    nowplaying_movie_list

    :

           

  26.        nowplaying_dict

    =

    {}

           

  27.        nowplaying_dict

    [

    "id"

    ]

    =

    item

    [

    "data-subject"

    ]

         

  28.        

    for

    tag_img_item

    in

    item

    .

    find_all

    (

    "img"

    ):

               

  29.            nowplaying_dict

    [

    "name"

    ]

    =

    tag_img_item

    [

    "alt"

    ]

               

  30.            nowplaying_list

    .

    append

    (

    nowplaying_dict

    )

       

  31.    

    return

    nowplaying_list

  32. #爬取評論函數

  33. def

    getCommentsById

    (

    movieId

    ,

    pageNum

    ):

  34.    eachCommentList

    =

    [];

  35.    

    if

    pageNum

    >

    0

    :

  36.         start

    =

    (

    pageNum

    -

    1

    )

    *

    20

  37.    

    else

    :

  38.        

    return

    False

  39.    requrl

    =

    "https://movie.douban.com/subject/"

    +

    movieId

    +

    "/comments"

    +

    "?"

    +

    "start="

    +

    str

    (

    start

    )

    +

    "&limit=20"

  40.    

    print

    (

    requrl

    )

  41.    resp

    =

    request

    .

    urlopen

    (

    requrl

    )

  42.    html_data

    =

    resp

    .

    read

    ().

    decode

    (

    "utf-8"

    )

  43.    soup

    =

    bs

    (

    html_data

    ,

    "html.parser"

    )

  44.    comment_div_lits

    =

    soup

    .

    find_all

    (

    "div"

    ,

    class_

    =

    "comment"

    )

  45.    

    for

    item

    in

    comment_div_lits

    :

  46.        

    if

    item

    .

    find_all

    (

    "p"

    )[

    0

    ].

    string

    is

    not

    None

    :

       

  47.            eachCommentList

    .

    append

    (

    item

    .

    find_all

    (

    "p"

    )[

    0

    ].

    string

    )

  48.    

    return

    eachCommentList

  49. def

    main

    ():

  50.    

    #循環獲取第一個電影的前10頁評論

  51.    commentList

    =

    []

  52.    

    NowPlayingMovie_list

    =

    getNowPlayingMovie_list

    ()

  53.    

    for

    i

    in

    range

    (

    10

    ):

       

  54.        num

    =

    i

    +

    1

  55.        commentList_temp

    =

    getCommentsById

    (

    NowPlayingMovie_list

    [

    0

    ][

    "id"

    ],

    num

    )

  56.        commentList

    .

    append

    (

    commentList_temp

    )

  57.    

    #將列表中的數據轉換為字元串

  58.    comments

    =

    ""

  59.    

    for

    k

    in

    range

    (

    len

    (

    commentList

    )):

  60.        comments

    =

    comments

    +

    (

    str

    (

    commentList

    [

    k

    ])).

    strip

    ()

  61.    

    #使用正則表達式去除標點符號

  62.    pattern

    =

    re

    .

    compile

    (

    r

    "[u4e00-u9fa5]+"

    )

  63.    filterdata

    =

    re

    .

    findall

    (

    pattern

    ,

    comments

    )

  64.    cleaned_comments

    =

    ""

    .

    join

    (

    filterdata

    )

  65.    

    #使用結巴分詞進行中文分詞

  66.    segment

    =

    jieba

    .

    lcut

    (

    cleaned_comments

    )

  67.    words_df

    =

    pd

    .

    DataFrame

    ({

    "segment"

    :

    segment

    })

  68.    

    #去掉停用詞

  69.    stopwords

    =

    pd

    .

    read_csv

    (

    "stopwords.txt"

    ,

    index_col

    =

    False

    ,

    quoting

    =

    3

    ,

    sep

    =

    "t"

    ,

    names

    =[

    "stopword"

    ],

    encoding

    =

    "utf-8"

    )#

    quoting

    =

    3

    全不引用

  70.    words_df

    =

    words_df

    [~

    words_df

    .

    segment

    .

    isin

    (

    stopwords

    .

    stopword

    )]

  71.    

    #統計詞頻

  72.    words_stat

    =

    words_df

    .

    groupby

    (

    by

    =[

    "segment"

    ])[

    "segment"

    ].

    agg

    ({

    "計數"

    :

    numpy

    .

    size

    })

  73.    words_stat

    =

    words_stat

    .

    reset_index

    ().

    sort_values

    (

    by

    =[

    "計數"

    ],

    ascending

    =

    False

    )

  74.    

    #用詞雲進行顯示

  75.    wordcloud

    =

    WordCloud

    (

    font_path

    =

    "simhei.ttf"

    ,

    background_color

    =

    "white"

    ,

    max_font_size

    =

    80

    )

  76.    word_frequence

    =

    {

    x

    [

    0

    ]:

    x

    [

    1

    ]

    for

    x

    in

    words_stat

    .

    head

    (

    1000

    ).

    values

    }

  77.    word_frequence_list

    =

    []

  78.    

    for

    key

    in

    word_frequence

    :

  79.        temp

    =

    (

    key

    ,

    word_frequence

    [

    key

    ])

  80.        word_frequence_list

    .

    append

    (

    temp

    )

  81.    wordcloud

    =

    wordcloud

    .

    fit_words

    (

    word_frequence_list

    )

  82.    plt

    .

    imshow

    (

    wordcloud

    )

  83. #主函數

  84. main

    ()


結果顯示如下:


上圖基本反映了《戰狼2》這部電影的情況。





  • 作者:hang



  • https://segmentfault.com/a/1190000010473819



  • Python開發整理髮布,轉載請聯繫作者獲得授權


【點擊成為Android大神】

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發 的精彩文章:

怎樣用Python給寶寶取個好名字?
你用 Python 寫過哪些牛逼的程序/腳本?

TAG:Python開發 |