[关闭]
@coder-pig 2018-04-02T11:50:44.000000Z 字数 8569 阅读 1912

小猪的Python学习之旅 —— 17.Python数据分析:我主良缘交友了解下

Python


一句话概括本文

爬取我主良缘交友所有的妹子信息,利用Jupyter Notebook对五个方面:
身高,学历,年龄,城市和交友宣言进行分析,并把分析结果通过pyecharts
进行数据可视化。


引言

本节应该是Python数据分析入门的最后一节了,数据分析的水可是深的很:
大数据处理,机器学习,深度学习,NLP等,当前能够抓下数据,用好
pandas,numpy和matplotlib基础三件套,完成数据可视化就够了。
上节分析拉勾网的Android招聘数据,没什么特别的感觉,我觉得
可能是数据太少了,加起来也就700来条。还有Jupyter Notebook
pyecharts没有去试试,有点美中不足,于是乎我又想着抓点
什么分析分析。一天早上,日常出地铁,电视上依旧无脑放着这样
的广告:我主良缘的公众号,可以在线找对象的公众号...
坐过深圳地铁的应该不会陌生...突然灵光一闪,要不抓一波
我主良缘,分析分析都是些怎么样的妹子在找对象?
有idea了,接着就是看下抓数据的难度了,回公司直接打开
官网,点开交友页:

http://www.lovewzly.com/jiaoyou.html

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条数据

抓的链接是:http://www.lovewzly.com/api/user/pc/list/search?
接着就是请求头模拟了:

然后呢,我想抓所有未婚的妹子的信息,查询参数如下:

看下返回的Json,能拿到的参数如下:

字段有:

头像出生年份省份性别, 学历身高交友宣言城市用户id昵称

东西都齐了,接着就是把爬到的数据写到csv里了,不难写出这样的代码:

没用代理,这里依旧是随缘休眠,避免访问过于频繁ip被封,

接着挂着就好,大概要爬1.3个小时(没有好的代理ip,不用多进程就这样~)
抓取成功后的数据:

总共有15521条数据,可以,很nice,接着开始胡乱分析环节。


2.安装Jupyter Notebook与pyecharts

在开始数据分析前,我们另外安装两个东西:

Jupyter Notebook:一个非常适合做数据分析的工具,可以在上面写
代码,运行代码,写文档,做数据可视化展示。举个例子:
在Pycharm上写代码,matplotlib绘制的图形要么通过plt.show()展示出来
要么保存为一个图片文件,然后你要看的时候把图片文件打开。
而使用Jupyter直接就可以看到,配合支持文档编写,你都不需要报告了,
利用可以直接运行的特点,很多人都拿来直接写Python教程,非常方便。
安装也很简单,直接通过pip命令安装即可。

  1. 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走一波:

  1. pip install pyecharts

安装完之后,直接编写代码绘制地图,地图区域是无法显示,你需要
另外安装地图文件:

  1. pip install echarts-countries-pypkg
  2. pip install echarts-china-provinces-pypkg
  3. 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这两个东东,结果还是没
分析出什么特别有用的东西,分析完大概知道了这样一些信息:

好吧,关于Python做数据分析就到这里了,数据分析是一个方向,但是目前不会深究:
行业大数据 + 机器学习框架 + 深度学习算法 => 人工智能
so,不用我说什么了,后面能有适合的环境,有这样的机会研究这些东西,
再续写相关的文章吧。后面的文章会写回Python爬虫,多进程,分布式爬虫,
爬虫与反爬虫的策略研究,学习Redis,Mongodb,MySQL,Flask写个自己
APP使用的API,Django,弄自己的网站等等,敬请期待~


