/ 生活

定时汇报成绩脚本

0x01 介绍

定时查看成绩,当有新成绩出来时向邮箱发送成绩
主要麻烦的地方是分析信息门户统一认证登录的过程

0x02 代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2017-01-15
# @Author  : Sqvds (wang@sqvds.com)
# @Link    : http://www.sqvds.com
# @Version : 1.0

import requests
import time
import re
from bs4 import BeautifulSoup
import smtplib
from email.mime.text import MIMEText
import datetime

NowMax = 6

def Grade():
	# 几个重要的URL
	loginURL = "http://idas.uestc.edu.cn/authserver/login?service=http://portal.uestc.edu.cn/index.portal"
	loginURLCapture = "http://idas.uestc.edu.cn/authserver/needCaptcha.html?username=2015220501006&_=%s" % str(time.time())
	grade = "http://eams.uestc.edu.cn/eams/teach/grade/course/person!search.action?semesterId=123&projectType="
	myheaders = {
		'Proxy-Connection': 'keep-alive',
		'Cache-Control': 'max-age=0',
		'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
		'Upgrade-Insecure-Requests': '1',
		'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36',
		'Content-Type': 'application/x-www-form-urlencoded',
		'Referer': 'http://portal.uestc.edu.cn/index.portal',
		'Accept-Encoding': 'gzip, deflate',
		'Accept-Language': 'zh-CN,zh;q=0.8',
	}


	r = requests.Session()
	checkCapture = r.get(loginURLCapture,headers=myheaders)
	if checkCapture.text == 'true':
		print "Need Capture"
		exit()
	login = r.get(loginURL,headers=myheaders)
	# lt是存在页面上的一个hidden标签,还有其他的几个需要post的数据是放在hidden中但是只要lt是变化的
	lt = re.findall(r'name="lt" value="(.*)"/>',login.text)[0]

	post_data = {
		'username': 'xxxxxxx',  # 这里输入学号
		'password': 'xxxxxx',	# 信息门户密码
		'lt': lt,
		'dllt': 'userNamePasswordLogin',
		'execution': 'e1s1',
		'_eventId': 'submit',
		'rmShown': '1'
	}

	login = r.post(loginURL, data=post_data, headers=myheaders)
	login.encoding='utf-8'
	# 简单的判断一下是否成功登陆
	result = re.findall(u'<li>欢迎您:</li>', login.text)
	if result:
		print "Login success"
	else:
		# 登陆失败就发送邮件通知
		print "failed login in"
		_user = "xxxxxx"	# 发送邮件者邮箱
		_pwd  = "xxxxxx"	# 邮箱授权码
		_to   = "xxxxxx"	# 目的地邮箱
		msg = MIMEText(u"登录失败",_subtype='plain',_charset='utf-8')
		msg["Subject"] = u"请注意"
		msg["From"]    = _user
		msg["To"]      = _to

		try:
		    s = smtplib.SMTP_SSL("smtp.qq.com", 465)
		    s.login(_user, _pwd)
		    s.sendmail(_user, _to, msg.as_string())
		    s.quit()
		    print "Success!"
		except smtplib.SMTPException,e:
		    print "Falied,%s"%e

	getgrade = r.post(grade,headers=myheaders)

	# 用bs4分析页面将成绩存储到一个列表中去
	mygrade = []
	soup = BeautifulSoup(getgrade.text,"html5lib")
	for idx, tr in enumerate(soup.find_all('tr')):
		if idx != 0:
			tds = tr.find_all('td')
			mygrade.append(
				{
				'课程序号': tds[2].contents[0],
				'课程名称': tds[3].contents[0],
				'学分': tds[5].contents[0],
				'总评成绩': tds[6].contents[0],
				'绩点': tds[9].contents[0]
				})

	# 返回一个存储成绩的列表 和 成绩那一页的html
	return mygrade,getgrade.text

def main():
	# 目前出了六门成绩,判断如果超过六门成绩就发邮件通知,并更新阈值,全局变量NowMax
	global NowMax
	mygrade,htmlcontent= Grade()
	if len(mygrade)>NowMax:
		# 更新报告的阈值
		NowMax = len(mygrade)
		print "NowMax = "+str(NowMax)
		# 先本地打印一份成绩
		print '课程序号'+'\t'+'课程名称'+'\t'+'学分'+'\t'+'总评成绩'+'\t'+'绩点'
		for i in mygrade:
			print i['课程序号']+'\t'+i['课程名称']+'\t'+i['学分']+'\t'+i['总评成绩']+'\t'+i['绩点']

		# 将成绩发送到邮箱中去
		_user = "xxxxxx"	# 发送邮件者邮箱
		_pwd  = "xxxxxx"	# 邮箱授权码
		_to   = "xxxxxx"	# 目的地邮箱
		content = htmlcontent
		msg = MIMEText(content, _subtype='html', _charset='utf-8')
		msg["Subject"] = "don't panic"
		msg["From"]    = _user
		msg["To"]      = _to

		try:
		    s = smtplib.SMTP_SSL("smtp.qq.com", 465)
		    s.login(_user, _pwd)
		    s.sendmail(_user, _to, msg.as_string())
		    s.quit()
		    print "Success!"
		except smtplib.SMTPException,e:
		    print "Falied,%s"%e 

def sleeptime(hour,min,sec):
	return hour*3600 + min*60 + sec

# 定时45分钟查询一次
second = sleeptime(0, 45, 0)
while True:
	now = datetime.datetime.now()
	now.strftime('%Y-%m-%d %H:%M:%S')
	print now
	main()
	time.sleep(second)

定时汇报成绩效果