本节我们以网址https://daxue.eol.cn/mingdan.shtml为初始链接,爬取教育部公布的正规高校名单。

  思路:

    1、首先以上面的地址开始链接,抓取到下面省份对应的链接。

    2、在解析具体的省份源代码,获取数据。虽然山东和河南的网页结构和其他不同,我们也不做特殊处理,直接不做抓取即可;将抓取到的数据存储到mongodb数据库

    3、对高校数据做数据分析及数据可视化。

抓取数据

1、定义数据结构

class daxueItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
province = Field() # 省份
name = Field() # 学校名称
bianhao = Field() # 学校编号
zhishujigou = Field() # 直属机构
diqu = Field() # 所属城市名称
jibei = Field() # 学校级别

2、编写爬虫

class DaxueSpider(scrapy.Spider):
name = 'daxue'
#allowed_domains = ['daxue.eol.cn']
start_urls = ['https://daxue.eol.cn/mingdan.shtml'] def parse(self, response): #初始网页的解析函数
soup = BeautifulSoup(response.text, 'lxml')
gx_url_list = soup.find_all(name='div', class_='province')
for gx_url in gx_url_list:
url = gx_url.a['href']
yield Request(url = url,callback = self.parse_daxue_list) #回调函数 def parse_daxue_list(self,response):
#response.encoding = 'utf-8' # 解决中文乱码
soup = BeautifulSoup(response.text, 'lxml') prov = soup.find_all(name='div', class_='title')[0].text.replace('正规高校名单', '') #获取省份名称 dx_list = soup.find_all(name='table', class_='table-x')
for dx_details in dx_list:
for dx_detail in dx_details.find_all(name='tr'):
if (dx_detail == dx_details.find_all(name='tr')[0] or dx_detail == dx_details.find_all(name='tr')[1]):
continue
else:
daxue = daxueItem()
daxue['province'] = prov
daxue['name'] = dx_detail.find_all(name='td')[1].text
daxue['bianhao'] = dx_detail.find_all(name='td')[2].text
daxue['zhishujigou'] = dx_detail.find_all(name='td')[3].text
daxue['diqu'] = dx_detail.find_all(name='td')[4].text
daxue['jibei'] = dx_detail.find_all(name='td')[5].text
yield daxue

3、将数据存入mongodb数据库,编写pipeline

class MongoPipeline(object):
def __init__(self,mongo_url,mongo_db,collection):
self.mongo_url = mongo_url
self.mongo_db = mongo_db
self.collection = collection @classmethod
def from_crawler(cls,crawler):
return cls(
mongo_url=crawler.settings.get('MONGO_URL'),
mongo_db = crawler.settings.get('MONGO_DB'),
collection = crawler.settings.get('COLLECTION')
) def open_spider(self,spider):
self.client = pymongo.MongoClient(self.mongo_url)
self.db = self.client[self.mongo_db] def process_item(self,item, spider):
name = self.collection
self.db[name].insert(dict(item))
return item def close_spider(self,spider):
self.client.close()

4、配置setting文件,需要配置的项:mongodb的连接信息,放开pipeline即可,没有其他复杂的配置。

5、运行项目即可获取数据;刨除山东和河南,我们共抓取数据2361条,全部高校数据均被抓取下来。

代码链接:https://gitee.com/liangxinbin/Scrpay/tree/master/scrapydaxue

分析数据

1、以饼图展示全国高校中,本科和专科的数据占比,代码

def daxue():
client = pymongo.MongoClient(host='localhost', port=27017)
db = client['test'] # 指定数据库
collection = db['daxue'] # 指定集合
daxue = collection.find()
dx_data = DataFrame(list(daxue)) # 将读取到的mongo数据转换为DataFrame数据集合
dx_data = dx_data.drop(['_id'],axis=1)
df_jibei = dx_data['jibei'] # 从数据集中取出学校级别一列 df = df_jibei.value_counts() # 统计专科很本科的数据量
labels = df.index # 显示在图形上的标签
sizes = df.values # 要在图中显示的数据 # 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False fig1, ax1 = plt.subplots()
ax1.pie(sizes, labels=labels, autopct='%1.1f%%', shadow=True, startangle=90) # 使用pie()方法绘制饼图。
ax1.axis('equal')
ax1.set(title="全国高校本科专科占比") # 设置饼图标题 plt.show()

