Python分析44130條使用者觀影資料,挖掘使用者與電影之間的隱藏資訊!

語言: CN / TW / HK

01、前言

很多電影也上映,看電影前很多人都喜歡去 『豆瓣』 看影評,所以我爬取44130條 『豆瓣』 的使用者觀影資料,分析使用者之間的關係,電影之間的聯絡,以及使用者和電影之間的隱藏關係。

02、爬取觀影資料

資料來源

https://movie.douban.com/

在****『豆瓣』****平臺爬取使用者觀影資料。

爬取使用者列表

網頁分析

為了獲取使用者,我選擇了其中一部電影的影評,這樣可以根據評論的使用者去獲取其使用者名稱稱(後面爬取使用者觀影記錄只需要**『使用者名稱稱』******)。

https://movie.douban.com/subject/24733428/reviews?start=0

url中start引數是頁數(page*20,每一頁20條資料),因此start=0、20、40...,也就是20的倍數,通過改變start引數值就可以獲取這4614條使用者的名稱。

檢視網頁的標籤,可以找到******『使用者名稱稱』******值對應的標籤屬性。

程式設計實現

i=0
url = "https://movie.douban.com/subject/24733428/reviews?start=" + str(i * 20)
r = requests.get(url, headers=headers)
r.encoding = 'utf8'
s = (r.content)
selector = etree.HTML(s)
 
 
for item in selector.xpath('//*[@class="review-list  "]/div'):
    userid = (item.xpath('.//*[@class="main-hd"]/a[2]/@href'))[0].replace("https://www.douban.com/people/","").replace("/", "")
    username = (item.xpath('.//*[@class="main-hd"]/a[2]/text()'))[0]
    print(userid)
    print(username)
    print("-----")

爬取使用者的觀影記錄

上一步爬取到****『使用者名稱稱』,接著爬取使用者觀影記錄需要用到『使用者名稱稱』。****

網頁分析

#https://movie.douban.com/people/{使用者名稱稱}/collect?start=15&sort=time&rating=all&filter=all&mode=grid
https://movie.douban.com/people/mumudancing/collect?start=15&sort=time&rating=all&filter=all&mode=grid

通過改變****『使用者名稱稱』****,可以獲取到不同使用者的觀影記錄。

url中start引數是頁數(page*15,每一頁15條資料),因此start=0、15、30...,也就是15的倍數,通過改變start引數值就可以獲取這1768條觀影記錄稱。

檢視網頁的標籤,可以找到****『電影名』****值對應的標籤屬性。

程式設計實現

url = "https://movie.douban.com/people/mumudancing/collect?start=15&sort=time&rating=all&filter=all&mode=grid"
r = requests.get(url, headers=headers)
r.encoding = 'utf8'
s = (r.content)
selector = etree.HTML(s)
for item in selector.xpath('//*[@class="grid-view"]/div[@class="item"]'):
    text1 = item.xpath('.//*[@class="title"]/a/em/text()')
    text2 = item.xpath('.//*[@class="title"]/a/text()')
    text1 = (text1[0]).replace(" ", "")
    text2 = (text2[1]).replace(" ", "").replace("\n", "")
    print(text1+text1)
    print("-----")

儲存到excel

定義表頭

# 初始化execl表
def initexcel(filename):
    # 建立一個workbook 設定編碼
    workbook = xlwt.Workbook(encoding='utf-8')
    # 建立一個worksheet
    worksheet = workbook.add_sheet('sheet1')
    workbook.save(str(filename)+'.xls')
    ##寫入表頭
    value1 = [["使用者", "影評"]]
    book_name_xls = str(filename)+'.xls'
    write_excel_xls_append(book_name_xls, value1)

excel表有兩個標題(使用者, 影評)

寫入excel

# 寫入execl
def write_excel_xls_append(path, value):
    index = len(value)  # 獲取需要寫入資料的行數
    workbook = xlrd.open_workbook(path)  # 開啟工作簿
    sheets = workbook.sheet_names()  # 獲取工作簿中的所有表格
    worksheet = workbook.sheet_by_name(sheets[0])  # 獲取工作簿中所有表格中的的第一個表格
    rows_old = worksheet.nrows  # 獲取表格中已存在的資料的行數
    new_workbook = copy(workbook)  # 將xlrd物件拷貝轉化為xlwt物件
    new_worksheet = new_workbook.get_sheet(0)  # 獲取轉化後工作簿中的第一個表格
    for i in range(0, index):
        for j in range(0, len(value[i])):
            new_worksheet.write(i+rows_old, j, value[i][j])  # 追加寫入資料,注意是從i+rows_old行開始寫入
    new_workbook.save(path)  # 儲存工作簿

