*本文数据从猿辅导爬取,爬取工具为BeautifulSoup+jupyter notebook,共爬取课程条数1615个。(截至2018.10.18)

前言

本文以猿辅导为案例进行数据分析的第一篇文章,主要介绍数据分析的目标以及数据爬取的过程。希望通过本文和大家分享数据分析的一些方法,欢迎和我沟通交流。

还是先上图:

可以看到,数据分析主要分为四个步骤:明确目标、获取数据、数据处理以及数据展示。根据不同的场景,有些时候还可能会需要构建模型,或者有些人还会把数据处理分成观察数据和数据清洗。这里不多讨论。

概述

本文将从以上几个部分整理本次数据分析的过程。

涉及知识点:结构化思维、描述性分析、相关性分析、python爬虫、数据清洗、mysql、数据可视化等。

第一部分:明确目标

明确目标是第一步也是最关键的一步,要做到“如何将一个命题转化拆分为一个可用数据分析的问题”。首先我们来问三个问题吧:

问1:为什么要分析一家教育行业的公司,能解决什么问题?

答:通过对教育行业中一家企业的分析,可以对行业现状有一定的了解。同时对当前该公司课程销售和教师队伍的分析,可以加强对教育行业的理解以及对在线教育发展的理解。

问2:要解决这些问题能否借助数据分析?

答:数据分析是一个很好的方法,可以对“猿辅导的课程情况”进行拆解:课程、老师、报名情况、价格、年级等等。当然更深层的分析还需要行业经验的支持。

问3:为什么选择“猿辅导”,从哪些方面考虑?

答:我是从一下几个方面考虑的:1、课程重点突出相对于沪江网等课程繁多的网站,猿辅导主要面向k12人群,定位比较清晰。

2、成立时间猿辅导成立于2012年,目前已融资到E轮。属于独角兽企业,有一定示范意义。

3、数据爬取方便市面上部分教育行业的网站课程内容少,而猿辅导的网站内容比较清晰(如图):

可见,猿辅导的网站结构化程度较好,数据比较容易爬取。

明确目标之后,还需要做的一件事情就是通过描述性分析和相关性分析建立起对获取数据的初步思考:

第二部分:数据获取

通过第一部分的整理我们已经有一定的对于获取哪些数据的概念了,下面就要具体来看一下了:

一、观察网页

正如前文所述,我们可以爬取每个课程的名称、年级、老师、报名人数、价格等信息。不过需要注意以下几点:

1、课程的分类依靠的是网址的不同,且每个年级下会有系统班、专题班等不同类型。

2、对于系统班,往往需要下钻一层获取该系统班下的每个课程信息

3、每个课程页面有细微的不同,在爬取时也要注意

二、爬虫层级结构

看一下网站的结构可能就更清晰了:

三、爬虫思路

根据上面的网站结构可以知道:1、课程有三种类型,其中系统课多一层,因此系统课和专题/讲座的爬取可以分开;

2、年级学科是递进关系,可以使用for循环获取;

3、课程详情页面包含课程信息和教师信息,由于一个课程有可能有不止一位老师,可能导致主键的混乱,因此可以考虑分成课程表和教师表。

因此,最终我的爬虫代码分为三部分:

1、存放从首页获取的所有课程的课程id以及年级、学科等信息的课程表

2、从每个课程页面获取的课程详细信息如课程价格、报名人数等

3、从每个课程页面获取的教师详细信息如教师id、名字等

四、爬虫代码

说了那么多,具体的代码是什么样的呢?为了节省时间,我在关键的代码上面添加了备注。首先简单介绍一下我本次使用的爬虫方法:BeautifulSoup方法。

可以看出,在操作上只需要对不同类型的元素采用不同的标志即可爬取,方法简单容易上手。同时支持for循环,之后案例代码中也会提到。

再简单介绍一下如何观察网站:

如图所示,在Chrome浏览器中点“检查”后,可以得到类似上图的前端代码,通过观察元素、确定元素位置、确定元素路径可以定位到我们需要爬取到元素。

下面我们就重点分析一下爬虫的代码吧。根据上面的计划,爬虫代码也分为三部分:

1、爬取所有课程的概览信息

字段包括:studyphase(学段:小学、初中、高中)、grade(年级:1-12)、channelid(课程类型:语文、数学。。。)、groupid(系统课id)、groupname(系统课名称)、groupurl(系统课网址)、lessonid(课程id)、lessonname(课程名称)、lessonurl(课程url)。其中,lessonid为主键。