抓取的数据中,本科1121,专科1240,由此可见,占比差异不大。

2、以条形图展示各个身份的高校数量

def daxue_shuliang():
client = pymongo.MongoClient(host='localhost', port=27017)
db = client['test'] # 指定数据库
collection = db['daxue'] # 指定集合
daxue = collection.find()
dx_data = DataFrame(list(daxue))
dx_data = dx_data.drop(['_id'], axis=1)
df = dx_data['province'] df1 = df.value_counts()
ind = np.arange(len(df1.values))
width = 0.8 fig, ax = plt.subplots()
rects1 = ax.bar(ind,df1.values, width, color='SkyBlue') # # Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('数量')
ax.set_title('全国高校分布情况')
ax.set_xlabel('省份')
ax.set_xticklabels((df1.index))
ax.legend() x = np.arange(len(df1.index))
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.yticks(np.arange(0, 180, 10)) # 设置y轴的刻度范围
plt.xticks(x, df1.index, rotation=45, fontsize=9) # 设置x轴上显示的省份个数 # 在图形上面添加数值,并设置数值的位置
# for x, y in enumerate(df1.values):
# plt.text(x, y + 100, '%s' % round(y,2), ha='left') plt.show()

可以看到,江苏省和广东省的高校数量遥遥领先,刚好,这两个省份也是全国经济最发达的两个省份(个人见解);由此可见,教育对省份经济的促进作用。

上面我们从省份的维度查看了高校的分布,现在我们从城市的角度出发,在看一下高校在各个城市的分布情况。

def daxue_shuliang_city():
client = pymongo.MongoClient(host='localhost', port=27017)
db = client['test'] # 指定数据库
collection = db['daxue'] # 指定集合
daxue = collection.find()
dx_data = DataFrame(list(daxue))
dx_data = dx_data.drop(['_id'], axis=1)
df = dx_data['diqu'] df1 = df.value_counts()
df1 = df1[df1.values >= 15] #因城市太多,我们只取了城市大学数量超过15的城市
print(df1)
ind = np.arange(len(df1.values))
width = 0.5 fig, ax = plt.subplots()
rects1 = ax.bar(ind,df1.values, width, color='SkyBlue') # # Add some text for labels, title and custom x-axis tick labels, etc. ax.set_title('全国高校分布情况')
ax.set_xlabel('城市')
ax.set_ylabel('数量')
ax.set_xticklabels((df1.index))
ax.legend() x = np.arange(len(df1.index))
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.yticks(np.arange(0, 100, 10)) # 设置y轴的刻度范围
plt.xticks(x, df1.index, rotation=45, fontsize=9) # 设置x轴上显示的省份个数 # 在图形上面添加数值,并设置数值的位置
# for x, y in enumerate(df1.values):
# plt.text(x, y + 100, '%s' % round(y,2), ha='left') plt.show()

从图中可以考到,首都北京的高校数量时最多的,排名前五的城市依次是北京,武汉,广州,重庆,和上海,这五个城市在全国都是经济非常发达的城市。因此我们大致可以得出,城市大学数量和城市经济呈正相关。

可能会有人郁闷了,上面我们以省份为维度时,高校数量最多的省份是江苏省,但是以城市为维度时,大学数量超过15的城市,属于江苏省的只有南京和苏州,且排名都不怎么靠前,那好,接下来我们以江苏省为基准,查看江苏省内高校数量的分布情况。

def daxue_shuliang_prov_jiangsu():
client = pymongo.MongoClient(host='localhost', port=27017)
db = client['test'] # 指定数据库
collection = db['daxue'] # 指定集合
daxue = collection.find()
dx_data = DataFrame(list(daxue))
dx_data = dx_data.drop(['_id'], axis=1)
dx_data = dx_data[dx_data['province'] == '江苏省']
dx_data = dx_data.sort_values('diqu')
df1 = dx_data['diqu']
df1 = df1.value_counts() ind = np.arange(len(df1.values))
width = 0.5 fig, ax = plt.subplots()
rects1 = ax.bar(ind,df1.values, width, color='SkyBlue') # # # Add some text for labels, title and custom x-axis tick labels, etc.
#
ax.set_title('江苏省高校分布情况')
ax.set_xlabel('城市')
ax.set_ylabel('数量')
ax.set_xticklabels((df1.index))
ax.legend()
#
x = np.arange(len(df1.index))
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.yticks(np.arange(0, 60, 10)) # 设置y轴的刻度范围
plt.xticks(x, df1.index, rotation=45, fontsize=9) # 设置x轴上显示的省份个数 # 在图形上面添加数值,并设置数值的位置
# for x, y in enumerate(df1.values):
# plt.text(x, y + 100, '%s' % round(y,2), ha='left') plt.show()

