Python爬蟲:多種方法爬取貓眼top100電影

2020-10-11 川崎1010

摘要: 作為小白,爬蟲可以說是入門python最快和最容易獲得成就感的途徑。因為初級爬蟲的套路相對固定,常見的方法只有幾種,比較好上手。最近,跟著崔慶才大佬的書:python3網絡爬蟲開發實戰 學習爬蟲。選取網頁結構較為簡單的貓眼top100電影為案例進行練習。 重點是用上述所說的4種方法提取出關鍵內容。一個問題採用不同的解決方法有助於拓展思維,通過不斷練習就能夠靈活運用。

https://www.makcyun.top/web_scraping_withpython1.html

本文知識點:
Requsts 請求庫的使用
beautiful+lxml兩大解析庫使用
正則表達式 、xpath、css選擇器的使用


1. 為什麼爬取該網頁?

  • 比較懶,不想一頁頁地去翻100部電影的介紹,想在一個頁面內進行總體瀏覽(比如在excel表格中);


深入了解一些比較有意思的信息,比如:哪部電影的評分最高?哪位演員的作品數量最多?哪個國家/地區上榜的電影數量最多?哪一年上榜的電影作品最多等。這些信息在網頁上是不那麼容易能直接獲得的,所以需要爬蟲。


2. 爬蟲目標

  • 從網頁中提取出top100電影的電影名稱、封面圖片、排名、評分、演員、上映國家/地區、評分等信息,並保存為csv文本文件。
  • 根據爬取結果,進行簡單的可視化分析。

平臺:windows7 + SublimeText3

3. 爬取步驟

3.1. 網址URL分析

首先,打開貓眼Top100的url網址: http://maoyan.com/board/4?offset=0。頁面非常簡單,所包含的信息就是上述所說的爬蟲目標。下拉頁面到底部,點擊第2頁可以看到網址變為:http://maoyan.com/board/4?offset=10。因此,可以推斷出url的變化規律:offset表示偏移,10代表一個頁面的電影偏移數量,即:第一頁電影是從0-10,第二頁電影是從11-20。因此,獲取全部100部電影,只需要構造出10個url,然後依次獲取網頁內容,再用不同的方法提取出所需內容就可以了。
下面,用requests方法獲取第一個頁面。

3.2. Requests獲取首頁數據

先定義一個獲取單個頁面的函數:get_one_page(),傳入url參數。