这一部分内容较多,因此在实际操作中我将爬虫程序分成几个部分编写:

1.1 首先是获取首页上所有可能的URL组合:

通过观察网站我们可以知道,猿辅导的首页课程页可以分成“小学、初中、高中”、“一年级到高三”、“语文、数学到编程”三个部分。因此可以用下面代码获取所有URL组合:

1.2 获取首页下系统课的group名、groupid、groupurl:

因为上文提到过,系统课和专题/讲座课的层级不同,因此需要分开处理。

1.3 对每个groupurl下的页面提取lessonid、lesson名、lessonurl:

1.4 对专题/讲座类课程做类似的操作

注意要判断是否为讲座类(或者专题课)。

2、爬取每个课程页面的课程详细信息

字段包括:lessen_id(课程id)、price(课程价格)、signup_number(报名人数)。其中,lesson_id为主键。

由于上面一部分已经将课程名称取出,这一部分只需要根据课程URL获取课程价格和报名人数即可:

但是由于猿辅导的课程页面有不同情况,比如:

因此在实际爬取时要做一个if判断:

3、爬取每个课程页面的教师详细信息

字段包括:lessen_id(课程id)、teacher_id(课程价格)、teacher_name(老师名字)。其中,teacher_id为主键。

同样的道理,我们先对某一页面的教师情况做爬取测试:

五、爬取结果

讲上述程序重新组织一下就可以得到我们的最终爬虫代码了:

1、首先是爬取系统课相关的信息:

#导入模块

import numpy as np

import pandas as pd

import requests

from bs4 import BeautifulSoup

from collections import OrderedDict

#定义主域名

domain='https://www.yuanfudao.com'

#定义主info表

info = {}

info['grade'] = []

info['channelid'] = []

info['lessonid'] = []

info['lessonurl'] = []

info['lessonname'] = []

#定义主页面筛选表

gradeList = range(1,13)

urlList = {}

urlList[1] = [3]

urlList[2] = [3]

urlList[3] = [3]

urlList[4] = [3,201]

urlList[5] = [3,201]

urlList[6] = [3,201]

urlList[7] = [1,2,3,7,8]

urlList[8] = [1,2,3,4,5,7,8]

urlList[9] = [1,2,3,4,5,7,8,14]

urlList[10] = [1,2,3,4,5,6,7,8,9]

urlList[11] = [1,2,3,4,5,6,7,8,9]

urlList[12] = [1,2,3,4,5,6,7,8,9]

#获取每个主页面系统课的info:

for grade in gradeList:

for channelid in url_list['channelid']:

main_url='https://www.yuanfudao.com/?grade=%i&channelId\

=%i&count=80'%(grade, channelid)

res1 = requests.get(main_url)

soup1 = BeautifulSoup(res1.text,'html.parser')

#循环取出group相关的信息

for Class in soup1.select('.group h3'):

groupurl = domain + Class.select('a')[0]['href']

res2 = requests.get(groupurl)

soup2 = BeautifulSoup(res2.text, 'html.parser')

#循环取出每个groupurl,即课程下面的课程信息

for classlist in soup2.select('li h3'):

info['lessonid'].append(classlist.select('a')[0]['href'][9:16])

info['lessonurl'].append(domain + classlist.select('a')[0]['href'])

info['lessonname'].append(classlist.select ('a span')[0].text)

info['grade'].append(grade)

info['channelid'].append(channelid)

#利用有序字典导入DataFrame

infoOrderDict=OrderedDict(info)

infoDf=pd.DataFrame(infoOrderDict)

infoDf.head()

2、将专题和讲座以及无groupid的系统课附加到系统课表格中,组成all_lesson表

#获取每个主页面专题/讲座/无groupid的系统班的info:

for grade in gradeList:

for channelid in url_list['channelid']:

main_url='https://www.yuanfudao.com/?grade=%i&channelId\

=%i&count=80'%(grade, channelid)

res1 = requests.get(main_url)

soup1=BeautifulSoup(res1.text,'html.parser')

#循环取数据

for Class in soup1.select('.lesson-box'):

#判断是否为讲座类

if (Class.select('h2')[0].text == '讲座'):

for seminar in Class.select('h3'):

info['lessonname'].append(seminar.select('span')[0].text)

info['lessonurl'].append(domain + seminar.select('a')[0]['href'])

info['lessonid'].append(seminar.select('a')[0]['href'][9:16])

info['grade'].append(grade)

info['channelid'].append(channelid)

#判断是否为专题类

elif (Class.select('h2')[0].text == '专题课'):

