acfun網站400W使用者資料分析和pyecharts視覺化
首先在這給我心愛的Acfun說句抱歉了,這幾天進行的資料爬取如果對猴山產生了不好的影響,請接受我的道歉。
本次所有程式碼都會上傳到GitHub上:爬蟲部分和ip搜尋部分
sql檔案地址:百度雲盤 密碼:5xov
專案程式碼分成三個部分:
1、爬取基礎資料
2、根據ip地址查詢相對應的省市地址
3、統計:將你想檢視的html複製下來然後網頁開啟就能看到效果了
本次例項是通過分析A站獲取使用者資料的介面,通過scrapy獲取每個使用者的一些基本資料。包括ip,使用者名稱,最後登入時間,註冊時間等。
本次總共獲取的詳細資料有4302457條,詳細資料有:798817。資料丟失量在5%左右,由於A站的多次宕機和高層變動等原因,以及今年上半年‘涼了’的故事,或許對資料有一定的影響。導致本次資料獲取與統計,在14年前的統計感覺有失真實性。姑且就先這樣吧。
本次統計有:
1、從建站以來到2018-8月每年使用者註冊數量和消失數量柱狀圖
2、所有記錄中性別比例餅圖
3、所有修改了個性簽名使用者中,出現最頻繁的詞,生成詞雲圖
4、從2018-01-01以來,所有登入過A站的使用者全國省分佈圖
(正常情況下應該統計的事距離查詢完日期後,往前兩個月或者一個月仍會登入的使用者為活躍使用者)
5、每年註冊人數和十二個月中,每個月註冊人數折線圖和柱狀圖
本次所有統計生成工具為pyecharts。
為了方便展示,我在用pycharts生成檔案時,生成了png,其實這個生成html所形成的效果圖是最直觀的。頁面上會有一些動態操作可以進行。
統計1:
從圖中可以看出,17年的各種動盪和視訊內容的不完善與落後,讓許多Acer的腳步停留在了17年裡。
而18年的“A站已涼”更是加劇了這種顯現的出現。一直到幾年8月份,A站活躍使用者和新增的數量也往往不及前兩年。
統計2:
對,相信自己的眼睛,這大部分都是女性。 事實上是真的嘛? 不是的。今年上半年有一次資料調整,猴子在修改還是轉移資料的時候,將大部分人的性別修改成了女性
統計3:
詞雲圖生成可以看:
雖然A站的使用者以基佬遍天下而樂於自嘲,但是在個簽上能體現出的真不多,大多數是up主的一些微博微信qq群啥的,但是由此也能看到一些正常的感悟人生和個人興趣。
統計4:
由圖中可看出,A站使用者主要還是分佈在中部和東部地區。
在資料統計當中,還有國外的資料未統計在地圖中,計劃是在世界地圖中展示,然而pyecharts的作者們沒有新增世界地圖國家經緯度搜索,需要手動進行。有時間再做吧。需要一個個查座標的。。
但是看在控制檯輸出的資料中,各個發達國家和日本韓國登入使用者較多,也就是說大多數都是留學生出國在外的人訪問的多。(還有一些戰亂國家也有登入的,大兄弟!牛逼!)
統計5:
由這個統計可以看出來,每年的秋冬季節是註冊人數的高峰期,或許是因為天氣變冷,大家都不想出門,開始存膘過冬的習性,宅家裡進行一些網上娛樂就變多了。而春夏季節,則是減少的。春天了,又到了交配的季節了。。。你懂的,多出門約小姐姐,解決終身大事吧。
統計的相關程式碼:
# -*- coding: utf-8 -*- from pyecharts import Bar from pyecharts import Pie from pyecharts import Line from pyecharts import Geo import urllib.request import urllib.parse import json import pymysql # 獲取指定區間內男女比例 def create_gender_round(): sql = "select gender,count(*) from user_info group by gender " datas = get_all_data(sql) info_name = ['隱藏', '男性', '女性', 'Acer'] man = 0 women = 0 Xman = 0 acer = 0 for i in datas: if i[0] == -1: Xman = i[1] elif i[0] == 1: man = i[1] elif i[0] == 0: women = i[1] elif i[0] == 2: acer = i[1] pie = Pie('男女使用者比例') pie.add('性別比例圖', info_name, [Xman, man, women, acer], radius=None, center=None, rosetype='') # rosetype 是否展示成南丁格爾圖,通過半徑區分資料大小,有 # 'radius'和'area'兩種模式。預設為 # 'radius' # radius:扇區圓心角展現資料的百分比,半徑展現資料的大小 # area:所有扇區圓心角相同,僅通過半徑展現資料大小 # pie.render('detail\性別比例圖.html') pie.render('detail\比例圖.png') # 每年註冊人數 def create_bar_year(): sql = "select regtime from user_info order by regtime" data = get_all_data(sql) yera = {} for i in data: y = i[0][0:4] if y in yera: count = yera.get(y) count += 1 yera[y] = count else: yera[y] = 0 bar = Bar("每年註冊人數", "按年劃分") bar.add("", list(yera.keys()), list(yera.values())) # 生成折線圖 create_lin('每年註冊人數', list(yera.keys()), list(yera.values()), '每年註冊人數') bar.render(path='detail\註冊人數劃分_年.html') # 每個月註冊人數 def create_bar_month(): sql = "select regtime from user_info order by regtime" data = get_all_data(sql) months = {'01': 0, '02': 0, '03': 0, '04': 0, '05': 0, '06': 0, '07': 0, '08': 0, '09': 0, '10': 0, '11': 0, '12': 0, } for i in data: regTime = i[0][5:7] count = months.get(regTime) count += 1 months[regTime] = count create_lin('每個月註冊人數', list(months.keys()), list(months.values()), '') bar = Bar("每個月註冊人數", "按月劃分") bar.add("", list(months.keys()), list(months.values())) #生成折線圖 create_lin('註冊人數劃分_月',list(months.keys()),list(months.values()),'註冊人數劃分_月') bar.render(path='detail\註冊人數劃分_月.html') # 生成本地 HTML 檔案 # 根據sql獲取指定區間內的資料 def get_all_data(sql): conn = pymysql.connect(host="localhost", user="root", passwd="Cs123456.", db="acfun", charset="utf8") cursor = conn.cursor() cursor.execute(sql) data = cursor.fetchall() cursor.close() conn.close() return data # 註冊人數與當年活躍人數對比圖 def year_2(): sql = "select regtime,lastLoginTime from user_info order by regtime" data = get_all_data(sql) yera = {} for i in data: y = i[0][0:4] y2 = str(i[1])[0:4] if y in yera: count = yera.get(y)[0] count += 1 yera[y][0] = count if y2 in yera: count_2 = yera.get(y2)[1] count_2 += 1 yera[y2][1] = count_2 else: yera[y2] = [0, 0] else: yera[y] = [0, 0] bar = Bar("年註冊人數與每年最後一次上線人數", "按年劃分") bar.add("", [k for k in sorted(yera.keys())], [yera[k][0] for k in sorted(yera.keys())]) bar.add("", [k for k in sorted(yera.keys())], [yera[k][1] for k in sorted(yera.keys())]) bar.render(path='detail\每年註冊人數與每年最後一次上線人數.html') # 折線圖,若想顯示兩條或多條,自己處理下,就是多加個add的事情 def create_lin(h_name, k, val, line_name): line = Line(h_name) line.add(line_name, k, val, mark_point=["average"]) line.render('detail\%s_折線圖.html' % h_name) #全國地圖點狀圖用到的方法 def geo_formatter(params): return params.name + ' : ' + params.value[2] # map圖,指定區間內,全國省使用者分佈圖 def Geo_create(): sql = "select comeFrom,count(*) from user_info where 1=1 and comeFrom is not NULL and comeFrom !='未知' and comeFrom !='' and lastLoginTime >= '2018-01-01 00:00:00' group by comeFrom order by comeFrom" datas = get_all_data(sql) city = {} country = {} for data in datas: #資料整理 b = data[0].find(',') s = data[0].encode('utf-8').decode('utf-8').find('市') sheng = data[0].encode('utf-8').decode('utf-8').find('省') zzq = data[0].encode('utf-8').decode('utf-8').find('自治區') if b is not -1: res, count = get_city_name(data, b, city) # print('b',data[0], '---', res, '-----', count, '----', sheng) if res in city: count = city[res] count += data[1] # print(res, '---', count) city[res] = count else: city[res] = data[1] elif zzq is not -1: res, count = get_city_name(data, zzq, city) # print('zzq',data[0], '---', res, '-----', count, '----', sheng) if res in city: count = city[res] count += data[1] # print(res, '---', count) city[res] = count else: city[res] = data[1] elif sheng is not -1: res, count = get_city_name(data, sheng, city) # print('sheng',data[0], '---', res, '-----', count, '----', sheng) if res in city: count = city[res] count += data[1] # print(res, '---', count) city[res] = count else: city[res] = data[1] elif s is not -1: res, count = get_city_name(data, b, city) # print('s',data[0], '---', res, '-----', count, '----', sheng) if res in city: count = city[res] count += data[1] # print(res, '---', count) city[res] = count else: city[res] = data[1] else: # print(data[0],'------',data[1]) if data[0] in country: count = country[data[0]] count += data[1] else: country[data[0]] = data[1] #去掉不識別的資料 del city['海外'] del country['AFRINIC'] del country['APNIC'] del country['RIPE'] del country['IANA'] del country['運營商級NAT'] country['中國'] = 0 for i in city: country['中國'] += city[i] f_country = {} for i in list(country.keys()): f_country[fanyi(i)] = country.pop(i) # print(city) print(f_country) create_geo('2018截止8月全國Acer省分佈情況', '', city, 'detail/2018截止8月全國Acer省分佈情況.html', 'china') # create_geo('2018截止8月全世界Acer省分佈情況', '', f_country, 'detail/2018截止8月世界Acer省分佈情況.html', 'world') #原本打算做世界地圖的,所以做了中文翻譯的請求 def fanyi(content): url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&sessionFrom=http://fanyi.youdao.com/' # 有道翻譯查詢入口 data = { # 表單資料 'i': content, 'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb', 'doctype': 'json', 'version': '2.1', 'keyfrom': 'fanyi.web', 'action': 'FY_BY_CLICKBUTTION', 'typoResult': 'false' } data = urllib.parse.urlencode(data).encode('utf-8') # 對POST資料進行編碼 response = urllib.request.urlopen(url, data) # 發出POST請求並獲取HTTP響應 html = response.read().decode('utf-8') # 獲取網頁內容,並進行解碼解碼 target = json.loads(html) # json解析 return target['translateResult'][0][0]['tgt'] #遮蔽的全國地圖的點狀圖 def create_geo(pname, cname, data, path, map_type): # geo = Geo(pname, cname, title_color="#fff", title_pos="center", width=1200, height=600, # background_color="#404a59", ) # attr, value = geo.cast(data) # geo.add("", attr, value, type="heatmap", is_random=True, is_legend_show=False, # maptype=map_type, # tooltip_formatter=geo_formatter, # 重點在這裡,將函式直接傳遞為引數。 # effect_scale=5) # geo = Geo( pname, cname, title_color="#fff", title_pos="center", width=1200, height=600, background_color="#404a59", ) attr, value = geo.cast(data) geo.add( "", attr, value, type="heatmap", maptype=map_type, is_visualmap=True, visual_range=[0, 300], visual_text_color="#fff", ) geo.render(path=path) #對查詢到的城市名稱資料進行過濾和數字統計 def get_city_name(data, n_len, city_list): res = data[0][0:n_len] count = 0 if res in city_list: count = city_list[res] count += data[1] else: count = data[1] return res, count if __name__ == '__main__': #create_gender_round() #create_bar_month() #create_bar_year() #year_2() Geo_create()
好了。本次統計到此結束。謝謝觀看。
pyecharts真的是一個非常方便的資料圖形展示工具,我這裡只是使用了最簡單的幾個樣板,還有更多更有趣也更科學的關係圖形展示,詳情請點選:pyecharts中文說明文件