一句話概括本文:
爬取我主良緣交友所有的妹子資訊,利用Jupyter Notebook對五個方面: 身高,學歷,年齡,城市和交友宣言進行分析,並把分析結果通過pyecharts 進行資料視覺化。
引言:
本節應該是Python資料分析入門的最後一節了,資料分析的水可是深的很: 大資料處理,機器學習,深度學習,NLP等,當前能夠抓下資料,用好 pandas,numpy和matplotlib基礎三件套,完成資料視覺化就夠了。 上節分析拉勾網的Android招聘資料,沒什麼特別的感覺,我覺得 可能是資料太少了,加起來也就700來條。還有Jupyter Notebook 和pyecharts沒有去試試,有點美中不足,於是乎我又想著抓點 什麼分析分析。一天早上,日常出地鐵,電視上依舊無腦放著這樣 的廣告:我主良緣的公眾號,可以線上找物件的公眾號... 坐過深圳地鐵的應該不會陌生...突然靈光一閃,要不抓一波 我主良緣,分析分析都是些怎麼樣的妹子在找物件? 有idea了,接著就是看下抓資料的難度了,回公司直接開啟 官網,點開交友頁:
F12開啟抓包,大概看了抓取的難度不大,接著就開始爬資料環節啦~
1.資料抓取
列表滾動到底部載入更多,猜測是Ajax動態載入資料,直接攔截XHR
有點明顯,隨手點開一個:
喲,直接就是我們想要的資料了,接著研究下請求規律。 篩選條件都勾上,獲取一波所有的引數,然後再自行搭配。
抓包看下引數:
欄位 | 值 | 含義 |
---|---|---|
startage | 21 | 起始年齡 |
endage | 30 | 截止年齡 |
gender | 2 | 性別,1代表男,2代表女 |
cityid | 52 | 城市id,這個通過檢視頁面結構可以獲取熱門的幾個城市id |
startheight | 161 | 起始身高 |
endheight | 170 | 截止身高 |
marry | 1 | 結婚狀態,1未婚,3離異,4喪偶 |
astro | 2 | 星座,看下錶 |
lunar | 2 | 生肖,看下錶 |
education | 40 | 教育水平,看下錶 |
salary | 2 | 收入,看下錶 |
page | 1 | 頁數,一頁20條資料 |
抓的連結是:www.lovewzly.com/api/user/pc… 接著就是請求頭模擬了:
然後呢,我想抓所有未婚的妹子的資訊,查詢引數如下:
看下返回的Json,能拿到的引數如下:
欄位有:
頭像,出生年份,省份,性別, 學歷,身高,交友宣言,城市,使用者id,暱稱
東西都齊了,接著就是把爬到的資料寫到csv裡了,不難寫出這樣的程式碼:
沒用代理,這裡依舊是隨緣休眠,避免訪問過於頻繁ip被封,
接著掛著就好,大概要爬1.3個小時(沒有好的代理ip,不用多程式就這樣~) 抓取成功後的資料:
總共有15521條資料,可以,很nice,接著開始胡亂分析環節。
2.安裝Jupyter Notebook與pyecharts
在開始資料分析前,我們另外安裝兩個東西:
Jupyter Notebook:一個非常適合做資料分析的工具,可以在上面寫 程式碼,執行程式碼,寫文件,做資料視覺化展示。舉個例子: 在Pycharm上寫程式碼,matplotlib繪製的圖形要麼通過plt.show()展示出來 要麼儲存為一個圖片檔案,然後你要看的時候把圖片檔案開啟。 而使用Jupyter直接就可以看到,配合支援文件編寫,你都不需要報告了, 利用可以直接執行的特點,很多人都拿來直接寫Python教程,非常方便。 安裝也很簡單,直接通過pip命令安裝即可。
pip install jupyter notebook
複製程式碼
安裝完成後,命令列鍵入:jupyter notebook
會自動開啟一個網頁
點選New,選擇一個核心,比如Python3,然後會新建一個ipynb字尾的檔案, 點開會出現下面的頁面:
頁面比較簡單,自己點開摸索摸索吧,加號是新建一個單元格, 剪刀圖示是刪除單元格,接著是複製貼上單元格,單元格上下移, 執行,終止。Code那裡下拉可以選擇單元格編寫的內容;
執行的快捷鍵是:shift + enter,大概就這些,更多可見下述視訊教程:
Jupyter Notebook Tutorial: Introduction, Setup, and Walkthrough
再接著是安裝pyecharts,這是一個用於生成Echarts圖表的類庫, Echarts是百度開源的一個資料視覺化JS 庫。用Echarts生成的圖視覺化 效果非常棒,pyecharts是為了與 Python 進行對接,方便在Python中直接 使用資料生成圖,生成結果是一個html檔案,用瀏覽器開啟即可看到效果。
相關文件:
安裝方法同樣也很簡單,直接pip走一波:
pip install pyecharts
複製程式碼
安裝完之後,直接編寫程式碼繪製地圖,地圖區域是無法顯示,你需要 另外安裝地圖檔案:
pip install echarts-countries-pypkg
pip install echarts-china-provinces-pypkg
pip install echarts-china-cities-pypkg
複製程式碼
特別註明,中國地圖在 echarts-countries-pypkg 裡。 一般安裝第一個就夠了,其他看自己吧。 到此就準備好了,接下來開始編碼進行資料分析~
3.開始資料分析
這裡我們直接在Jupyter寫程式碼進行資料分析,命令列鍵入: jupyter notebook 開啟,然後來到我們的目錄下,新建一個WZLY.ipynb的檔案,進入後就可以 開始編寫程式碼了。
1.讀取CSV檔案裡的資料
2.分析身高
執行結果:
3.分析學歷
結果分析
4.分析年齡
執行結果:
5.分析城市
執行結果:
6.分析交友宣言
輸出結果
小結
以上就是對通過爬蟲採集到的我主良緣妹子交友資訊進行的簡單的資料分析, 主要目的還是試試Jupyter Notebook和pyechars這兩個東東,結果還是沒 分析出什麼特別有用的東西,分析完大概知道了這樣一些資訊:
- 1.妹子身高:集中在150-170cm之間,達到了**94.21%**的佔比;
- 2.妹子學歷:本科和大專是主力軍;
- 3.妹子年齡:26-30歲的最多,18-25次之,31-40歲的大齡剩女也挺多的;
- 4.妹子城市分佈:大部分還是集中在北深上廣,其次杭州,南京,廈門,福州,成都,武漢,青島;
- 5.妹子中意的物件特點:前八依次是責任心,上進心,事業心,熱愛生活,性格開朗,脾氣好,孝順父母,安全感
好吧,關於Python做資料分析就到這裡了,資料分析是一個方向,但是目前不會深究: 行業大資料 + 機器學習框架 + 深度學習演算法 => 人工智慧 so,不用我說什麼了,後面能有適合的環境,有這樣的機會研究這些東西, 再續寫相關的文章吧。後面的文章會寫回Python爬蟲,多程式,分散式爬蟲, 爬蟲與反爬蟲的策略研究,學習Redis,Mongodb,MySQL,Flask寫個自己 APP使用的API,Django,弄自己的網站等等,敬請期待~
附:最終程式碼(都可以在:github.com/coder-pig/R… 找到):
import requests as rq
import config as c
import tools as t
import pandas as pd
import numpy as np
import time
import random
import sys
from pyecharts import Bar, Pie, Funnel, Radar, Geo, WordCloud
import jieba as jb
import re
from collections import Counter
result_save_file = c.outputs_logs_path + 'wzly.csv'
# Ajax載入url
ajax_url = "http://www.lovewzly.com/api/user/pc/list/search?"
# 模擬請求頭
ajax_headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Connection': 'keep-alive',
'Host': 'www.lovewzly.com',
'Referer': 'http://www.lovewzly.com/jiaoyou.html',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 '
'Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}
# post請求引數
form_data = {'gender': '2', 'marry': '1', 'page': '1'}
# csv表頭
csv_headers = [
'暱稱', '使用者id', '頭像', '身高', '學歷', '省份',
'城市', '出生年份', '性別', '交友宣言'
]
height_interval = ['140', '150', '160', '170', '180'] # 身高範圍
edu_interval = ['本科', '大專', '高中', '中專', '初中', '碩士', '博士', '院士'] # 學歷範圍
age_interval = [
('18-30', 8000), ('26-30', 8000), ('31-40', 8000),
('41-50', 8000), ('50以上', 8000),
] # 學歷範圍
word_pattern = re.compile('[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?“”、~@#¥%……&*()(\d+)]+')
# 獲取每頁交友資訊
def fetch_data(page):
while True:
try:
form_data['page'] = page
print("抓取第:" + str(page) + "頁!")
resp = rq.get(url=ajax_url, params=form_data, headers=ajax_headers)
if resp.status_code == 200:
data_json = resp.json()['data']['list']
if len(data_json) > 0:
data_list = []
for data in data_json:
data_list.append((
data['username'], data['userid'], data['avatar'],
data['height'], data['education'], data['province'],
data['city'], data['birthdayyear'], data['gender'], data['monolog']))
result = pd.DataFrame(data_list)
if page == 1:
result.to_csv(result_save_file, header=csv_headers, index=False, mode='a+')
else:
result.to_csv(result_save_file, header=False, index=False, mode='a+')
return None
except Exception as e:
print(e)
# 分析身高
def analysis_height(data):
height_data = data['身高']
height = (height_data.loc[(height_data > 140) & (height_data < 200)]).value_counts().sort_index()
height_count = [0, 0, 0, 0, 0]
for h in range(0, len(height)):
if 140 <= height.index[h] < 150:
height_count[0] += height.values[h]
elif 150 <= height.index[h] < 160:
height_count[1] += height.values[h]
elif 160 <= height.index[h] < 170:
height_count[2] += height.values[h]
elif 170 <= height.index[h] < 180:
height_count[3] += height.values[h]
elif 180 <= height.index[h] < 190:
height_count[4] += height.values[h]
return height_count
# 分析學歷
def analysis_edu(data):
return data['學歷'].value_counts()
# 分析年齡
def analysis_age(data):
age_data = data['出生年份']
age = (age_data.loc[(age_data >= 1956) & (age_data <= 2000)]).value_counts().sort_index()
age_count = [0, 0, 0, 0, 0]
for h in range(0, len(age)):
if 1993 <= age.index[h] <= 2000:
age_count[0] += age.values[h]
elif 1988 <= age.index[h] <= 1992:
age_count[1] += age.values[h]
elif 1978 <= age.index[h] <= 1987:
age_count[2] += age.values[h]
elif 1968 <= age.index[h] <= 1977:
age_count[3] += age.values[h]
elif age.index[h] < 1968:
age_count[4] += age.values[h]
return age_count
# 分析城市分佈
def analysis_city(data):
city_data = data['城市'].value_counts()
city_list = []
for city in range(0, len(city_data)):
if city_data.values[city] > 10:
city_list.append((city_data.index[city], city_data.values[city]))
return city_list
# 詞頻分佈
def analysis_word(data):
word_data = data['交友宣言'].value_counts()
word_list = []
for word in range(0, len(word_data)):
if word_data.values[word] == 1:
word_list.append(word_data.index[word])
return word_list
# 繪製身高分佈柱狀圖
def draw_height_bar(data):
bar = Bar("妹子身高分佈柱狀圖")
bar.add("妹子身高", height_interval, data, bar_category_gap=0, is_random=True, )
return bar
# 繪製身高分佈餅圖
def draw_height_pie(data):
pie = Pie("妹子身高分佈餅圖-圓環圖", title_pos='center')
pie.add("", height_interval, data, radius=[40, 75], label_text_color=None,
is_label_show=True, legend_orient='vertical', is_random=True,
legend_pos='left')
return pie
# 學歷漏斗圖
def draw_edu_funnel(data):
funnel = Funnel("妹子學歷分佈漏斗圖")
funnel.add("學歷", edu_interval, data, is_label_show=True,
label_pos="inside", label_text_color="#fff", title_top=50)
return funnel
# 年齡雷達圖
def draw_age_radar(data):
radar = Radar("妹子年齡分佈雷達圖")
radar.config(age_interval)
radar.add("年齡段", data, is_splitline=True, is_axisline_show=True)
return radar
# 城市分佈地圖
def draw_city_geo(data):
geo = Geo("全國妹子分佈城市", "data about beauty", title_color="#fff",
title_pos="center", width=1200,
height=600, background_color='#404a59')
attr, value = geo.cast(data)
geo.add("", attr, value, visual_range=[10, 2500], visual_text_color="#fff",
symbol_size=15, is_visualmap=True)
return geo
# 交友宣言詞雲
def draw_word_wc(name, count):
wc = WordCloud(width=1300, height=620)
wc.add("", name, count, word_size_range=[20, 100], shape='diamond')
wc.render()
if __name__ == '__main__':
if not t.is_dir_existed(result_save_file, mkdir=False):
for i in range(1, 777):
time.sleep(random.randint(2, 10))
fetch_data(i)
else:
raw_data = pd.read_csv(result_save_file)
word_result = word_pattern.sub("", ''.join(analysis_word(raw_data)))
words = [word for word in jb.cut(word_result, cut_all=False) if len(word) >= 3]
exclude_words = [
'一輩子', '不相離', '另一半', '業餘時間', '性格特點', '茫茫人海', '男朋友', '找物件',
'談戀愛', '有時候', '女孩子', '哈哈哈', '加微信', '興趣愛好',
'是因為', '不良嗜好', '男孩子', '為什麼', '沒關係', '不介意',
'沒什麼', '交朋友', '大大咧咧', '大富大貴', '聯絡方式', '打招呼',
'有意者', '晚一點', '哈哈哈', '以上學歷', '是不是', '給我發',
'不怎麼', '第一次', '越來越', '遇一人', '擇一人', '無數次',
'符合條件', '什麼樣', '全世界', '比較簡單', '浪費時間', '不知不覺',
'有沒有', '尋尋覓覓', '自我介紹', '請勿打擾', '差不多', '不在乎', '看起來',
'一點點', '陪你到', '這麼久', '看清楚', '身高體重', '比較慢', '比較忙',
'多一點', '小女生', '土生土長', '發訊息', '最合適'
]
for i in range(0, len(words)):
if words[i] in exclude_words:
words[i] = None
filter_list = list(filter(lambda t: t is not None, words))
data = r' '.join(filter_list)
c = Counter(filter_list)
word_name = [] # 詞
word_count = [] # 詞頻
for word_freq in c.most_common(100):
word, freq = word_freq
word_name.append(word)
word_count.append(freq)
draw_word_wc(word_name, word_count)
複製程式碼
來啊,Py交易啊
想加群一起學習Py的可以加下,智障機器人小Pig,驗證資訊裡包含: Python,python,py,Py,加群,交易,屁眼 中的一個關鍵詞即可通過;
驗證通過後回覆 加群 即可獲得加群連結(不要把機器人玩壞了!!!)~~~ 歡迎各種像我一樣的Py初學者,Py大神加入,一起愉快地交流學♂習,van♂轉py。