项目名称:爬取正方教务网课表及成绩信息
所需主要库文件:
- requests
- BeautifulSoup
- openpyxl
项目需求:
- 利用代码登陆教务网
- 爬取课程信息
- 爬取成绩信息
以浙江农林大学教务网为例
0.打开教务网->审查元素->NetWork->刷新教务网
image.pngimage.png
可以看到default2.aspx和CheckCode.aspx这两个链接
通过观察请求头可以发现,二者的Cookie值是一样的,
所以可以通过生成一个requests.session()对象来保留cookie信息
先请求default2.aspx保留cookie信息,再请求CheckCode.aspx两次请求cookie值相同,从而确保登陆
1、创建一个session对象访问default2.aspx记录cookie信息
s = requests.session()#相当于一个浏览器 记录所有信息
#eg.msgbox('正在连接教务网....',image='wait.gif')
try:
response = s.get("http://115.236.84.162/default2.aspx",headers=headers,timeout=5)
#print(response.status_code)
except ReadTimeout:
eg.msgbox('超时了,教务网好像蹦了。。。再试试。。(Timeout)','作者:Warms QQ:769737584',image='pawd.gif')
#print('Timeout')
return 0
except ConnectionError:
eg.msgbox('请检查你的网络!','作者:Warms QQ:769737584',image='pawd.gif')
#print('Connection error')
return 0
except RequestException:
eg.msgbox('教务网蹦了。。。。(HTTPerror)','作者:Warms QQ:769737584',image='pawd.gif')
#print('Error')
return 0
2、使用上一步的session对象访问CheckCode.aspx获取验证码
res = s.get('http://115.236.84.162/CheckCode.aspx',headers=headers)
with open('验证码.gif','wb') as f:
f.write(res.content)
#os.system('验证码.gif')
msg = '请输入验证码(看不清请点击"Cancel"):'
img = '验证码.gif'
while True:
Code = eg.enterbox(msg,'作者:Warms QQ:769737584',image=img)
if Code == '':
msg = '验证码不能为空!'
continue
elif Code==None:
res = s.get('http://115.236.84.162/CheckCode.aspx', headers=headers)
with open('验证码.gif', 'wb') as f:
f.write(res.content)
continue
else:
break
上面已经通过代码访问了教务网首页,下一步就是登陆
浏览器打开教务网输入用户名、密码、验证码->登陆
审查元素->NetWork->查看网络请求
image.png在拦截的网络请求中可以看到default2.aspx的Request Method变为了post请求,再来查看一下Form data
image.png
在Form data中有__VIEWSTATE这个键,其值时可变的,在post数据中也是必不可少的,下一步是怎样获取这个值,打开教务网登陆首页->查看源代码->Ctrl+F搜索.
image.png
在源代码中找到了__VIEWSTATE它在一个input标签中 属性value的值及为需要的数据,利用BeautifulSoup解析库可以方便的提取出__VIEWSTATE
soup = BeautifulSoup(response.text,'lxml')
value =soup.find('input')['value']
Form data中还有一个键为RadioButtonList1,搜索登陆页源代码可知这是URL编码后的学生 两字(这里是以学生身份登陆所以是学生)
requests库会自动进行URL编码 也可以从 urllib.parse库中引入urlencode方法进行编码
构建post_data
def get_post_data(number,passward,Code,value):
data = {
'__VIEWSTATE':value,
'txtUserName':number,
'Textbox1':'',
'TextBox2':passward,
'txtSecretCode':Code,
'RadioButtonList1': '学生',
'Button1':'',
'lbLanguage':'',
'hidPdrs':'',
'hidsc':'',
'__EVENTVALIDATION':''
}
return data
3、发送post请求完成登陆
try:
response =s.post('http://115.236.84.162/default2.aspx',data=get_post_data(number=students_number,passward=passward, Code=Code,value=value),headers=headers)#登陆首页 响应
except ReadTimeout:
eg.msgbox('超时了,教务网好像蹦了。。。(Timeout)''作者:Warms QQ:769737584',image='pawd.gif')
#print('Timeout')
return 0
except ConnectionError:
eg.msgbox('请检查你的网络!''作者:Warms QQ:769737584',image='pawd.gif')
#print('Connection error')
return 0
except RequestException:
eg.msgbox('教务网蹦了。。。。(HTTPerror)''作者:Warms QQ:769737584',image='pawd.gif')
#print('Error')
return 0
3、判断是否登陆成功
由于登录后defaut.aspx2的状态码是302 重定向,requests库后会自动跳转到重定向后的网址,如需关闭请将allow_redirects参数设为False这里不关闭,由于会切换网页所以response的URL会改变,这里通过判断URL是否切换来判断是否登陆成功
if 'xs_main.aspx'in response.url :#if 'xs_main.aspx'in response.url :6671
#print('login Success!')
choices = ['最新学年课表','成绩单']
while True:
choice = eg.indexbox('请选择查询类型:','作者:Warms',image='success.gif',choices=choices)
if choice == 0:
class_html = get_class_infor(s,response.text).replace(r'<br>', '\n')
code= save_class_infor(class_html)
return code
elif choice == 1:
grades_html = get_grates_infor(s,response.text).replace(' ',' ')
code=save_grades_infor(grades_html)
return code
else :
return 4#输入信息有误
4、拉取课表框架代码->BeaufulSoup库解析->存储到excel
这里还是用之前创建的requests.session()对象来访问课表URL,即需要保持相同的cookie值,否则会出现302 错误无法获取框架代码,注意这里的header一定要加上Referer:http://115.236.84.162/xs_main.aspx?xh=' + students_number (登录后的URL加上学生学号)否则会出错
def get_class_infor(s,text):
header = {
'Referer': 'http://115.236.84.162/xs_main.aspx?xh=' + students_number,
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
params = get_params_data(text)#获取get请求参数
class_url = 'http://115.236.84.162/xskbcx.aspx'
response = s.get(class_url, headers=header, params=params )#课程信息 响应体
return response.text
def get_params_data(text):
soup = BeautifulSoup(text, 'lxml')
name = soup.find(id="xhxm").string[:2]
params = {
'xh': students_number,
'xm': name,
'gnmkdm': 'N121603'
}
return params
5、拉取成绩框架->BeautifulSoup解析->存储到excel
def get_grates_infor(s,text):
header = {
'Referer': 'http://115.236.84.162/xs_main.aspx?xh=' + students_number,
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
payload = {
'__EVENTTARGET':'',
'__EVENTARGUMENT':'',
'__VIEWSTATE': '',
'hidLanguage':'',
'ddlXN':'',
'ddlXQ':'',
'ddl_kcxz':'',
'btn_zcj':'历年成绩'
}
params = get_params_data(text) # 获取get请求参数
grades_url = 'http://115.236.84.162/xscjcx.aspx'
response = s.get(grades_url, headers=header, params=params) # 成绩信息 响应体
#print(response.url)
soup = BeautifulSoup(response.text, 'lxml')
value = soup.input. find_next_sibling(). find_next_sibling()['value']
#print(value)
payload['__VIEWSTATE']=value
#print(response.url)
response = s.post(response.url,headers=header,data=payload)
#print(response.text)
return response.text
网页分析和上面第二步分析类似
总结一下:分析请求方式post或者get->分析Form data 查看网页源代码查找所需数据是否存在-->提取所需数据(用解析库或者正则表达式)->构建Form data ->用对应的请求方式进行请求->得到所需要的网页源代码->提取数据->存储
源代码
如有帮助请帮忙点个星
github:https://github.com/pythonFCG/Access-to-the-course-information
7、效果图
加上了easygui 并对excel进行了美化
网友评论