1def get_one_page(url): 2    try: 3        headers = { 4            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'} 5        # 不加headers爬不了 6        response = requests.get(url, headers=headers) 7        if response.status_code == 200: 8            return response.text 9        else:10            return None11    except RequestException:12        return None13    # try-except語句捕獲異常

接下來在main()函數中設置url。

1def main():2    url = 'http://maoyan.com/board/4?offset=0'3    html = get_one_page(url)4    print(html)567if __name__ == '__main__':8    main()

運行上述程序後,首頁的原始碼就被爬取下來了。如下圖所示:


接下來就需要從整個網頁中提取出幾項我們需要的內容,用到的方法就是上述所說的四種方法,下面分別進行說明。

3.3. 4種內容解析提取方法

3.3.1. 正則表達式提取

第一種是利用正則表達式提取。
什麼是正則表達式? 下面這串看起來亂七八糟的符號就是正則表達式的語法。

1'<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?'

它是一種強大的字符串處理工具。之所以叫正則表達式,是因為它們可以識別正則字符串(regular string)。可以這麼定義:「 如果你給我的字符串符合規則,我就返回它」;「如果字符串不符合規則,我就忽略它」。通過requests抓取下來的網頁是一堆大量的字符串,用它處理後便可提取出我們想要的內容。

如果還不了解它,可以參考下面的教程:

http://www.runoob.com/regexp/regexp-syntax.html
https://www.w3cschool.cn/regexp/zoxa1pq7.html

下面,開始提取關鍵內容。右鍵網頁-檢查-Network選項,選中左邊第一個文件然後定位到電影信息的相應位置,如下圖:


可以看到每部電影的相關信息都在dd這個節點之中。所以就可以從該節點運用正則進行提取。
第1個要提取的內容是電影的排名。它位於class="board-index"的i節點內。不需要提取的內容用'.*?'替代,需要提取的數字排名用()括起來,()裡面的數字表示為(\d+)。正則表達式可以寫為:

1'<dd>.*?board-index.*?>(\d+)</i>'

接著,第2個需要提取的是封面圖片,圖片網址位於img節點的'data-src'屬性中,正則表達式可寫為:

1'data-src="(.*?)".*?'

第1和第2個正則之間的代碼是不需要的,用'.*?'替代,所以這兩部分合起來寫就是:

1'<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)"

同理,可以依次用正則寫下主演、上映時間和評分等內容,完整的正則表達式如下:

1'<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?star">(.*?)</p

正則表達式寫好以後,可以定義一個頁面解析提取方法:parse_one_page(),用來提取內容:

1def parse_one_page(html): 2    pattern = re.compile( 3        '<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S) 4    # re.S表示匹配任意字符,如果不加,則無法匹配換行符 5    items = re.findall(pattern, html) 6    # print(items) 7    for item in items: 8        yield { 9            'index': item[0],10            'thumb': get_thumb(item[1]),  # 定義get_thumb()方法進一步處理網址11            'name': item[2],12            'star': item[3].strip()[3:],13            # 'time': item[4].strip()[5:],14            # 用兩個方法分別提取time裡的日期和地區15            'time': get_release_time(item[4].strip()[5:]),16            'area': get_release_area(item[4].strip()[5:]),17            'score': item[5].strip() + item[6].strip()18            # 評分score由整數+小數兩部分組成19        }

Tips:
re.S:匹配任意字符,如果不加,則無法匹配換行符;
yield:使用yield的好處是作為生成器,可以遍歷迭代,並且將數據整理形成字典,輸出結果美觀。具體用法可參考:https://blog.csdn.net/zhangpinghao/article/details/18716275;
.strip():用於去掉字符串中的空格。

上面程序為了便於提取內容,又定義了3個方法:get_thumb()、get_release_time()和 get_release_area():

1# 獲取封面大圖
2def get_thumb(url):
3 pattern = re.compile(r'(.*?)@.*?')
4 thumb = re.search(pattern, url)
5 return thumb.group(1)
6# http://p0.meituan.net/movie/5420be40e3b755ffe04779b9b199e935256906.jpg@160w_220h_1e_1c
7# 去掉@160w_220h_1e_1c就是大圖
8
9
10# 提取上映時間函數
11def get_release_time(data):
12 pattern = re.compile(r'(.*?)(\(|$)')
13 items = re.search(pattern, data)
14 if items is None:
15 return '未知'
16 return items.group(1) # 返回匹配到的第一個括號(.*?)中結果即時間
17
18
19# 提取國家/地區函數
20def get_release_area(data):
21 pattern = re.compile(r'.*\((.*)\)')
22 # $表示匹配一行字符串的結尾,這裡就是(.*?);\(|$,表示匹配字符串含有(,或者只有(.*?)
23 items = re.search(pattern, data)
24 if items is None:
25 return '未知'
26 return items.group(1)


Tips:
'r':正則前面加上'r' 是為了告訴編譯器這個string是個raw string,不要轉意'\'。當一個字符串使用了正則表達式後,最好在前面加上'r';
'|' 正則'|'表示或','′:∗∗正則′∣′表示或′,′'表示匹配一行字符串的結尾;
.group(1):意思是返回search匹配的第一個括號中的結果,即(.*?),gropup()則返回所有結果2013-12-18(,group(1)返回'('。

接下來,修改main()函數來輸出爬取的內容:

1def main(): 2    url = 'http://maoyan.com/board/4?offset=0' 3    html = get_one_page(url) 4 5    for item in parse_one_page(html):   6        print(item) 7 8 9if __name__ == '__main__':10    main()

Tips:
if _ name_ == '_ main_':當.py文件被直接運行時,if _ name_ == '_ main_'之下的代碼塊將被運行;當.py文件以模塊形式被導入時,if _ name_ == '_ main_'之下的代碼塊不被運行。
參考:https://blog.csdn.net/yjk13703623757/article/details/77918633。

運行程序,就可成功地提取出所需內容,結果如下:

1{'index': '1', 'thumb': 'http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg', 'name': '霸王別姬', 'star': '張國榮,張豐毅,鞏俐', 'time': '1993-01-01', 'area': '中國香港', 'score': '9.6'}2{'index': '2', 'thumb': 'http://p0.meituan.net/movie/54617769d96807e4d81804284ffe2a27239007.jpg', 'name': '羅馬假日', 'star': '格利高裡·派克,奧黛麗·赫本,埃迪·艾伯特', 'time': '1953-09-02', 'area': '美國', 'score': '9.1'}3{'index': '3', 'thumb': 'http://p0.meituan.net/movie/283292171619cdfd5b240c8fd093f1eb255670.jpg', 'name': '肖申克的救贖', 'star': '蒂姆·羅賓斯,摩根·弗裡曼,鮑勃·岡頓', 'time': '1994-10-14', 'area': '美國', 'score': '9.5'}4{'index': '4', 'thumb': 'http://p0.meituan.net/movie/e55ec5d18ccc83ba7db68caae54f165f95924.jpg', 'name': '這個殺手不太冷', 'star': '讓·雷諾,加裡·奧德曼,娜塔莉·波特曼', 'time': '1994-09-14', 'area': '法國', 'score': '9.5'}5{'index': '5', 'thumb': 'http://p1.meituan.net/movie/f5a924f362f050881f2b8f82e852747c118515.jpg', 'name': '教父', 'star': '馬龍·白蘭度,阿爾·帕西諾,詹姆斯·肯恩', 'time': '1972-03-24', 'area': '美國', 'score': '9.3'}67...8}9[Finished in 1.9s]

以上是第1種提取方法,如果還不習慣正則表達式這種複雜的語法,可以試試下面的第2種方法。

3.3.2. lxml結合xpath提取

該方法需要用到lxml這款解析利器,同時搭配xpath語法,利用它的的路徑選擇表達式,來高效提取所需內容。lxml包為第三方包,需要自行安裝。如果對xpath的語法還不太熟悉,可參考下面的教程:
http://www.w3school.com.cn/xpath/xpath_syntax.asp

1</div> 2 3 4    <div class="container" id="app" class="page-board/index" > 5 6<div class="content"> 7    <div class="wrapper"> 8        <div class="main"> 9            <p class="update-time">2018-08-18<span class="has-fresh-text">已更新</span></p>10            <p class="board-content">榜單規則:將貓眼電影庫中的經典影片,按照評分和評分人數從高到低綜合排序取前100名,每天上午10點更新。相關數據來源於「貓眼電影庫」。</p>11            <dl class="board-wrapper">12                <dd>13                        <i class="board-index board-index-1">1</i>14    <a href="/films/1203" title="霸王別姬" class="image-link" data-act="boarditem-click" data-val="{movieId:1203}">15      <img src="//ms0.meituan.net/mywww/image/loading_2.e3d934bf.png" alt="" class="poster-default" />16      <img data-src="http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c" alt="霸王別姬" class="board-img" />17    </a>18    <div class="board-item-main">19      <div class="board-item-content">20              <div class="movie-item-info">21        <p class="name"><a href="/films/1203" title="霸王別姬" data-act="boarditem-click" data-val="{movieId:1203}">霸王別姬</a></p>22        <p class="star">23                主演:張國榮,張豐毅,鞏俐24        </p>25<p class="releasetime">上映時間:1993-01-01(中國香港)</p>    </div>26    <div class="movie-item-number score-num">27<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>        28    </div>2930      </div>31    </div>3233                </dd>34                <dd>

根據截取的部分html網頁,先來提取第1個電影排名信息,有兩種方法。

第一種:直接複製。
右鍵-Copy-Copy Xpath,得到xpath路徑為:
//*[@id="app"]/div/div/div[1]/dl/dd[1]/i,為了能夠提取到頁面所有的排名信息,需進一步修改為://*[@id="app"]/div/div/div[1]/dl/dd/i/text(),如果想要再精簡一點,可以省去中間部分絕對路徑'/'然後用相對路徑'//'代替,最後進一步修改為://*[@id="app"]//div//dd/i/text()


第二種:觀察網頁結構自己寫。
首先注意到
id = app的div節點,因為在整個網頁結構id是唯一的不會有第二個相同的,所有可以將該div節點作為xpath語法的起點,然後往下觀察分別是3級div節點,可以省略寫為://div,再往下分別是是兩個並列的p節點、dl節點、dd節點和最後的i節點文本。中間可以隨意省略,只要保證該路徑能夠選擇到唯一的文本值'1'即可,例如省去p和dl節點,只保留後面的節點。這樣,完整路徑可以為://*[@id="app"]//div//dd/i/text(),和上式一樣。


根據上述思路,可以寫下其他內容的xpath路徑。觀察到路徑的前一部分://*[@id="app"]//div//dd都是一樣的,從後面才開始不同,因此為了能夠精簡代碼,將前部分路徑賦值為一個變量items,最終提取的代碼如下:

1# 2 用lxml結合xpath提取內容 2def parse_one_page2(html): 3    parse = etree.HTML(html) 4    items = parse.xpath('//*[@id="app"]//div//dd') 5    # 完整的是//*[@id="app"]/div/div/div[1]/dl/dd 6    # print(type(items)) 7    # *代表匹配所有節點,@表示屬性 8    # 第一個電影是dd[1],要提取頁面所有電影則去掉[1] 9    # xpath://*[@id="app"]/div/div/div[1]/dl/dd[1]    10    for item in items:11        yield{12            'index': item.xpath('./i/text()')[0],13            #./i/text()前面的點表示從items節點開始14            #/text()提取文本15            'thumb': get_thumb(str(item.xpath('./a/img[2]/@data-src')[0].strip())),16            # 'thumb': 要在network中定位,在elements裡會寫成@src而不是@data-src,從而會報list index out of range錯誤。17            'name': item.xpath('./a/@title')[0],18            'star': item.xpath('.//p[@class = "star"]/text()')[0].strip(),19            'time': get_release_time(item.xpath(20                './/p[@class = "releasetime"]/text()')[0].strip()[5:]),21            'area': get_release_area(item.xpath(22                './/p[@class = "releasetime"]/text()')[0].strip()[5:]),23            'score' : item.xpath('.//p[@class = "score"]/i[1]/text()')[0] + \24            item.xpath('.//p[@class = "score"]/i[2]/text()')[0]25        }

Tips:
[0]:xpath後面添加了[0]是因為返回的是只有1個字符串的list,添加[0]是將list提取為字符串,使其簡潔;
Network:要在最原始的Network選項卡中定位,而不是Elements中,不然提取不到相關內容;
class屬性:p[@class = "star"]/text()表示提取class屬性為"star"的p節點的文本值;
提取屬性值:img[2]/@data-src':提取img節點的data-src屬性值,屬性值後面無需添加'/text()'

運行程序,就可成功地提取出所需內容,結果和第一種方法一樣。

以上是第2種提取方法,如果也不太習慣xpath語法,可以試試下面的第3種方法。

3.3.3. Beautiful Soup + css選擇器

Beautiful Soup 同lxml一樣,是一個非常強大的python解析庫,可以從HTML或XML文件中提取效率非常高。關於它的用法,可參考下面的教程:
https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/

css選擇器選是一種模式,用於選擇需要添加樣式的元素,使用它的語法同樣能夠快速定位到所需節點,然後提取相應內容。使用方法可參考下面的教程:
http://www.w3school.com.cn/cssref/css_selectors.asp

下面就利用這種方法進行提取:

1# 3 用beautifulsoup + css選擇器提取 2def parse_one_page3(html): 3    soup = BeautifulSoup(html, 'lxml') 4    # print(content) 5    # print(type(content)) 6    # print('------------') 7    items = range(10) 8    for item in items: 9        yield{1011            'index': soup.select('dd i.board-index')[item].string,12            # iclass節點完整地為'board-index board-index-1',寫board-index即可13            'thumb': get_thumb(soup.select('a > img.board-img')[item]["data-src"]),14            # 表示a節點下面的class = board-img的img節點,注意瀏覽器eelement裡面是src節點,而network裡面是data-src節點,要用這個才能正確返回值1516            'name': soup.select('.name a')[item].string,17            'star': soup.select('.star')[item].string.strip()[3:],18            'time': get_release_time(soup.select('.releasetime')[item].string.strip()[5:]),19            'area': get_release_area(soup.select('.releasetime')[item].string.strip()[5:]),20            'score': soup.select('.integer')[item].string + soup.select('.fraction')[item].string2122        }

運行上述程序,結果同第1種方法一樣。

3.3.4. Beautiful Soup + find_all函數提取

Beautifulsoup除了和css選擇器搭配,還可以直接用它自帶的find_all函數進行提取。
find_all,顧名思義,就是查詢所有符合條件的元素,可以給它傳入一些屬性或文本來得到符合條件的元素,功能十分強大。
它的API如下:

1find_all(name , attrs , recursive , text , **kwargs)

常用的語法規則如下:
soup.find_all(name='ul'): 查找所有
ul節點,ul節點內還可以嵌套;
li.string和li.get_text():都是獲取
li節點的文本,但推薦使用後者;
soup.find_all(attrs={'id': 'list-1'})):傳入 attrs 參數,參數的類型是字典類型,表示查詢
idlist-1 的節點;
常用的屬性比如 id、class 等,可以省略attrs採用更簡潔的形式,例如:
soup.find_all(id='list-1')
soup.find_all(class_='element')

根據上述常用語法,可以提取網頁中所需內容:

1def parse_one_page4(html): 2    soup = BeautifulSoup(html,'lxml') 3    items = range(10) 4    for item in items: 5        yield{ 6 7            'index': soup.find_all(class_='board-index')[item].string, 8            'thumb': soup.find_all(class_ = 'board-img')[item].attrs['data-src'], 9            # 用.get('data-src')獲取圖片src連結,或者用attrs['data-src']10            'name': soup.find_all(name = 'p',attrs = {'class' : 'name'})[item].string,11            'star': soup.find_all(name = 'p',attrs = {'class':'star'})[item].string.strip()[3:],12            'time': get_release_time(soup.find_all(class_ ='releasetime')[item].string.strip()[5:]),13            'area': get_release_time(soup.find_all(class_ ='releasetime')[item].string.strip()[5:]),14            'score':soup.find_all(name = 'i',attrs = {'class':'integer'})[item].string.strip() + soup.find_all(name = 'i',attrs = {'class':'fraction'})[item].string.strip()1516        }

以上就是4種不同的內容提取方法。

3.4. 數據存儲

上述輸出的結果為字典格式,可利用csv包的DictWriter函數將字典格式數據存儲到csv文件中。

1# 數據存儲到csv2def write_to_file3(item):3    with open('貓眼top100.csv', 'a', encoding='utf_8_sig',newline='') as f:4        # 'a'為追加模式(添加)5        # utf_8_sig格式導出csv不亂碼 6        fieldnames = ['index', 'thumb', 'name', 'star', 'time', 'area', 'score']7        w = csv.DictWriter(f,fieldnames = fieldnames)8        # w.writeheader()9        w.writerow(item)

然後修改一下main()方法:

1def main(): 2    url = 'http://maoyan.com/board/4?offset=0' 3    html = get_one_page(url) 4 5    for item in parse_one_page(html):   6        # print(item) 7        write_to_csv(item) 8 910if __name__ == '__main__':11    main()

結果如下圖:


再將封面的圖片下載下來:

1def download_thumb(name, url,num): 2    try: 3        response = requests.get(url) 4        with open('封面圖/' + name + '.jpg', 'wb') as f: 5            f.write(response.content) 6            print('第%s部電影封面下載完畢' %num) 7            print('------') 8    except RequestException as e: 9        print(e)10        pass11     # 不能是w,否則會報錯,因為圖片是二進位數據所以要用wb

3.5. 分頁爬取

上面完成了一頁電影數據的提取,接下來還需提取剩下9頁共90部電影的數據。對網址進行遍歷,給網址傳入一個offset參數即可,修改如下:

1def main(offset): 2    url = 'http://maoyan.com/board/4?offset=' + str(offset) 3    html = get_one_page(url) 4 5    for item in parse_one_page(html):   6        # print(item) 7        write_to_csv(item) 8 910if __name__ == '__main__':11    for i in range(10):12        main(offset = i*10)

這樣就完成了所有電影的爬取。結果如下:



4. 可視化分析

俗話說「文不如表,表不如圖」。下面根據excel的數據結果,進行簡單的數據可視化分析,並用圖表呈現。

4.1. 電影評分最高top10

首先,想看一看評分最高的前10部電影是哪些?

程序如下:

1import pandas as pd
2import matplotlib.pyplot as plt
3import pylab as pl #用於修改x軸坐標
4
5plt.style.use('ggplot') #默認繪圖風格很難看,替換為好看的ggplot風格
6fig = plt.figure(figsize=(8,5)) #設置圖片大小
7colors1 = '#6D6D6D' #設置圖表title、text標註的顏色
8
9columns = ['index', 'thumb', 'name', 'star', 'time', 'area', 'score'] #設置表頭
10df = pd.read_csv('maoyan_top100.csv',encoding = "utf-8",header = None,names =columns,index_col = 'index') #打開表格
11# index_col = 'index' 將索引設為index
12
13df_score = df.sort_values('score',ascending = False) #按得分降序排列
14
15name1 = df_score.name[:10] #x軸坐標
16score1 = df_score.score[:10] #y軸坐標
17plt.bar(range(10),score1,tick_label = name1) #繪製條形圖,用range()能搞保持x軸正確順序
18plt.ylim ((9,9.8)) #設置縱坐標軸範圍
19plt.title('電影評分最高top10',color = colors1) #標題
20plt.xlabel('電影名稱') #x軸標題
21plt.ylabel('評分') #y軸標題
22
23# 為每個條形圖添加數值標籤
24for x,y in enumerate(list(score1)):
25 plt.text(x,y+0.01,'%s' %round(y,1),ha = 'center',color = colors1)
26
27pl.xticks(rotation=270) #x軸名稱太長發生重疊,旋轉為縱向顯示
28plt.tight_layout() #自動控制空白邊緣,以全部顯示x軸名稱
29# plt.savefig('電影評分最高top10.png') #保存圖片
30plt.show()

結果如下圖:


可以看到:排名最高的分別是兩部國產片"霸王別姬"和"大話西遊",其他還包括"肖申克的救贖"、"教父"等。
嗯,還好基本上都看過。

4.2. 各國家的電影數量比較

然後,想看看100部電影都是來自哪些國家?
程序如下:

1area_count = df.groupby(by = 'area').area.count().sort_values(ascending = False) 2 3# 繪圖方法1 4area_count.plot.bar(color = '#4652B1')  #設置為藍紫色 5pl.xticks(rotation=0)   #x軸名稱太長重疊,旋轉為縱向 6 7 8# 繪圖方法2 9# plt.bar(range(11),area_count.values,tick_label = area_count.index)1011for x,y in enumerate(list(area_count.values)):12    plt.text(x,y+0.5,'%s' %round(y,1),ha = 'center',color = colors1)13plt.title('各國/地區電影數量排名',color = colors1)14plt.xlabel('國家/地區')15plt.ylabel('數量(部)')16plt.show()17# plt.savefig('各國(地區)電影數量排名.png')

結果如下圖:


可以看到,除去網站自身沒有顯示國家的電影以外,上榜電影被10個國家/地區"承包"了。其中,美國以30部電影的絕對優勢佔據第1名,其次是8部的日本,韓國第3,居然有7部上榜。

不得不說的是香港有5部,而內地一部都沒有。。。

4.3. 電影作品數量集中的年份

接下來站在漫長的百年電影史的時間角度上,分析一下哪些年份"貢獻了"最多的電影數量,也可以說是"電影大年"。

1# 從日期中提取年份 2df['year'] = df['time'].map(lambda x:x.split('/')[0]) 3# print(df.info()) 4# print(df.head()) 5 6# 統計各年上映的電影數量 7grouped_year = df.groupby('year') 8grouped_year_amount = grouped_year.year.count() 9top_year = grouped_year_amount.sort_values(ascending = False)101112# 繪圖13top_year.plot(kind = 'bar',color = 'orangered') #顏色設置為橙紅色14for x,y in enumerate(list(top_year.values)):15    plt.text(x,y+0.1,'%s' %round(y,1),ha = 'center',color = colors1)16plt.title('電影數量年份排名',color = colors1)17plt.xlabel('年份(年)')18plt.ylabel('數量(部)')1920plt.tight_layout()21# plt.savefig('電影數量年份排名.png')2223plt.show()

結果如下圖:


可以看到,100部電影來自37個年份。其中2011年上榜電影數量最多,達到9部;其次是前一年的7部。回憶一下,那會兒正是上大學的頭兩年,可怎麼感覺除了阿凡達之外,沒有什麼其他有印象的電影了。。。

另外,網上傳的號稱"電影史奇蹟年"的1994年僅排名第6。這讓我進一步對貓眼榜單的權威性產生了質疑。
再往後看,發現遙遠的1939和1940年也有電影上榜。那會兒應該還是黑白電影時代吧,看來電影的口碑好壞跟外在的技術沒有絕對的關係,質量才是王道。

4.3.1. 擁有電影作品數量最多的演員

最後,看看前100部電影中哪些演員的作品數量最多。
程序如下:

1#表中的演員位於同一列,用逗號分割符隔開。需進行分割然後全部提取到list中 2starlist = [] 3star_total = df.star 4for i in df.star.str.replace(' ','').str.split(','): 5    starlist.extend(i)   6# print(starlist) 7# print(len(starlist)) 8 9# set去除重複的演員名10starall = set(starlist)11# print(starall)12# print(len(starall))1314starall2 = {}15for i in starall:16    if starlist.count(i)>1:17        # 篩選出電影數量超過1部的演員18        starall2[i] = starlist.count(i)1920starall2 = sorted(starall2.items(),key = lambda starlist:starlist[1] ,reverse = True)2122starall2 = dict(starall2[:10])  #將元組轉為字典格式2324# 繪圖25x_star = list(starall2.keys())      #x軸坐標26y_star = list(starall2.values())    #y軸坐標2728plt.bar(range(10),y_star,tick_label = x_star)29pl.xticks(rotation = 270)30for x,y in enumerate(y_star):31    plt.text(x,y+0.1,'%s' %round(y,1),ha = 'center',color = colors1)3233plt.title('演員電影作品數量排名',color = colors1)34plt.xlabel('演員')35plt.ylabel('數量(部)')36plt.tight_layout()37plt.show()    38# plt.savefig('演員電影作品數量排名.png')

結果如下圖:


張國榮排在了第一位,這是之前沒有猜到的。其次是梁朝偉和星爺,再之後是布拉德·皮特。驚奇地發現,前十名影星中,香港影星居然佔了6位。有點嚴重懷疑這是不是香港版的top100電影。。。

對張國榮以7部影片的巨大優勢雄霸榜單第一位感到好奇,想看看是哪7部電影。

1df['star1'] = df['star'].map(lambda x:x.split(',')[0])  #提取1號演員2df['star2'] = df['star'].map(lambda x:x.split(',')[1])  #提取2號演員3star_most = df[(df.star1 == '張國榮') | (df.star2 == '張國榮')][['star','name']].reset_index('index')4# |表示兩個條件或查詢,之後重置索引5print(star_most)

可以看到包括排名第1的"霸王別姬"、第17名的"春光乍洩"、第27名的"射鵰英雄傳之東成西就"等。
突然發現,好像只看過"英雄本色"。。。有時間,去看看他其他的作品。

1     index        star              name20      1   張國榮,張豐毅,鞏俐        霸王別姬31     17   張國榮,梁朝偉,張震        春光乍洩42     27  張國榮,梁朝偉,張學友  射鵰英雄傳之東成西就53     37  張國榮,梁朝偉,劉嘉玲        東邪西毒64     70   張國榮,王祖賢,午馬        倩女幽魂75     99  張國榮,張曼玉,劉德華        阿飛正傳86    100   狄龍,張國榮,周潤發        英雄本色

由於數據量有限,故僅作了上述簡要的分析。

相關焦點

  • Python爬蟲正則案例:爬取貓眼電影
    主要內容requests設置headers,防止反爬爬取內容結果json保存多線程抓取設置headers設置headers的主要目的就是防止用戶請求被請求頁面判定為惡意請求,最基本的就是要讓用戶的請求模擬瀏覽器請求的方式。
  • 如何利用python爬蟲爬取各大網站VIP電影?小白都能看懂
    環境:windows python3.7文末有最新python資料下載地址以及視頻 思路:1、先選取你要爬取的電影2、用vip解析工具解析,獲取地址3、寫好腳本,下載片斷>2、import requests模塊安裝方法用windows命令行終端pip install requests 一、先選取你要爬
  • python爬蟲系列教程,用python爬取全國範圍內的KFC店地址
    下面羽憶教程教你會python爬取全國範圍內的KFC店地址,這是一篇python爬蟲系列的教程,簡單又能讓人填飽肚子。python爬蟲介紹python發展至今,python爬蟲已經成為了一種職業,因為其可以幫助企業快速得到網絡上的最新信息,但是為什麼很多寫python爬蟲的程式設計師會面臨牢獄之災呢?
  • Python爬蟲「學前班」!別踩坑了!輕鬆爬取大規模數據
    前言爬蟲應用的廣泛,例如搜尋引擎、採集數據、廣告過濾、數據分析等。當我們對少數網站內容進行爬取時寫多個爬蟲還是有可能的,但是對於需要爬取多個網站內容的項目來說是不可能編寫多個爬蟲的,這個時候我們就需要智能爬蟲。
  • Python爬蟲框架:scrapy爬取迅雷電影天堂最新電影
    電影信息電影內容劇情電影下載地址分析完成之後就可以首先編寫 items.py文件另外別忘了去settings.py中開啟 ITEM_PIPELINES 選項爬蟲文件編寫老樣子,為了方便測試我們的爬蟲,好的,發現直接返回正常的網頁也就是我們要的網頁,說明該網站沒有反爬機制
  • 2020年度火熱開發實戰:python爬蟲爬取美女圖片
    岸圖網站裡有大量的高清圖片素材和壁紙,並且可以免費下載,讀者也可以根據自己需要爬取其他類型圖片,方法是類似的,本文通過python爬蟲批量下載網站裡的高清美女圖片,熟悉python寫爬蟲的基本方法:發送請求、獲取響應、解析並提取數據、保存到本地。
  • 用python爬貓眼電影,簡單網站卻有「多重思路」
    七夕不看電影就爬電影吧。貓眼電影作為爬蟲的必備練手網站,相信每個人都試過吧?爬蟲思路:本次爬取網站為: https://maoyan.com/board/4?因為是要爬取T100或者更多, 觀察每一頁的網址特點,我們發現:https://maoyan.com/board/4?offset=0 1https://maoyan.com/board/4?offset=10 2https://maoyan.com/board/4?
  • python爬蟲29 | 使用scrapy爬取糗事百科
    是時候給你說說爬蟲框架了使用框架來爬取數據會節省我們更多時間很快就能抓取到我們想要抓取的內容好了現在假設你已經安裝好了 scrapy 這個框架那麼接下來小帥b會帶你使用它來爬取一下接著我們要定義一個爬蟲的名稱這裡定義一個唯一的名稱用來標識糗事的爬蟲在項目中不能和別的爬蟲名稱一樣
  • Python爬蟲:爬取虎牙星秀主播圖片
    動態爬取思路講解導入需要的python模塊通過爬蟲獲得的主播圖片在Pycharm中所敲的代碼動態爬取思路講解1.簡單的爬蟲只需要訪問網站搜索欄處的url,就可以在開發者工具(F12)處,利用正則表達式、Xpath、css等進行定位並抓取數據;2.虎牙星秀頁面不同於簡單的網頁
  • Python多進程爬蟲爬取愛奇藝vip視頻
    目標url:https://www.lagou.com/用selenium爬蟲實現,輸入任意關鍵字,比如 python 數據分析,點擊搜索,得到的有關崗位信息,爬取下來保存到Excel。輸入關鍵字 browser.find_element_by_class_name(&39;).click() 最大化窗口 time.sleep(2) browser.find_element_by_class_name(&39;).click() 34;scroll(0,3000)& 下拉滾動條 get_data() 模擬點擊下一頁 翻頁爬取數據
  • Python爬蟲實戰:2020最新BOOS直聘爬取教程
    Python爬蟲實戰:2020最新BOOS直聘爬取教程前言完整代碼及注釋分析圖片輔助分析運行結果更多爬蟲教程關注我,經過多次的爬取之後。。。。。。。失策失策,以前爬取別的網站從沒有這麼嚴格的反爬蟲機制,沒到到翻車了
  • 2020年度火熱開發實戰:python爬蟲爬取ge圖片各類
    岸圖網站裡有大量的高清圖片素材和壁紙,並且可以免費下載,讀者也可以根據自己需要爬取其他類型圖片,方法是類似的,本文通過python爬蟲批量下載網站裡的高清美女圖片,熟悉python寫爬蟲的基本方法:發送請求、獲取響應、解析並提取數據、保存到本地。
  • python爬蟲如何爬取各大招聘網站?看完本文你就會了
    拉勾網爬蟲筆記——selenium爬取拉勾網職位信息初步爬蟲框架構造第一頁職位信息爬取第二頁等頁面的職位信息爬取爬取數據的保存細節處理爬取過程中出現需要登錄的處理爬取過程中網頁崩潰的處理在拉勾網的爬蟲過程中,由於反爬蟲機制,requests方法爬取嘗試失敗,故嘗試採用selenium爬取職位信息,以python職位信息為例(拉勾網搜索python):
  • python爬蟲senlenium爬取拉勾網招聘數據
    ,輸入任意關鍵字,比如 python 數據分析,點擊搜索,得到的有關崗位信息,爬取下來保存到Excel#39;body-btn').click() # 關閉彈窗 啥領取紅包窗口 time.sleep(random.randint(1, 3)) browser.execute_script("scroll(0,3000)") # 下拉滾動條 get_data() # 調用抓取數據的函數 # 模擬點擊下一頁 翻頁爬取數據
  • Python爬蟲快速入門,靜態網頁爬取
    一、數據解析在爬取之前,我們需要檢測下響應狀態碼是否為200,如果請求失敗,我們將爬取不到任何數據:import requestsre = requests.get(&39;)if re.status_code == 200: print
  • Python爬蟲爬取微信朋友圈的方法,感興趣的朋友可以了解下
    小雨 | 作者python教程 | 來源接下來,我們將實現微信朋友圈的爬取。self.crawl()這樣我們就完成了整個朋友圈的爬蟲。控制臺輸出相應的爬取結果,結果被成功保存到 MongoDB 資料庫中。6. 結果查看我們到 MongoDB 中查看爬取結果,如圖所示。
  • 13天搞定python網絡爬蟲
    什麼是爬蟲?網絡爬蟲也叫網絡蜘蛛,如果把網際網路比喻成一個蜘蛛網,那麼蜘蛛就是在網上爬來爬去的蜘蛛,爬蟲程序通過請求url地址,根據響應的內容進行解析採集數據, 比如:如果響應內容是html,分析dom結構,進行dom解析、或者正則匹配,如果響應內容是xml/json數據,就可以轉數據對象,然後對數據進行解析。
  • PythonPython100個練手項目|github|瀏覽器|爬蟲|python|斷點_網易...
    天貓商品數據爬蟲    3. 爬取淘寶我已購買的寶貝數據    4. 每天不同時間段通過微信發消息提醒女友    5. 爬取5K解析度超清唯美壁紙    6. 爬取豆瓣排行榜電影數據(含GUI界面版)    7.
  • 最簡單的Python爬蟲,僅3步11行代碼爬取豆瓣電影排名
    提到網絡爬蟲,很多人望而卻步,覺得非常難,其實非如此,哪怕沒有爬蟲基礎,也可以寫出一個簡單的爬蟲。萬丈高樓平地起,今天分享一個最簡單的爬蟲,目的是通過案例,使大家對爬蟲有一個直觀的認識。第一步:確定目標爬蟲的第一步是要確定爬取的目標,沒有目標就沒有方向,更無從寫代碼。
  • Python爬蟲入門實例之爬取軟科中國大學排名
    2.爬取內容  本例爬取的是下圖的排名、大學名稱、:僅對輸入URL進行爬取,不擴展爬取註:requestts和bs4庫的使用只能獲取靜態頁面的信息,如何獲取動態頁面信息,我會在後邊專門寫篇文章詳細說明但該方法只能刪除開頭或是結尾的字符,不能刪除中間部分的字符。用在此處可以使爬取的內容,在格式化輸出時達到對齊的效果。