for subject in Class.select('h3'):

info['lessonname'].append(subject.select('span')[0].text)

info['lessonurl'].append(domain + subject.select('a')[0]['href'])

info['lessonid'].append(subject.select('a')[0]['href'][9:16])

info['grade'].append(grade)

info['channelid'].append(channelid)

elif (Class.select('h2')[0].text == '系统班'):

for subject in Class.select('h3'):

info['lessonname'].append(subject.select('span')[0].text)

info['lessonurl'].append(domain + subject.select('a')[0]['href'])

info['lessonid'].append(subject.select('a')[0]['href'][9:16])

info['grade'].append(grade)

info['channelid'].append(channelid)

#利用有序字典导入DataFrame

infoOrderDict=OrderedDict(info)

infoDf=pd.DataFrame(infoOrderDict)

infoDf.head()

#导出数据至xls

infoDf.to_excel('all_lesson.xls')

3、爬取课程表

#定义课程表

info_class = {}

info_class['lesson_id'] = []

info_class['price'] = []

info_class['signup_number'] = []

#爬取所有课的课程表

for url in info['lessonurl']:

res = requests.get(url)

soup = BeautifulSoup(res.text, 'html.parser')

#对课程里的“已报满”课程进行单独处理

if (soup.select('.price em')[0].text == '已报满'):

info_class['lesson_id'].append(url[-12:-5])

info_class['price'].append(soup.select('.price')[0].text[: soup.select('.price')[0].text.index('已')])

info_class['signup_number'].append(soup.select ('.common-num')[0].text)

else:

info_class['lesson_id'].append(url[-12:-5])

info_class['price'].append(soup.select ('.price em')[0].text)

info_class['signup_number'].append(soup.select ('.common-num')[0].text)

#利用有序字典导入DataFrame

infoOrderDict=OrderedDict(info_class)

infoclassDf=pd.DataFrame(infoOrderDict)

infoclassDf.head()

#导出课程表

infoclassDf.to_excel('lesson_detail.xls')

4、爬取教师表

#定义教师表

info_teacher = {}

info_teacher['lesson_id'] = []

info_teacher['teacher_id'] = []

info_teacher['teacher_name'] = []

#爬取所有课程的教师表

for url in info['lessonurl']:

res = requests.get(url)

soup = BeautifulSoup(res.text, 'html.parser')

for teacher in soup.select('.horizontal li'):

info_teacher['teacher_name'].append(teacher.select('a')[0].text)

begin = teacher.select ('a')[0]['href'].index('/',2)

end = teacher.select ('a')[0]['href'].index('/',12)

info_teacher['teacher_id'].append(teacher.select ('a')[0]['href'][begin+1:end])

info_teacher['lesson_id'].append(url[-12:-5])

#利用有序字典导入DataFrame

infoOrderDict=OrderedDict(info_teacher)

infoteacherDf=pd.DataFrame(infoOrderDict)

infoteacherDf.head()

#导出教师表

infoteacherDf.to_excel('teacher_detail.xls')

5、爬取结果如下:

all_lesson表(清洗前),共1615条记录。

lesson_detail表(清洗前),共1615条记录。

teacher_detail表(清洗前),共1915条记录(考虑到一门课有多名老师的情况)。

小结

本篇文章主要讨论了对猿辅导进行数据分析的目标和数据获取的方法。在确定目标时利用描述性分析和相关性分析确定应当获取的数据,获取数据则利用结构化思维对网站的数据结构进行了整理,并根据整理情况设计和实现了python爬虫。

特别鸣谢:wnapple:如何用数据分析方法剖析“猿辅导”K12课程​zhuanlan.zhihu.com