从图中可以看到,江苏省除了南京市和苏州市之外,其他城市大学数量分布较为均匀,基本都在10个左右;如果加上南京和苏州,计算江苏省内城市平均大学数量,应该会超过10个,城市大学数量平均10个,这在其他省份应该不太多,这也从另一方面说明了为什么江苏省内地区发展均为均衡的原因吧。

我们接着查看全国各省份有大学城市的城市大学平均个数

def daxue_shuliang_prov_mean():
client = pymongo.MongoClient(host='localhost', port=27017)
db = client['test'] # 指定数据库
collection = db['daxue'] # 指定集合
daxue = collection.find()
dx_data = DataFrame(list(daxue))
dx_data = dx_data.drop(['_id'], axis=1) dx_prov = dx_data.groupby('province') #按照省份对数据进行分组 dx_avg_list = []
for name, group in dx_prov: #遍历分组之后的数据,计算平均个数,形成省份和平均数量的字典,添加到列表中
dx_avg_dic = {}
dx_avg_dic['prov'] = name
dx_avg_dic['avg'] = (group['province'].count()/len(group.groupby('diqu')['name'].count())).round(decimals=2)
dx_avg_list.append(dx_avg_dic)
dx_df = DataFrame(list(dx_avg_list)) #以字典的列表构造df数据集
df1 = dx_df.sort_values('avg',ascending=False)
ind = np.arange(len(df1['avg']))
width = 0.5 fig, ax = plt.subplots()
rects1 = ax.bar(ind, df1['avg'], width, color='SkyBlue') # # # Add some text for labels, title and custom x-axis tick labels, etc.
#
ax.set_title('全国省份平均高校数量')
ax.set_xlabel('省份')
ax.set_ylabel('数量')
ax.set_xticklabels(df1['prov'])
ax.legend() x = np.arange(len(df1['avg']))
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.yticks(np.arange(0, 100, 10)) # 设置y轴的刻度范围
plt.xticks(x, df1.prov, rotation=45, fontsize=9) # 设置x轴上显示的省份个数 plt.show()

包含北京,上海,天津,重庆四大直辖市

刨除北京,上海,天津,重庆四大直辖市

从上面两张图可以看出,在刨除北京,上海,天津,重庆四个直辖市之后,城市平均大学数量排名第一的是 江苏省,达到了11.13个,也印证了我们上面的分析。

有趣的是,排名第二的河北省,经济却比较落后,可能是距离北京太近了吧,O(∩_∩)O哈哈~

至此,我们完成了对全国高校数据的抓取和分析,仅仅是小试牛刀,完整代码请参见: https://gitee.com/liangxinbin/Scrpay/blob/master/Vsualization.py

