摘要:今年的流浪地球這么火,通過爬取貓眼電影上網友對該片的評價如何。也許很多人在這天通過看流浪地球過節吧。
背景
最近幾年貓眼電影越來越熱門了,都差不多和豆瓣并駕齊驅了。今年的《流浪地球》這么火,通過爬取貓眼電影上網友對該片的評價如何。
爬取貓眼評論 找到評論網頁地址先打開貓眼官網找到《流浪地球》的介紹頁面:https://maoyan.com/films/248906
雖然顯示有112.4萬人評分,但是頁面只有熱門短評,其他評論都去哪里了,手機明明是有的。
那么我們用chrome切換到手機頁面:
打開開發者工具
開啟手機瀏覽功能
訪問手機版地址:http://m.maoyan.com/movie/248...$from=canary#
這時候我們就看到了所有的評論。
獲取評論請求地址在點擊打開“查看全部330613條討論”后,發現評論分為最熱和最新兩部分,最熱數量有限,而最新則是未經過處理的,也正是我們需要的。通過search來查看下對應的請求:
發現,在chrome 的網絡展示中發現只有一個類型為document的請求包含了所需的信息。那么這部分的評論獲取就需要解析網頁了,我們再把屏幕上的評論往下拉,發現會自動加載更多的評論,對應的chrome網絡請求多出來了兩個comments.json的請求:
果然這才是我們需要的!把初始頁面的url和這兩個json請求的url復制到一起比較一下:
http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset=0&limit=15&ts=0&type=3 http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset=15&limit=15&ts=1549965527295&type=3 http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset=30&limit=15&ts=1549965527295&type=3
我們可以發現規律:
初始頁面的ts值為0,隨后會有ts值,且保持不變。這里的ts是當前的時間戳,可以通過轉換工具查看:
offset是請求評論開始的序號,limit為請求的條數
再看返回的json結果:
data.comments中是評論的具體內容
paging中通過hasMore來告訴我們是否還有更多(判斷是否繼續抓取)
我們再嘗試下將offset設置為0,也加上ts參數:
http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset=0&limit=15&ts=1549965527295&type=3
發現也是可以獲取數據的:
那么通過offset和limit來控制每次請求獲取的數量。
我們還可以通過加大limit參數來嘗試,是否可以一次性獲取更多的評論:
http://m.maoyan.com/review/v2/comments.json?movieId=248906&userId=-1&offset=0&limit=30&ts=1549965527295&type=3
效果如下:
再增加limit的值,會發現評論數回到了15條,可見貓眼系統僅支持每次最多獲取30條。
構造請求url 方法一根據上面的分析,我們構造請求的url就很明確了:
從offset=0&limit=30開始
通過返回的paging.hasMore來判斷是否繼續抓取
下一個抓取的url中offset+=limit
只能抓取1000條?!根據上述分析,在返回的json數據中是可以看到總評論數的,但是實際抓取的時候,在offset超過1000之后,返回的數據中hasMore就變成了false。
于是嘗試通過瀏覽器一直下拉刷新,到達offset超過1000的情況,發現頁面會不停的發送請求,但也無法獲取數據。
那應該就是網站做了控制,不允許offset超過1000。
構造請求URL 方法二那么就要考慮其他構造url的方法來抓取了。先觀察下每個請求返回的信息:
發現每個comment里都包含有一個time信息,把time做一下處理:
2019-02-13 13:38:00##感覺韓朵朵這個人設是多余的 2019-02-13 13:38:00##真的感動 非常棒 2019-02-13 13:38:00##這電影大陸的起航 2019-02-13 13:38:00##不怎么樣,劇情挺感人,但是有點尷尬 2019-02-13 13:37:00##好看。。。。。。。。。。 2019-02-13 13:37:00##超級超級超級超級超級超級超級好看 2019-02-13 13:37:00##太牛逼了,中國科幻片可有一部能看的了。支持吳京 2019-02-13 13:36:00##不錯!中國科幻的希望 2019-02-13 13:36:00##中國里程碑式的科幻電影。 2019-02-13 13:36:00##什么垃圾座位沒人管的么亂坐的
可以發現后臺是按照時間順序的,每分鐘一個間隔,那么就可以考慮根據每次返回comment中的時間來更新url中的ts即可。
由于不確定每次請求返回的數據中包含了多長的時間段,且返回的第一個評論時間戳與第二個評論是不同的,所以抓取思路如下:
獲取請求數據
記錄第一個時間戳
記錄第二個時間戳
當遇到第三個時間戳時,將ts設置為第二個時間戳,重新構造url
如果單次抓取中每遇到第三個時間戳,則通過修改offset來繼續抓取,直到遇到第三個時間戳
抓取實現根據上面思路,實現相對就比較簡單了:
生成url
def get_url(): global offset url = "http://m.maoyan.com/review/v2/comments.json?movieId=" + movieId + "&userId=-1&offset=" + str( offset) + "&limit=" + str(limit) + "&ts=" + str(ts) + "&type=3" return url
訪問url
def open_url(url): global ua try: headers = {"User-Agent": ua.random} response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: return None except Exception as e: print(e) return None
數據處理:將評論保存并判斷是否要繼續抓取
def parse_json(data): global count global offset global limit global ts ts_duration = ts res = json.loads(data) comments = res["data"]["comments"] for comment in comments: comment_time = comment["time"] if ts == 0: ts = comment_time ts_duration = comment_time if comment_time != ts and ts == ts_duration: ts_duration = comment_time if comment_time !=ts_duration: ts = ts_duration offset = 0 return get_url() else: content = comment["content"].strip().replace(" ", "。") print("get comment " + str(count)) count += 1 write_txt(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(comment_time/1000)) + "##" + content + " ") if res["paging"]["hasMore"]: offset += limit return get_url() else: return None
最后一共抓取評論131106條,足夠做各種分析了
2019-02-13 18:13:11,625 - get_comments.py[line:78] - INFO: get comment 131104 2019-02-13 18:13:11,729 - get_comments.py[line:78] - INFO: get comment 131105 2019-02-13 18:13:11,827 - get_comments.py[line:78] - INFO: get comment 131106 2019-02-13 18:13:15,416 - get_comments.py[line:98] - INFO: end數據分析 按日期匯總分析熱度
前面我們再抓取時,將評論的時間和內容通過csv的格式保存下來,并使用;分割。讀取csv文件并統計處理就要用到大名鼎鼎的pandas了。
讀取數據
pandas提供read_csv方法來直接獨處數據保存為DateFrame格式。
df = pd.read_csv("comment.csv", sep=";", header=None)
設置數據列名
由于我們知道數據有兩列,先通過這只列名可以方便后續引用。
df.columns = ["date", "comment"]
時間日期處理
在date列,我們保存的數據格式是string,需要把轉換為日期格式才能進一步處理。
df["date"] = pd.to_datetime(df["date"])
我們需要按時間來統計,所以把date列設置為index:
df = df.set_index("date")
日期篩選
由于我們知道《流浪地球》是2月5日上映的,我們可以對日期進行限定,以免出現有些在上映前的評論,會占用大段的空白情況。
設置index之后,可以參考list類型操作,由于時間是倒序的,所以可以直接使用[:"2019-02-04"]來選取2月4日之后到今天的所有數據。pandas在數據篩選方面相當智能,按照datetime的格式直接篩選即可。
cacu_df = df[:"2019-02-04"]
按日期進行數量統計
pandas中,通過resample方法進行重新采樣,通過傳入rule參數就可以按需要的頻率獲取數據,獲得一個resampler對象。
DataFrame.resample(rule, how=None, axis=0, fill_method=None, closed=None, label=None, convention="start", kind=None, loffset=None, limit=None, base=0, on=None, level=None)
resampler對象提供了很多的統計方法,比如匯總求和可使用Resampler.count()。
# 按日統計數量 cacu = cacu_df.resample("D").count()
這樣就完成了按日期求和統計操作。
繪圖
畫圖需要使用matplotlib庫,通過導入該庫,可直接對DateFrame對象進行畫圖處理。畫圖及圖表格式化如下:
# 設置中文字體 font = FontProperties(fname="/System/Library/Fonts/PingFang.ttc") plt.plot(cacu) plt.title("流浪地球評論分析", fontproperties=font) plt.xlabel("日期", fontproperties=font) plt.ylabel("評論數", fontproperties=font) plt.axis("tight") # 顯示網格 plt.grid(True) # 自動旋轉橫軸日期 plt.gcf().autofmt_xdate() # 顯示數值 for a, b in zip(cacu.index, cacu.values): plt.text(a, b, str(b[0])) # 保存圖片 plt.savefig("comment_analysis.png") # 查看圖片 plt.show()
分析結果
結果如下:
可見從上映之后,關注度直線飆升,到2月10日之后(上映5天),大家關注度逐漸下降。其中2月14日為情人節,大家的關注又有了小幅的上升。也許很多人在這天通過看《流浪地球》過節吧。
制作評論熱點圖云
數據清洗
首先由于評論是用戶發表的,可能什么字符都會有,要先把一些特殊符號去掉,這里就用到了正則替換:
msg = re.sub("[s+.!/_,$%^*()+""?]+|[+——!,。?、~@#¥%……&*()【】;:]+|[.+]|[.+]", "", line)
分詞與標簽
清洗后的數據,可以使用jieba分詞包來進行分詞,并把所有的分詞保存在一個list中,然后計算出每個分詞出現的次數。
# 分詞 tags = jieba.analyse.extract_tags(msg) for t in tags: word_list.append(t) # 計算詞頻 for word in word_list: if word not in word_dict: word_dict[word] = 1 else: word_dict[word] += 1
生成詞云
使用wordcloud包,就可以很方便的生成詞云圖片了。
先新建一個WordCloud對象,進行配置,然后利用前面的分詞詞頻就可以生成對應的圖片了。
# 計算圖片顏色 alice_coloring = np.array(img) my_wordcloud = WordCloud(background_color="white", max_words=500, mask=alice_coloring, max_font_size=200, random_state=42, font_path=(os.path.join(d, "font/msyh.ttf"))) my_wordcloud = my_wordcloud.generate_from_frequencies(wordList)
這里需要注意的是:
mask=alice_coloring:這里通過numpy將圖片矩陣化,來獲取圖片的顏色作為WordCloud的mask,是為了最后生成的圖云不僅外形與我們輸入的圖片保持一致,而且整體顏色也保持一致。
輸入的原圖,背景色需要設置為白色而不是透明色,否則會全屏幕都是字。。。
對于中文的詞云,需要制定中文的字體,這里用的是微軟雅黑
保存圖片
最后使用matplotlib.pyplot來保存圖片,保存前要進行圖片屬性的一些設置。
width = img.width/80 height = img.height/80 plt.figure(figsize=(width, height)) plt.imshow(my_wordcloud.recolor(color_func=image_colors)) plt.imshow(my_wordcloud) plt.axis("off") # 通過設置subplots_adjust來控制畫面外邊框 plt.subplots_adjust(bottom=.01, top=.99, left=.01, right=.99) plt.savefig("jupiter_wordcloud_1.png") plt.show()
這里需要注意的是: 建議根據原圖片的長寬比例進行一定的縮小,以免生成的圖片像素過大而產生報錯。
ValueError: Image size of 98400x46500 pixels is too large. It must be less than 2^16 in each direction.
詞云展示
放一張原圖,你能看的出來嘛,摳圖技術有限O(∩_∩)O哈哈~
以上就是使用抓取的評論生成詞云的大致思路,完成的實現代碼請見:https://github.com/keejo125/w...
如果有更好的方法,歡迎一起探討。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/43242.html
摘要:另外由于豆瓣上一些電影評分數量太少而不顯示,所以這里的電影數量會和票房數量有所差異。月度票房將類型片的票房按月劃分,得到了這張圖。 去年末的時候,我招收了新的 實訓生 。本文是其中一位 @齊大圣 同學在實訓兩個月時完成的項目案例。(碼上行動群里同學應該都看過這個名字,現在也是助教之一。)項目最初的想法是, 從互聯網上的公開信息中采集2018年在國內上映電影的票房、評分、類型、演員等信息...
摘要:作者周蘿卜鏈接長津湖貓眼影評歡迎關注,專注數據分析數據挖掘好玩工具對于這個十一黃金周的電影市場,絕對是長津湖的天下,短短幾天,票房就已經突破億,大有奮起直追戰狼的盡頭。 ...
摘要:來源重力助推而在影片中,也就是為了獲取更大的速度以脫離太陽系,人類才選擇借助木星的引力彈弓效應。引力彈弓的概念在幾年前的星際穿越和火星救援中都有提及,我一直想寫個模擬,直到這次趁流浪地球熱映的機會才動手實現。 本文涉及影片內容,但算不上劇透。想看還未看的同學請謹慎閱讀。 春節檔的幾部電影里,《 流浪地球 》成為一匹黑馬,刷爆微博和朋友圈,從最初不高的排片率,一躍上升到票房榜首。 看過影...
摘要:最近的股市有點熱鬧上證指數從開年的點,幾乎一路漲到前幾天的點,短短兩個月,最高漲幅超過。橫軸是日期,縱軸紅線是上證指數,綠線和藍柱是什么數據大家可以先自己猜一下。 注:本文首發于2019年3月11日。本想等3月的官方報告出來后修正文中數據。但很神奇的是,本文發布之后,中登公司的每周數據就再無更新。直到近日,公布了3月的月度數據,確實在意料之中,環比增加了一倍。 最近的股市有點熱鬧:上證...
閱讀 2318·2021-11-22 12:01
閱讀 1999·2021-11-12 10:34
閱讀 4520·2021-09-22 15:47
閱讀 2834·2019-08-30 15:56
閱讀 2866·2019-08-30 15:53
閱讀 2407·2019-08-30 13:53
閱讀 3383·2019-08-29 15:35
閱讀 3129·2019-08-29 12:27