附:最终代码(都可以在:https://github.com/coder-pig/ReptileSomething 找到):

  1. import requests as rq
  2. import config as c
  3. import tools as t
  4. import pandas as pd
  5. import numpy as np
  6. import time
  7. import random
  8. import sys
  9. from pyecharts import Bar, Pie, Funnel, Radar, Geo, WordCloud
  10. import jieba as jb
  11. import re
  12. from collections import Counter
  13. result_save_file = c.outputs_logs_path + 'wzly.csv'
  14. # Ajax加载url
  15. ajax_url = "http://www.lovewzly.com/api/user/pc/list/search?"
  16. # 模拟请求头
  17. ajax_headers = {
  18. 'Accept': 'application/json, text/javascript, */*; q=0.01',
  19. 'Accept-Encoding': 'gzip, deflate, br',
  20. 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  21. 'Connection': 'keep-alive',
  22. 'Host': 'www.lovewzly.com',
  23. 'Referer': 'http://www.lovewzly.com/jiaoyou.html',
  24. 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 '
  25. 'Safari/537.36',
  26. 'X-Requested-With': 'XMLHttpRequest',
  27. }
  28. # post请求参数
  29. form_data = {'gender': '2', 'marry': '1', 'page': '1'}
  30. # csv表头
  31. csv_headers = [
  32. '昵称', '用户id', '头像', '身高', '学历', '省份',
  33. '城市', '出生年份', '性别', '交友宣言'
  34. ]
  35. height_interval = ['140', '150', '160', '170', '180'] # 身高范围
  36. edu_interval = ['本科', '大专', '高中', '中专', '初中', '硕士', '博士', '院士'] # 学历范围
  37. age_interval = [
  38. ('18-30', 8000), ('26-30', 8000), ('31-40', 8000),
  39. ('41-50', 8000), ('50以上', 8000),
  40. ] # 学历范围
  41. word_pattern = re.compile('[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?“”、~@#¥%……&*()(\d+)]+')
  42. # 获取每页交友信息
  43. def fetch_data(page):
  44. while True:
  45. try:
  46. form_data['page'] = page
  47. print("抓取第:" + str(page) + "页!")
  48. resp = rq.get(url=ajax_url, params=form_data, headers=ajax_headers)
  49. if resp.status_code == 200:
  50. data_json = resp.json()['data']['list']
  51. if len(data_json) > 0:
  52. data_list = []
  53. for data in data_json:
  54. data_list.append((
  55. data['username'], data['userid'], data['avatar'],
  56. data['height'], data['education'], data['province'],
  57. data['city'], data['birthdayyear'], data['gender'], data['monolog']))
  58. result = pd.DataFrame(data_list)
  59. if page == 1:
  60. result.to_csv(result_save_file, header=csv_headers, index=False, mode='a+')
  61. else:
  62. result.to_csv(result_save_file, header=False, index=False, mode='a+')
  63. return None
  64. except Exception as e:
  65. print(e)
  66. # 分析身高
  67. def analysis_height(data):
  68. height_data = data['身高']
  69. height = (height_data.loc[(height_data > 140) & (height_data < 200)]).value_counts().sort_index()
  70. height_count = [0, 0, 0, 0, 0]
  71. for h in range(0, len(height)):
  72. if 140 <= height.index[h] < 150:
  73. height_count[0] += height.values[h]
  74. elif 150 <= height.index[h] < 160:
  75. height_count[1] += height.values[h]
  76. elif 160 <= height.index[h] < 170:
  77. height_count[2] += height.values[h]
  78. elif 170 <= height.index[h] < 180:
  79. height_count[3] += height.values[h]
  80. elif 180 <= height.index[h] < 190:
  81. height_count[4] += height.values[h]
  82. return height_count
  83. # 分析学历
  84. def analysis_edu(data):
  85. return data['学历'].value_counts()
  86. # 分析年龄
  87. def analysis_age(data):
  88. age_data = data['出生年份']
  89. age = (age_data.loc[(age_data >= 1956) & (age_data <= 2000)]).value_counts().sort_index()
  90. age_count = [0, 0, 0, 0, 0]
  91. for h in range(0, len(age)):
  92. if 1993 <= age.index[h] <= 2000:
  93. age_count[0] += age.values[h]
  94. elif 1988 <= age.index[h] <= 1992:
  95. age_count[1] += age.values[h]
  96. elif 1978 <= age.index[h] <= 1987:
  97. age_count[2] += age.values[h]
  98. elif 1968 <= age.index[h] <= 1977:
  99. age_count[3] += age.values[h]
  100. elif age.index[h] < 1968:
  101. age_count[4] += age.values[h]
  102. return age_count
  103. # 分析城市分布
  104. def analysis_city(data):
  105. city_data = data['城市'].value_counts()
  106. city_list = []
  107. for city in range(0, len(city_data)):
  108. if city_data.values[city] > 10:
  109. city_list.append((city_data.index[city], city_data.values[city]))
  110. return city_list
  111. # 词频分布
  112. def analysis_word(data):
  113. word_data = data['交友宣言'].value_counts()
  114. word_list = []
  115. for word in range(0, len(word_data)):
  116. if word_data.values[word] == 1:
  117. word_list.append(word_data.index[word])
  118. return word_list
  119. # 绘制身高分布柱状图
  120. def draw_height_bar(data):
  121. bar = Bar("妹子身高分布柱状图")
  122. bar.add("妹子身高", height_interval, data, bar_category_gap=0, is_random=True, )
  123. return bar
  124. # 绘制身高分布饼图
  125. def draw_height_pie(data):
  126. pie = Pie("妹子身高分布饼图-圆环图", title_pos='center')
  127. pie.add("", height_interval, data, radius=[40, 75], label_text_color=None,
  128. is_label_show=True, legend_orient='vertical', is_random=True,
  129. legend_pos='left')
  130. return pie
  131. # 学历漏斗图
  132. def draw_edu_funnel(data):
  133. funnel = Funnel("妹子学历分布漏斗图")
  134. funnel.add("学历", edu_interval, data, is_label_show=True,
  135. label_pos="inside", label_text_color="#fff", title_top=50)
  136. return funnel
  137. # 年龄雷达图
  138. def draw_age_radar(data):
  139. radar = Radar("妹子年龄分布雷达图")
  140. radar.config(age_interval)
  141. radar.add("年龄段", data, is_splitline=True, is_axisline_show=True)
  142. return radar
  143. # 城市分布地图
  144. def draw_city_geo(data):
  145. geo = Geo("全国妹子分布城市", "data about beauty", title_color="#fff",
  146. title_pos="center", width=1200,
  147. height=600, background_color='#404a59')
  148. attr, value = geo.cast(data)
  149. geo.add("", attr, value, visual_range=[10, 2500], visual_text_color="#fff",
  150. symbol_size=15, is_visualmap=True)
  151. return geo
  152. # 交友宣言词云
  153. def draw_word_wc(name, count):
  154. wc = WordCloud(width=1300, height=620)
  155. wc.add("", name, count, word_size_range=[20, 100], shape='diamond')
  156. wc.render()
  157. if __name__ == '__main__':
  158. if not t.is_dir_existed(result_save_file, mkdir=False):
  159. for i in range(1, 777):
  160. time.sleep(random.randint(2, 10))
  161. fetch_data(i)
  162. else:
  163. raw_data = pd.read_csv(result_save_file)
  164. word_result = word_pattern.sub("", ''.join(analysis_word(raw_data)))
  165. words = [word for word in jb.cut(word_result, cut_all=False) if len(word) >= 3]
  166. exclude_words = [
  167. '一辈子', '不相离', '另一半', '业余时间', '性格特点', '茫茫人海', '男朋友', '找对象',
  168. '谈恋爱', '有时候', '女孩子', '哈哈哈', '加微信', '兴趣爱好',
  169. '是因为', '不良嗜好', '男孩子', '为什么', '没关系', '不介意',
  170. '没什么', '交朋友', '大大咧咧', '大富大贵', '联系方式', '打招呼',
  171. '有意者', '晚一点', '哈哈哈', '以上学历', '是不是', '给我发',
  172. '不怎么', '第一次', '越来越', '遇一人', '择一人', '无数次',
  173. '符合条件', '什么样', '全世界', '比较简单', '浪费时间', '不知不觉',
  174. '有没有', '寻寻觅觅', '自我介绍', '请勿打扰', '差不多', '不在乎', '看起来',
  175. '一点点', '陪你到', '这么久', '看清楚', '身高体重', '比较慢', '比较忙',
  176. '多一点', '小女生', '土生土长', '发消息', '最合适'
  177. ]
  178. for i in range(0, len(words)):
  179. if words[i] in exclude_words:
  180. words[i] = None
  181. filter_list = list(filter(lambda t: t is not None, words))
  182. data = r' '.join(filter_list)
  183. c = Counter(filter_list)
  184. word_name = [] # 词
  185. word_count = [] # 词频
  186. for word_freq in c.most_common(100):
  187. word, freq = word_freq
  188. word_name.append(word)
  189. word_count.append(freq)
  190. draw_word_wc(word_name, word_count)

来啊,Py交易啊

想加群一起学习Py的可以加下,智障机器人小Pig,验证信息里包含:
PythonpythonpyPy加群交易屁眼 中的一个关键词即可通过;

验证通过后回复 加群 即可获得加群链接(不要把机器人玩坏了!!!)~~~
欢迎各种像我一样的Py初学者,Py大神加入,一起愉快地交流学♂习,van♂转py。


添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注