Scrapy实战篇(八)之爬取教育部高校名单抓取和分析的更多相关文章

  1. Heritrix源码分析(九) Heritrix的二次抓取以及如何让Heritrix抓取你不想抓取的URL

    本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/644396       本博客已迁移到本人独立博客: http://www.yun5u ...

  2. fiddler抓包工具 https抓取 ios手机端抓取

    fiddler抓包工具 https抓取 ios手机端抓取  转载链接:https://www.cnblogs.com/bais/p/9118297.html   抓取pc端https请求,ios手机端 ...

  3. Scrapy实战篇(七)之爬取爱基金网站基金业绩数据

    本篇我们以scrapy+selelum的方式来爬取爱基金网站(http://fund.10jqka.com.cn/datacenter/jz/)的基金业绩数据. 思路:我们以http://fund.1 ...

  4. Scrapy实战篇(六)之爬取360图片数据和图片

    本篇文章我们以360图片为例,介绍scrapy框架的使用以及图片数据的下载. 目标网站:http://images.so.com/z?ch=photography 思路:分析目标网站为ajax加载方式 ...

  5. Scrapy实战篇(五)之爬取历史天气数据

    本篇文章我们以抓取历史天气数据为例,简单说明数据抓取的两种方式: 1.一般简单或者较小量的数据需求,我们以requests(selenum)+beautiful的方式抓取数据 2.当我们需要的数据量较 ...

  6. Scrapy实战篇(二)之爬取链家网成交房源数据(下)

    在上一小节中,我们已经提取到了房源的具体信息,这一节中,我们主要是对提取到的数据进行后续的处理,以及进行相关的设置. 数据处理 我们这里以把数据存储到mongo数据库为例.编写pipelines.py ...

  7. Scrapy实战篇(三)之爬取豆瓣电影短评

    今天的主要内容是爬取豆瓣电影短评,看一下网友是怎么评价最近的电影的,方便我们以后的分析,以以下三部电影:二十二,战狼,三生三世十里桃花为例. 由于豆瓣短评网页比较简单,且不存在动态加载的内容,我们下面 ...

  8. Scrapy实战篇(八)之简书用户信息全站抓取

    相对于知乎而言,简书的用户信息并没有那么详细,知乎提供了包括学习,工作等在内的一系列用户信息接口,但是简书就没有那么慷慨了.但是即便如此,我们也试图抓取一些基本信息,进行简单地细分析,至少可以看一下, ...

  9. Scrapy实战篇(四)之周杰伦到底唱了啥

    从小到大,一直很喜欢听周杰伦唱的歌,可是相信很多人和我一样,并不能完全听明白歌词究竟是什么,今天我们就来研究一下周董最喜欢在歌词中用的词,这一小节的构思是这样的,我们爬取周杰伦的歌词信息,并且将其进行 ...

随机推荐

  1. 微信小程序 image属性 mode

    mode属性可以改变图片的填充容器方式

  2. flex 布局 实现电商网页菜单的多级分类展示

    用flex,实现多级菜单分类展示,这里记录一下,方便以后查阅. 效果展示如下: 跟上面floor的设计差不多,鼠标hover全部商品分类的时候,将下拉列表展示在指定区域,这个类似鼠标悬浮商品图片期待上 ...

  3. Js/如何修改easyui修饰的input的val值

    1.关于js对input值的修改介绍:一般js改变input的val值,我一直使用的方法是: $('#id').val('test');这样的方式来进行修改.但是我使 用了class="ea ...

  4. Java 8 Lambda 表达式(一)

    Java 8 新特性 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). 使用 Lambda 表 ...

  5. 微信小程序个人/企业开放服务类目一览表

    微信小程序个人/企业开放服务类目一览表   微信小程序个人开放服务类目表 服务类目 类目分类一 类目分类二 引导描述 出行与交通 代驾 / / 生活服务 家政.丽人.摄影/扩印.婚庆服务.环保回收/废 ...

  6. vue 动态循环出的多个select 不能重复选择相同的数据

    看图说话 HTML: JS:        1)  2) 3) 有更好的方法可以相互学习.

  7. 安装了低版本Jdk后eclipse无法打开的终极解决方法

    环境jdk1.7.0_17,eclipse oxygen(2017年6月发布) 因为之前安装的是jdk1.8.0_144,所以eclipse的相关配置都修改成了jdk1.8的版本,然而,近期因为某些原 ...

  8. java-多线程(上)

    ###24.01_多线程(多线程的引入)(了解) * 1.什么是线程     * 线程是程序执行的一条路径, 一个进程中可以包含多条线程     * 多线程并发执行可以提高程序的效率, 可以同时完成多 ...

  9. SG函数和SG定理

    Fibonacci again and again 利用SG函数求出每一堆的SG值,如果三个值的异或和为零 先手必败态,否则,先手必胜态. #include <bits/stdc++.h> ...

  10. ios-键盘回收

    对输入的UITextField 控件设置完代理,然后粘上两种方法,即可. #pragma mark- 键盘收回 -(void)textFieldDidEndEditing:(UITextField * ...