定義了寫入excel函式,這樣爬起每一頁資料時候呼叫寫入函式將資料儲存到excel中。

最後採集了44130條資料(原本是4614個使用者,每個使用者大約有500~1000條資料,預計400萬條資料)。但是為了演示分析過程,只爬取每一個使用者的前30條觀影記錄(因為前30條是最新的)。

最後這44130條資料會在下面分享給大家

03、資料分析挖掘

讀取資料集

def read_excel():
    # 開啟workbook
    data = xlrd.open_workbook('豆瓣.xls')
    # 獲取sheet頁
    table = data.sheet_by_name('sheet1')
    # 已有內容的行數和列數
    nrows = table.nrows
    datalist=[]
    for row in range(nrows):
        temp_list = table.row_values(row)
        if temp_list[0] != "使用者" and temp_list[1] != "影評":
            data = []
            data.append([str(temp_list[0]), str(temp_list[1])])
            datalist.append(data)
    return datalist

從豆瓣.xls中讀取全部資料放到datalist集合中。

分析1:電影觀看次數排行

###分析1:電影觀看次數排行
def analysis1():
    dict ={}
    ###從excel讀取資料
    movie_data = read_excel()
    for i in range(0, len(movie_data)):
        key = str(movie_data[i][0][1])
        try:
            dict[key] = dict[key] +1
        except:
            dict[key]=1
    ###從小到大排序
    dict = sorted(dict.items(), key=lambda kv: (kv[1], kv[0]))
    name=[]
    num=[]
    for i in range(len(dict)-1,len(dict)-16,-1):
        print(dict[i])
        name.append(((dict[i][0]).split("/"))[0])
        num.append(dict[i][1])
    plt.figure(figsize=(16, 9))
    plt.title('電影觀看次數排行(高->低)')
    plt.bar(name, num, facecolor='lightskyblue', edgecolor='white')
    plt.savefig('電影觀看次數排行.png')

分析

  1. 由於使用者資訊來源於 『心靈奇旅』 評論,因此其使用者觀看量最大。
  2. 最近的熱播電影中,播放量排在第二的是 『送你一朵小紅花』,信條和拆彈專家2也緊跟其後。

分析2:使用者畫像(使用者觀影相同率最高)

###分析2:使用者畫像(使用者觀影相同率最高)
def analysis2():
    dict = {}
    ###從excel讀取資料
    movie_data = read_excel()
 
 
    userlist=[]
    for i in range(0, len(movie_data)):
        user = str(movie_data[i][0][0])
        moive = (str(movie_data[i][0][1]).split("/"))[0]
        #print(user)
        #print(moive)
 
 
        try:
            dict[user] = dict[user]+","+str(moive)
        except:
            dict[user] =str(moive)
            userlist.append(user)
 
 
    num_dict={}
    # 待畫像使用者(取第一個)
    flag_user=userlist[0]
    movies = (dict[flag_user]).split(",")
    for i in range(0,len(userlist)):
        #判斷是否是待畫像使用者
        if flag_user != userlist[i]:
            num_dict[userlist[i]]=0
            #待畫像使用者的所有電影
            for j in range(0,len(movies)):
                #判斷當前使用者與待畫像使用者共同電影個數
                if movies[j] in dict[userlist[i]]:
                    # 相同加1
                    num_dict[userlist[i]] = num_dict[userlist[i]]+1
    ###從小到大排序
    num_dict = sorted(num_dict.items(), key=lambda kv: (kv[1], kv[0]))
    #使用者名稱稱
    username = []
    #觀看相同電影次數
    num = []
    for i in range(len(num_dict) - 1, len(num_dict) - 9, -1):
        username.append(num_dict[i][0])
        num.append(num_dict[i][1])
 
 
    plt.figure(figsize=(25, 9))
    plt.title('使用者畫像(使用者觀影相同率最高)')
    plt.scatter(username, num, color='r')
    plt.plot(username, num)
    plt.savefig('使用者畫像(使用者觀影相同率最高).png')

分析

