(3条消息) 从网上爬取全国大学学校数据2020版(最新版,包含大部分常用字段)
1. 文章说明
现在跟教育沾边的项目基本上都离不开“学校”的数据,而全国大学的数据网上版本也非常之多,下载了很多个版本,浪费了近100点C币,最终得到的数据都不尽如人意,有些只有学校数据缺少其他重要的字段,有些只有部分学校,缺少很多学校。本篇文章的目的就是为了分享我获取到的最新的全国大学学校数据,数据非常的丰富,字段多达41个,总共2934所,数据来源:中国教育在线
2. 爬取数据样例展示
为了让大家清楚的看到数据本身的样子,这里给出几个示例:
字段 | 字段值 | 字段含义 |
---|---|---|
id | 140 | 系统内部自增ID |
school_id_code | 4111010003 | 学校标识码,全国唯一 |
school_code | 10003 | 学校招生代码,全国唯一 |
name | 清华大学 | 学校名称 |
type | 5000 | 分类编码 |
type_name | 综合类 | 分类名称 |
school_type | 6000 | 类型编码 |
school_type_name | 普通本科 | 类型名称 |
school_nature | 36000 | 性质编码 |
school_nature_name | 公办 | 性质名称 |
belong | 教育部 | 隶属于 |
f985 | 1 | 是否为985学校 |
f211 | 1 | 是否未211学校 |
num_subject | 39 | 重点学科数量 |
num_master | 66 | 硕士点数量 |
num_doctor | 58 | 博士点数量 |
num_academician | 66 | 院士人数 |
num_library | 400万 | 藏书数量 |
num_lab | 61 | 重点实验室数量 |
province_id | 11 | 所属省份编码 |
province_name | 北京 | 所属省份名称 |
city_id | 1101 | 所属市编码 |
city_name | 北京市 | 所属市名称 |
county_id | 110108 | 所属区域编码 |
town_name | 海淀区 | 所属区域名称 |
create_date | 1911 | 创办年份 |
area | 5886.00 | 学校占地面积,单位:亩 |
old_name | 原名 | |
short | 北京清华,清华 | 简称 |
ruanke_rank | 1 | |
wsl_rank | 1 | |
qs_rank | 1 | |
xyh_rank | 2 | |
dual_class_name | 双一流 | |
zsb@mail.tsinghua.edu.cn | 招生办邮箱 | |
address | 北京市海淀区清华园1号 | 学校地址 |
postcode | 100084 | 邮政编码 |
site | http://www.join-tsinghua.edu.cn | 招生办网址 |
school_site | https://www.tsinghua.edu.cn/publish/thu2018/index.html | 学校官网 |
phone | 010-62782051,010-62770334 | 招生办电话 |
content | 清华大学的前身清华学堂始建于1911年,1912年更名为清华学校,略… | 学校概况 |
说明:上面有4个学校排名字段笔者暂时还没弄清楚具体是什么维度的排名,如果有知道的可以评论告知一下,不胜感激。
3. 如何爬取
现在把爬取数据的核心代码分享给大家,笔者使用的是Java程序来爬取的,建议大家如果在爬取的时候也要注意每次爬取的间隔,太小有可能会被认定为恶意请求被限制访问。
3.1 选取爬取链接
爬取地址
:https://static-data.eol.cn/www/school/1738/info.json
路径参数1738代表中国教育在线内部系统的id,仔细观察下教育在线数据可以发现,这个编码不会太大,如果不放心,可以设置大一点的数据,如3600,用浏览器打开链接
会发现请求是失败的,大家可以尝试一下3500,是有数据返回的。那么就可以通过1-3500来进行循环的爬取,每次爬取是一所学校的详情。可能有的人会说爬取
https://api.eol.cn/gkcx/api/?access_token=&admissions=¢ral=&department=&dual_class=&f211=&f985=&is_dual_class=&keyword=&page=2&province_id=&request_type=1&school_type=&signsafe=&size=20&sort=view_total&type=&uri=apigkcx/api/school/hotlists
,笔者最开始是爬取的这个地址,但后来发现,链接太复杂,并且返回的数据没有前者丰富。
3.2 爬取代码
BufferedWriter writer = new BufferedWriter(new FileWriter(new File("D:/school.txt"))); for (int i = 1; i < 3600; i++) { String url = "https://static-data.eol.cn/www/school/1738/info.json"; ResponseEntity<String> results = restTemplate.getForEntity(url, String.class); TimeUnit.SECONDS.sleep(1); String result = results.getBody(); writer.append(result).append("\n"); System.out.println(result); } writer.flush(); writer.close();
说明:我这个爬取分2步,第一步是爬取数据,将数据写入到D:/school.txt,每所学校的数据以json字符串格式写入到文件中,每所学校占一行。
3.2 写入数据库
首先,将数据从txt文件读取出来,再拼接成sql语句,重新写到sql文件中,最后通过navicat写入到数据库。这种爬取方式可以支持任何数据库,只要写一句insert的模板语句即可。
BufferedReader reader = new BufferedReader(new FileReader("D:/school.txt")); BufferedWriter writer = new BufferedWriter(new FileWriter(new File("D:/school.sql"))); String line = null; String sql="INSERT INTO `usercenter_school` (`school_id`, `data_code`, `name`, `type`, `school_type`, `school_nature`, `belong`, `f985`, `f211`, `num_subject`, `num_master`, `num_doctor`, `num_academician`, `num_library`, `num_lab`, `province_id`, `province_name`, `city_id`, `city_name`, `county_id`, `town_name`, `create_date`, `area`, `old_name`, `short`, `ruanke_rank`, `wsl_rank`, `qs_rank`, `xyh_rank`, `level_name`, `type_name`, `school_type_name`, `school_nature_name`, `dual_class_name`, `email`, `address`, `postcode`, `site`, `school_site`, `phone`, `content`) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');"; while (true) { line = reader.readLine(); if (line == null) { break; } JSONObject detail= JSONObject.parseObject(line); String s=String.format(sql, detail.getString("id"), detail.getString("data_code"), detail.getString("name"), detail.getString("type"), detail.getString("school_type"), detail.getString("school_nature"), detail.getString("belong"), detail.getString("f985"), detail.getString("f211"), detail.getString("num_subject"), detail.getString("num_master"), detail.getString("num_doctor"), detail.getString("num_academician"), detail.getString("num_library"), detail.getString("num_lab"), detail.getString("province_id"), detail.getString("province_name"), detail.getString("city_id"), detail.getString("city_name"), detail.getString("county_id"), detail.getString("town_name"), detail.getString("create_date"), detail.getString("area"), detail.getString("old_name"), detail.getString("short"), detail.getString("ruanke_rank"), detail.getString("wsl_rank"), detail.getString("qs_rank"), detail.getString("xyh_rank"), detail.getString("level_name"), detail.getString("type_name"), detail.getString("school_type_name"), detail.getString("school_nature_name"), detail.getString("dual_class_name"), detail.getString("email"), detail.getString("address"), detail.getString("postcode"), detail.getString("site"), detail.getString("school_site"), detail.getString("phone"), detail.getString("content") ); writer.append(s).append("\n"); System.out.println(s); } reader.close(); writer.flush(); writer.close();
经过上面的步骤,就已经生成了sql文件,到此也就水到渠成了。
细心的读者可能已经发现,生成的sql记录,少了学校标识码school_id_code和学校代码school_code字段。从中国教育在线网上爬取的数据中不包含这两个字段,但笔者提供的数据中是包含这两个字段的,笔者是从某某网站上下载的数据,经过表连接手段插入的学校标识码,但还是会有少部分学校不能关联,因此又从某网站手工的查询剩余的学校,将标识码补齐(真的是手工,耗费2小时)。最后是校代码,校代码了解的读者就会知道,校代码是根据标识码生成的,因此有了标识码就自然有了校代码。