猿辅导python大纲_解读独角兽企业“猿辅导”(一)相关推荐

  1. 猿辅导python助教_应届生在猿辅导做辅导老师(类似于助教)是怎样的体验?

    长期更新哦,后面有入职后的内容------------------------------------------- 普通二本应届毕业生,猿编程班主任,马上入职. 说一下本人情况,考研没过复试线,计算 ...

  2. 小猿圈python金角大王_小猿圈python学习-基本数据类型

    小猿圈python学习-基本数据类型 2019-04-24 11:16:14 1点赞 6收藏 0评论 什么是数据类型? 我们人类可以很容易的分清数字与字符的区别,但是计算机并不能呀,计算机虽然很强大, ...

  3. 小猿圈python视频_小猿圈分享学习Python的最佳方式

    原标题:小猿圈分享学习Python的最佳方式 python现在是世界上功能最多的编程语言之一,可以是用Python编辑应用程序,游戏.算法程序.还可以编程一个机器人,学习Python可以担任软件工程师 ...

  4. 猿辅导python面试_猿辅导西安少儿编程班主任面试:为什么选择猿辅导 猿辅导是一个 - 职朋职业圈...

    为了帮助职业圈网友能够及时了解猿辅导西安的面试流程以及面试过程所涉及的面试问题,职业圈小编把刚获得的猿辅导西安面试经验马上编辑好,快速提供给大家,以便能够尽快帮助到有需要的人.这次面试总共花了1天.面 ...

  5. 猿辅导python面试_猿辅导面试经历—个人感受

    今天参加了猿辅导的二面,无数槽点,不知道是不是很多公司都是这样,但是我还是忍不住要逼逼叨. 6月10号,我向猿辅导投了简历,想做招聘邀约专员这个岗位,然后hr加了我的微信,要了一份简历之后通知我,12 ...

  6. 猿编程python怎么样_猿编程怎么练习编程 让你提前熟悉代码

    猿编程作为一款专业的少儿编程学习软件,它能够正确引导想要学习编程的孩子,帮助学生更加有效的学习编程思维,为他的学习之路打下坚实的基础,很多用户在开始操作时不知道如何练习编程,想知道的赶快来看看下面的教 ...

  7. 猿编程python代码_程序猿编程课堂 Python学习之入门篇3:简单的数据类型

    1. 什么是数据类型? 我们知道编程就是编写程序解决某个问题,而任何能使用编程来解决的问题都是能够提取或者转换出相应的数据,只是数据的表达形式是不一样的,而这表达形式就是数据类型. 比如,数学中的数字 ...

  8. 小猿圈python视频_小猿圈python学习-格式化打印

    现有一练习需求,问用户的姓名.年龄.工作.爱好 ,然后打印成以下格式 ------------ info of Alex Li -----------Name : Alex Li Age : 22 j ...

  9. 程序员女朋友礼物python代码_一位程序猿送给女朋友的礼物

    背景 一个月前发现了V2EX这个网站,用创始人Livid的话来说,『这是一个主要关于做事儿的地方』.确实如此,我在这里收获了很多想法和灵感. 本文所记的,也是得益于某天的对某个主题的浏览.帖子中,大家 ...

  10. 小猿圈python之python期末考试测试题(二)_小猿圈Python开发面试题(二)

    原标题:小猿圈Python开发面试题(二) 小猿圈Python老师继上一次python面试题一,接着更新python面试题二,同学们测试一做的怎么样呢?有没有把握呢,想要看答案的同学们,可以在小猿圈上 ...

最新文章

  1. Android中实现双击屏幕跳转
  2. 最强人脸检测来了 yolov5 face
  3. 对MySQL 进行深入学习是非常必要的
  4. 78.Subsets
  5. 女孩去互联网大厂工作怎么样?
  6. Oracle iops升高查看,一则简单的磁盘的iops测试
  7. Python六大框架对比
  8. 20161212 输出1到n之间所有的奇(单)数(n30000) 。
  9. Linux基础命令---间歇性执行程序watch
  10. 常用的3款光学仿真软件分析---来源网络
  11. 【lua/aviutl】小型倒计时
  12. Q4营收同比增长34.7%,Saleforces股价为何总停滞不前?
  13. VC|MFC内存不能为read,内存不能为 written 分析
  14. DES的加密解密在ECB上的使用(C语言实现)——大三密码学实验
  15. chrome java过期_解决ubuntu的chrome浏览器的flash过期问题
  16. js:根据闰年的判断条件,利用if循环判断闰年
  17. 点击按钮页面滚动到对应位置(锚点)
  18. 使用 Stunnel 加密
  19. 问题解决:Word在插入图片后保存变模糊
  20. 学系统集成项目管理工程师(中项)系列17b_范围管理(下)

热门文章

  1. vscode环境搭建:配置prettier
  2. 毕业两年做到测试经理的经历总结【转】
  3. 网易云课堂-微专业Java
  4. 定制Android模拟器skin
  5. 网段划分 特殊网段(localhost0.0.0.01.1.1.1127.0.0.1)
  6. 中国出海50强,华为超越阿里得亚军,第一名居然是它?
  7. python文件加密
  8. Android 12 WiFi 架构
  9. 多卡聚合设备基于融合系统指挥平台的解决方案
  10. 从图灵奖小插曲看50年来什么样的人工智能最受追捧