以使用者 『mumudancing』 為例進行使用者畫像

  1. 從圖中可以看出,與使用者 『mumudancing』 觀影相同率最高的是:“請帶我回布拉格”,其次是“李校尉”。

  2. 使用者:'絕命紙牌', '笨小孩', '私享史', '溫衡', '沈唐', '修左',的觀影相同率****相同

分析3:使用者之間進行電影推薦

###分析3:使用者之間進行電影推薦(與其他使用者同時被觀看過)
def analysis3():
    dict = {}
    ###從excel讀取資料
    movie_data = read_excel()
 
 
    userlist=[]
    for i in range(0, len(movie_data)):
        user = str(movie_data[i][0][0])
        moive = (str(movie_data[i][0][1]).split("/"))[0]
        #print(user)
        #print(moive)
 
 
        try:
            dict[user] = dict[user]+","+str(moive)
        except:
            dict[user] =str(moive)
            userlist.append(user)
 
 
    num_dict={}
    # 待畫像使用者(取第2個)
    flag_user=userlist[0]
    print(flag_user)
    movies = (dict[flag_user]).split(",")
    for i in range(0,len(userlist)):
        #判斷是否是待畫像使用者
        if flag_user != userlist[i]:
            num_dict[userlist[i]]=0
            #待畫像使用者的所有電影
            for j in range(0,len(movies)):
                #判斷當前使用者與待畫像使用者共同電影個數
                if movies[j] in dict[userlist[i]]:
                    # 相同加1
                    num_dict[userlist[i]] = num_dict[userlist[i]]+1
    ###從小到大排序
    num_dict = sorted(num_dict.items(), key=lambda kv: (kv[1], kv[0]))
 
 
    # 去重(使用者與觀影率最高的使用者兩者之間重複的電影去掉)
    user_movies = dict[flag_user]
    new_movies = dict[num_dict[len(num_dict)-1][0]].split(",")
    for i in range(0,len(new_movies)):
        if new_movies[i] not in user_movies:
            print("給使用者("+str(flag_user)+")推薦電影:"+str(new_movies[i]))

分析

以使用者 『mumudancing』 為例,對使用者之間進行電影推薦

  1. 根據與使用者 『mumudancing』 觀影率最高的使用者(A)進行進行關聯,然後獲取使用者(A)的全部觀影記錄

  2. 將使用者(A)的觀影記錄推薦給使用者 『mumudancing』(去掉兩者之間重複的電影)。

分析4:電影之間進行電影推薦

###分析4:電影之間進行電影推薦(與其他電影同時被觀看過)
def analysis4():
    dict = {}
    ###從excel讀取資料
    movie_data = read_excel()
 
 
    userlist=[]
    for i in range(0, len(movie_data)):
        user = str(movie_data[i][0][0])
        moive = (str(movie_data[i][0][1]).split("/"))[0]
        try:
            dict[user] = dict[user]+","+str(moive)
        except:
            dict[user] =str(moive)
            userlist.append(user)
 
 
    movie_list=[]
    # 待獲取推薦的電影
    flag_movie = "送你一朵小紅花"
    for i in range(0,len(userlist)):
        if flag_movie in dict[userlist[i]]:
             moives = dict[userlist[i]].split(",")
             for j in range(0,len(moives)):
                 if moives[j] != flag_movie:
                     movie_list.append(moives[j])
 
 
    data_dict = {}
    for key in movie_list:
        data_dict[key] = data_dict.get(key, 0) + 1
 
 
    ###從小到大排序
    data_dict = sorted(data_dict.items(), key=lambda kv: (kv[1], kv[0]))
    for i in range(len(data_dict) - 1, len(data_dict) -16, -1):
            print("根據電影"+str(flag_movie)+"]推薦:"+str(data_dict[i][0]))

分析

以電影 『送你一朵小紅花』 為例,對電影之間進行電影推薦

  1. 獲取觀看過 『送你一朵小紅花』 的所有使用者,接著獲取這些使用者各自的觀影記錄。

  2. 將這些觀影記錄進行統計彙總(去掉“送你一朵小紅花”),然後進行從高到低進行排序,最後可以獲取到與電影 『送你一朵小紅花』 關聯度最高排序的集合。

  3. 關聯度最高的前15部電影給使用者推薦。

04、總結

  1. 分析爬取豆瓣平臺數據思路,並程式設計實現

  2. 對爬取的資料進行分析(電影觀看次數排行使用者畫像使用者之間進行電影推薦電影之間進行電影推薦