背景
我是一个程序员,在201906月参加了PMP考试,考试报名费3900,培训费2499。
虽然考试前做了充分的准备,听网课、刷视频、刷题。但是在考试时,还是很懵逼,毕竟刷题那么多,但是PMP还是没有原题这么一说。
由于担心考试成绩不够理想,考试后的那一个月,天天都在登录PMI网站查询成绩,特别是临近发布成绩的那几天,每天基本要查个4-5遍,生怕老美忘记了给我发成绩的邮件。
由于考试是分ABCDE卷的,大部分同学都收到邮件了,而我还是没收到邮件,所以我猜测我应该是E卷。所以在多久之后的一个晚上,大概11点左右,才收到成绩邮件,还好通过了考试,不然真对不起自己熬夜刷题的那几晚上(虽然程序员老熬夜)。
时过境迁啊,这段时间,微信培训班里的同学又开始了新一轮的成绩查询,几乎天天都在问班主任什么时候成绩能下来之类的话。看着电脑里面成绩邮件,可想当初对考试成绩所急迫的心理。索性,为了帮助他们方便查询成绩,我就做一个查询成绩的小程序,一来练习下小程序的开发,二来作为过来人也就当为你们这些学弟学妹做个贡献吧。
页面展示
小程序首页结果1 结果2
所用技术
前台:微信小程序+支付宝小程序(uni-app)
后台:python(flask+requests+bs4)+ mysql + 腾讯云服务器
分析PMI网站代码
流程上只有2个重要节点
- 登录分析
- 成绩数据分析
PMI登录分析
-
用谷歌内核类的浏览器打开该网站
登录页面 -
点击F12,然后切到network页面
network页面 - 去登录页面随手输入账号1111111密码22222222
-
查看network页面查看连接
network2
此时找到第一个连接,可以看到提交的参数,其中包含了账号和密码
账号密码是明码(未加密),连加密流程都省下来了
-
右键点击网页查看源代码
此时可以找到上一个步骤中提交的参数及值信息,没有js自动生成的话,那就简单多了
源代码
报错信息当然,提取这些参数,可以用正则的方式,也可以使用 BeautifulSoup(bs4)
正则和bs4相对来说,bs4取数的代码要整洁一些
提示账号错误的信息也要提取出来,作为登录成功与否的提醒信息
登录伪代码
headers = {"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36 Edg/79.0.309.68",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"Accept-Encoding": "gzip, deflate, br"}
analysis = "https://ccrs.pmi.org/reporting/examanalysis"
dashboard = "https://ccrs.pmi.org/"
login_url = "https://authentication.pmi.org/Default.aspx?r=ccrs.pmi.org&s=True"
def login(self, uid, pwd, openid,platform = 'wechat'):
global session
self.session = requests.Session()
r = self.session.get(self.login_url, headers=self.headers)
soup = BeautifulSoup(r.text, 'html.parser')
inputs = soup.find_all('input')
params = {}
for input in inputs:
key = input.attrs.get('id', '')
value = input.attrs.get('value')
if 'tbUserName' in input.attrs.get('name'):
key = key.replace('_', '$')
value = uid
elif 'tbPassword' in input.attrs.get('name'):
key = key.replace('_', '$')
value = pwd
params[key] = value
params['__EVENTTARGET'] = 'ctl00$ContentMain$bLogIn'
r = self.session.post(url=self.login_url,
data=params, headers=self.headers)
# 分析是否登录成功
soup = BeautifulSoup(r.text, 'html.parser')
error = soup.select_one('.error-msg')
if error:
return False, error.text.strip()
else:
return True, r.cookies.get_dict()
PMI成绩分析
-
登录成功后的页面
个人主页
dashboard登录后跳转到个人主页
右边CERTIFICATION STATUS这个地方是当次考试信息,也是我们需要获取的地方,点击view more on your dashboard
源代码这个网页就是我们需要获取的数据了,右键查看源代码
通过bs4,我们可以从中提取相应的数据
基础数据分析代码
def _dashboardExams(self, cookies):
r = self.session.get(
self.dashboard, headers=self.headers, cookies=cookies)
soup = BeautifulSoup(r.text, 'html.parser')
# 图表区域
chart = soup.select('.chart-details')[-1]
# 这个是基本信息
span = chart.select('span')
Credential = span[0].text
Status = span[1].text
Earned = span[2].text
Renewal = span[3].text
renewDay = soup.select_one('.status.renewal')
renewDay = renewDay.select_one('em').text
chart = soup.select('.toggle-container')[-1]
em = chart.select('em')
Required = em[0].text
Applied = em[1].text
Remaining = em[2].text
return {'exams': [{'label': '证书号', 'content': Credential},
{'label': '状态', 'content': Status},
{'label': '取证日期', 'content': Earned},
{'label': '过期日期', 'content': Renewal},
{'label': '剩余过期天数', 'content': renewDay}],
'pdus': [{'label': '总共需要', 'content': Required}, {'label': '已取得', 'content': Applied}, {'label': '还需', 'content': Remaining}],
'crdate': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
原饼图最后还有一个考试分析的圆饼图,打开 考试分析,见下图
源代码需要继续查看源代码,分析原饼图的数据,见下图
json上图可以看到原饼图信息都是在html里面呈现,所以直接分析截取js代码就行了
用一个json格式化工具,找到关键节点即可
原饼图伪代码分析
def _analyExams(self, cookies):
r = self.session.get(
self.analysis, headers=self.headers, cookies=cookies)
soup = BeautifulSoup(r.text, 'html.parser')
data = {}
# 获取成绩是否通过
label = soup.select_one('.performance')
result = label.text.strip().split(':')
data['result'] = result[-1]
# 获取圆饼图
script = soup.select_one('.pie-chart')
script = script.text
js_json = re.findall('kendoChart\((.+?)\);}\);', script)[0]
j = json.loads(js_json)
items = j['dataSource']['data']
if items and len(items) > 0:
data['items'] = []
for item in items:
label = item['Domain']
color = item['Color']
total = item['PercentageofTotal']
data['items'].append(
{'color': color, 'label': label, 'total': total, 'level': level})
return data
小程序代码
小程序主要用uni-app跨平台框架来写的,其中他用的是vue的写法,我对vue也是刚学不久。套用了colorUI的外观以及ucharts的图表,还算把这个小程序给写下来了。
后台代码
总结
PMP考试相对于IPMP,CPMP恐怕要简单一些,每年的各个机构通过率都90%左右,所有各位有兴趣的话,可以考取一个,因为学习是一件终身的事情。
这次网站爬虫还是很简单的,毕竟所有数据都在页面可得,并不需要构造ajax请求就能获取。十分符合老美的风格。
另外,欢迎大家体验我做的小程序,目前已经上架 微信小程序和支付宝小程序。
微信小程序
支付宝小程序
网友评论