原文章地址:https://blog.csdn.net/memory_qianxiao/article/details/82388370
由于很多朋友需要这种数据,因为发布以来,有很多人再问我要源代码,我也给了,直到3月10多号某一天,有人告诉我,运行后没有数据,我自己也去测试一下果然没有数据,然后简单排查发现,是请求的网址变了....由于在准备蓝桥杯比赛,在做题,没有仔细排查,后来仔细排查,发现网址请求变了是一回事,重点是网站采用了ajax技术,数据不在网页源代码里面,是通过ajax局部请求数据,然后加载到网页中的...所以需要去请求ajax地址,拿到数据解析。。。接下来解释重构过程,虽然解析麻烦了,但是代码量减少了,只需要200行的样子...就可以了。
提示:由于网站每隔大概三个月的样子,就会维护更新,导致代码不能使用,而我还是应届毕业生,弄论文,做毕设,找工作,以后没有特情况,我是不会维护这个代码了,如果有需要的人,我这两篇博客中里面写了分析思路和过程,以及代码和注释,可以给你们参考学习~希望大家主动自己破解,提高思维和分析能力~而我本人时间和精力也有限,望体谅~ time:2020/5/20
开发环境:python 3.6 +pycahrm
第三放库:request(网页级请求库),xlwt(excel操作库),json(python和json互转的库)
由于在原文章详细写过爬取过程,这次就不写这么详细了,想详细学习,了解,请参考原文章:https://blog.csdn.net/memory_qianxiao/article/details/82388370(虽然代码没法用了,但是思路重要呀,毕竟学习思想最重要,代码逻辑是你自己思想的体现)
提示:由于网站再次更新,不过这次更新就是换汤不换药,把请求的API换了,导致代码不能使用,只需要在原请求的ajax请求地址更改成如下就好:(感谢江苏地区的路祎唯同学指出)。最终代码完整在更新一次(4月30日 7月19更新能用的代码请点击下面GIthub:)。
同时该网站增加一点反爬措施, 我们需要把请求伪装成浏览器,所以还需要在请求的时候还要增加一个请求头,设置如下:
更新时间:2019年7月19 最新可用源码点击GitHub传送门:点我进入,GitHub传送门~
老规矩,镇楼图如下(爬取的一部分):一个excel4页,理科专业线,文科专业线,理科省控线,文科省控线
一:下是分析过程:由于网站更新变化后,数据在ajax中,所以对网址请求没用了,下面给出逻辑分析:
先按F12进入开发者模式,点击network,按住XHR,在随便点个大学进去,发现每点年份或者文理科,都会出现一个api,数据都返回在api里面,所接下来分析的关键是如何分析拿到api里面的数据。
二:分析api里面的headers分析如下:
请求url是:https://gkcx.eol.cn/api
请求方法是:POST!POST!POST!很重要,不是get方法。
请求参数:post请求参数是
而我们拿数据最重要的就是这里的请求参数:
local_province_id:是省份的代号,网站更新后,都是自动定位的,会选择当前ip的定位位置,也就是定位后的代号自动填上,所以如果需要爬取其他地方的数据,可以更改请求参数,自己省份代号,需要自己去试。
local_type:是文理科代号,1是理科,2是文科,可以自己去测试,每点击一次就会有一个新的api去查看就行了。
school_id:是学校的id,所以需要查哪个学校就更改id就行
uri:"hxsjkqt/api/gk/score/province"是省控线 hxsjkqt/api/gk/score/special是专业线
year:是爬取的年份 也就是需要爬取哪一年就给year哪年参数
所以请求的是时候用request.post()方法,并且把上面的参数传进去。
这里附上全国34省的名称以及对应的代码:
北京:11
天津:12
河北:13
山西:14
内蒙古:15
辽宁:21
吉林:22
黑龙江:23
上海:31
江苏:32
浙江:33
安徽:34
福建:35
江西:36
山东:37
河南:41
湖北:42
湖南:43
广东:44
广西:45
海南:46
重庆:50
四川:51
贵州:52
云南:53
西藏:54
陕西:61
甘肃:62
青海:63
宁夏:64
新疆:65
台湾:71
香港:81
澳门:82
三:由于不知到学校的id还是采取暴力的方式,从30开始到 3000暴力循环学校id,然后拼接网址,请求。
还是定义三个函数,main()函数入口,get_html()请求信息,get_info()得到学校信息,并且保存到excel里面。代码里面都有注释,重复的就没有注释,是一样的。不过可能有以下报错,所以还是采用断点续爬,也就是每次都会打印网址,后面有个学校id,如果哪次报错继续更改否for循环起点,如果有大神知道这种报错解决方法,欢迎留言指导,感激不尽.
全代码如下:excel保存路径换成自己的文件路径就ok了。
# -*- coding: utf-8 -*-
# @Filename: 全国高校录取数据重构.py
# @Time : 2019/3/22 16:49
# @Author : LYT
"""
"""
import requests,re,xlwt,json
from bs4 import BeautifulSoup
def Get_html(url,data):
try:
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3676.400 QQBrowser/10.4.34"
}#更新后添加的请求头,伪装成浏览器
r=requests.post(url,params=data,headers=headers)#带请求参数params,同时把headers传进去
r.encoding=r.apparent_encoding
print("请求服务成功!")
print(r.text)
return r.text
except:
print("请求失败")
def Get_info(url,id):
url_api = "https://gkcx.eol.cn/gkcx/api"#更新后请求ajax api
#请求参数信息
data = {
'local_province_id': '51', # 省份 51为四川 默认是自动定位的地方
'local_type_id': 1, # 理科为1,文科为2,
'school_id': '30', # 学校id
'uri': "hxsjkqt/api/gk/score/province", # 专业线special 省线province
'year': 2018 # 年份 网站更新后 省录取线2014 -2018 专业录取线2014-2017
}
info_like=[]#存理科省线信息列表
info_wenke=[]#存文科省线信息列表
special_like=[]#存理科专业信息列表
special_wenke=[]#存文科专信息业表
name=""
for i in range(2014,2019):#请求2014-2018的省控线信息
data['year']=i #更换参数年份
data['school_id']=id#更换学校id
data['local_type_id']=1#更换为理科
infoes=json.loads(Get_html(url_api,data))
# print(info)
# print(info['data']['item'])
#存理科省录取线
if len(infoes['data']['item'])==0:
l=[]
l.append(name) # 没有数据就填充--
l.append(str(i))
l.append('--')
l.append('--')
l.append('--')
l.append('--')
l.append('--')
info_like.append(l)
for j in range(len(infoes['data']['item'])): # 可能有多个省录取线,比如提前批,一批,二批等
l = []
info = infoes['data']['item'][j]
name = info['name']
l.append(info['name'])#存学校名字
l.append(info['year'])#存年份
l.append(info['local_type_name']) # 科类
l.append(info['max'])#最大录取分数
l.append(info['average'])#平均分
l.append(info['min']) #最低分
l.append(info['proscore']) #省控线
l.append(info['local_batch_name'])#批次
info_like.append(l)
#存文科录取线
data['local_type_id']=2#更换为文科
infoes = json.loads(Get_html(url_api,data))
if len(infoes['data']['item'])==0:
l=[]
l.append(name) # 没有数据就填充--
l.append(str(i))
l.append('--')
l.append('--')
l.append('--')
l.append('--')
l.append('--')
info_wenke.append(l)
for j in range(len(infoes['data']['item'])):#可能有多个省录取线,比如提前批,一批,二批等
l=[]
info = infoes['data']['item'][j]
name=info['name']
l.append(info['name']) # 存学校名字
l.append(info['year']) # 存年份
l.append(info['local_type_name'])#科类
l.append(info['max']) #最大录取分数
l.append(info['average']) #平均分
l.append(info['min']) #最低分
l.append(info['proscore']) #省控线
l.append(info['local_batch_name'])#批次
info_wenke.append(l)
print(info_like)
print(info_wenke)
for i in range(2014,2018):#请求2014-2017的专业录取信息
# 请求参数信息
data['year'] = i # 更换参数年份
data['school_id'] = id # 更换学校id
data['local_type_id'] = 1 # 更换为理科
data['uri']='/'.join(data['uri'].split('/')[0:-1])+"/special"#更换为请求参数为专业录取线的参数网址
infoes = json.loads(Get_html(url_api,data))
#存理科专业信息
if len(infoes['data']['item']) == 0:
l = []
l.append(name)
l.append(str(i))
l.append('--')
l.append('--')
l.append('--')
l.append('--')
l.append('--')
l.append('--')
info_like.append(l)
for j in range(len(infoes['data']['item'])):
l=[]
info=infoes['data']['item'][j]
name=info['name']
l.append(info['name'])#学校名字
l.append(info['year'])#年份
l.append(info['spname'])#专业名称
l.append(info['local_type_name'])#科类
l.append(info['average'])#专业平均分
l.append(info['max'])#最高分
l.append(info['min'])#最低分
l.append(info['local_batch_name'])#录取批次
special_like.append(l)
#存文科专业录取信息
data['local_type_id']=2#更换为文科
infoes = json.loads(Get_html(url_api, data))
if len(infoes['data']['item']) == 0:
l = []
l.append(name) #没有信息就填充--符号
l.append(str(i))
l.append('--')
l.append('--')
l.append('--')
l.append('--')
l.append('--')
l.append('--')
info_like.append(l)
for j in range(len(infoes['data']['item'])):
l=[]
info=infoes['data']['item'][j]
name=info['name']
l.append(info['name'])#学校名字
l.append(info['year'])#年份
l.append(info['spname'])#专业名称
l.append(info['local_type_name'])#科类
l.append(info['average'])#专业平均分
l.append(info['max'])#最高分
l.append(info['min'])#最低分
l.append(info['local_batch_name'])#录取批次
special_wenke.append(l)
print(special_like)
print(special_wenke)
#*******************保存数据到excel**************************
print("*************正在写入Excrl数据***************")
# 创建excel簿指定编码
file=xlwt.Workbook(encoding='utf-8')
#创建表 一个表有4个sheet
print("*************正在写入Excrl理科专业线数据***************")
table1=file.add_sheet(name+'理科专业线')
value = ['学校名称', '年份','专业名称','科类', '平均分', '最高分', '最低分', '批次']
for i in range(len(value)):
table1.write(0,i,value[i])
for i in range(len(special_like)):
for j in range(len(special_like[i])):
table1.write(i+1,j,special_like[i][j])
print("*************正在写入Excrl文科专业线数据***************")
table2 = file.add_sheet(name + '文科专业线')
value = ['学校名称', '年份', '专业名称', '科类', '平均分', '最高分', '最低分', '批次']
for i in range(len(value)):
table2.write(0, i, value[i])
for i in range(len(special_wenke)):
for j in range(len(special_wenke[i])):
table2.write(i + 1, j, special_wenke[i][j])
print("*************正在写入Excrl理科省控线数据***************")
table3 = file.add_sheet(name + '理科省控线')
value = ['学校名称', '年份', '科类', '最高分', '平均分', '最低分', '省控线', '批次']
for i in range(len(value)):
table3.write(0, i, value[i])
for i in range(len(info_like)):
for j in range(len(info_like[i])):
table3.write(i + 1, j, info_like[i][j])
print("*************正在写入Excrl文科省控线数据***************")
table4 = file.add_sheet(name + '文科省控线')
value = ['学校名称', '年份', '科类', '最高分', '平均分', '最低分', '省控线', '批次']
for i in range(len(value)):
table4.write(0, i, value[i])
for i in range(len(info_wenke)):
for j in range(len(info_wenke[i])):
table4.write(i + 1, j, info_wenke[i][j])
# ***********指定保存路径******************
file.save('D:\QQPCMgr(1)\Desktop\高校/' + name + '录取数据.xls')
print("****************"+name+"所有数据爬取成功"+"*********************")
def main():
for id in range(30,3000):
url="https://gkcx.eol.cn/school/"+str(id)
print(url)
Get_info(url,id)
if __name__ == '__main__':
main()