自动打卡
兰大自动打卡
参考博主伍尔夫的猫的博文如何通过Python自动完成移动校园“每日健康”打卡和博主CookiePie的文章Python—利用Requests实现每日微信自动打卡,拿来主义可耻,所以还是自己写一篇博客记录一下解决问题的过程,主要是为了学习,顺便激励自己好好写论文,坚持写代码,早日去实习。
一、前期准备
1、抓包
不细说了,安装Fiddler或者在浏览器端的话直接用谷歌开发者工具。(我是在浏览器端完成的,小程序端会复杂些)
2、安装selenium
我用的也是Pycharm,参考这个博主的Python配置Selenium+Chrome环境和Selenium+PhantomJS环境
3、配置Phantomjs
如果参考上面安装过程中测试代码没有问题就可以跳过了
1 | driver = webdriver.Chrome() |
如果会报错,那么奖励你,继续看Python配置Selenium+Chrome环境和Selenium+PhantomJS环境,其中,第5点说明了无界面的浏览器包PhantomJS的应用。如果还会报错,可以将selenium的版本修改为了selenium2.48.0版本,亲测可以。
代码
代码参考了原博主的,然后根据学校的网站进行抓包分析,思路和原博主基本上是一致的。
- 抓包分析
- 模拟登录
- 伪装Header发送Cookie,data
但是!!!,正是由于抓取的post包里面有Authorization,

并且它还是刷新的,如果Header中没有授权码,则服务器默认收到的是非法数据。所以耗费了一天时间才搞定。所以重点记录解决这个问题的思路,因为我看的好几篇博客并没有遇见这个问题,只需要Cookie和User-Agent就可以了。
直接说Authorization,先读读这个权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token ,说实话我这个菜鸡开始也不是很懂,不过看见这个,那没事了。

也就是说我们需要去找到服务端返回给客户端的token,也就是刷新的Authorization。所以
找到它
获取并使用它
更新它
那么我们已经在包里面找到它了,但是实际上还是没有找到它…因为我们需要将它的值获取到且随着它更新,而不是复制出来。
那么到这里,我当时有两个思路:
我有一个大胆(笨比)的想法,就是webdriver.Chrome()既然是模拟浏览器操作,那么我们
- 模拟登录后,得到新的网页
- 然后点击“健康打卡”又可以进入打卡界面
- 终于只需要点击上报就ok啦! 这不是有手就行!? 然后我写了如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url_)
driver.find_element_by_xpath('//*[@id="username"]').send_keys(user_['name'])
driver.find_element_by_xpath('//*[@id="password"]').send_keys(user_['password'])
driver.find_element_by_xpath('//*[@id="loginForm"]/div[4]/button').click()
sleep(2)
cookie_ = driver.get_cookies()[0]
print(driver.current_url)
sleep(1)
driver.switch_to.window(driver.window_handles[0])
el = driver.find_element_by_xpath('//*[@id="my-apps"]/li[3]')
ActionChains(driver).move_to_element(el).perform() #鼠标移动到该元素停留
sleep(2)
buttonElement = driver.find_element_by_xpath('//*[@id="my-apps"]/li[3]/a/div[2]/p[2]/span[1]')
ActionClick = ActionChains(driver).click(buttonElement)
ActionClick.perform()
frame1 = driver.find_element_by_id("iframe")
# 切换到iframe1这个内嵌网页
driver.switch_to.frame(frame1)
ActionChains(driver).move_by_offset(843, 100).click().perform() # 鼠标左键点击, 200为x坐标, 100为y坐标
sleep(3)
driver.quit()
return cookie_['name'] + '=' + cookie_['value']首先简简单单的就到了第二步,准备点击健康打卡,结果tmd它不是button,没办法click(),而且只有鼠标在这个模块上放一秒,它才会出现进入这个元素。所以我机智的(暴力的)通过强大的driver模拟了这一操作过程。终于,到了最后一步了,只需要点击新出现弹窗里面的“进入”就可以了,结果tmd(真的忍不住)这个弹窗就很神奇,它的元素是定位不到的!(试了很多解决方法不行)无奈之下,想到了我的老本行——暴力,把鼠标移动到这个“进入”的坐标位置点击左键即可。然后用snipaste截图测位置测了半天没找到,只能放弃。
暴力无奈之下,只能另寻他路。结果突然发现这个Authorization就是token,并且它还保存在sessionStorage里面,真的得来全不费功夫。真的需要认真读文档和博客,而不是自己瞎弄。后面就是打开切换到这个内嵌iframe上,然后获取到token值,这样就解决问题了。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90import requests
import json
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.action_chains import ActionChains
def get_cookie(url_, user_):
list = []
driver = webdriver.Chrome()
driver.get(url_)
driver.find_element_by_xpath('//*[@id="username"]').send_keys(user_['name'])
driver.find_element_by_xpath('//*[@id="password"]').send_keys(user_['password'])
driver.find_element_by_xpath('//*[@id="loginForm"]/div[4]/button').click()
sleep(1)
cookie_ = driver.get_cookies()[0]
sleep(1)
driver.switch_to.window(driver.window_handles[0])
el = driver.find_element_by_xpath('//*[@id="my-apps"]/li[3]')
ActionChains(driver).move_to_element(el).perform()
sleep(1)
buttonElement = driver.find_element_by_xpath('//*[@id="my-apps"]/li[3]/a/div[2]/p[2]/span[1]')
ActionClick = ActionChains(driver).click(buttonElement)
ActionClick.perform()
frame1 = driver.find_element_by_id("iframe")
# 切换到iframe1这个内嵌网页
driver.switch_to.frame(frame1)
sleep(1)
token = driver.execute_script('return sessionStorage.getItem("token");')
driver.quit()
list.append(cookie_['name'] + '=' + cookie_['value'])
list.append(token)
return list
user = {'name': '账号', 'password': '密码'}
list = get_cookie(
'http://my.lzu.edu.cn:8080/login?service=http://my.lzu.edu.cn', user) ##网页打卡入口
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
'Authorization': list[1],
'Cookie': list[0]
}
data = {
'bh': 'xxxxxxxxxx',
'xykh': 'xxxxxxxx',
'twfw': 0,
'jkm': 0,
'sfzx': 1,
'sfgl': 0,
'szsf': '',
'szds': '',
'szxq': '',
'sfcg': 0,
'cgdd': '',
'gldd': '',
'jzyy': '',
'bllb': 0,
'sfjctr': 0,
'jcrysm': '',
'xgjcjlsj': '',
'xgjcjldd': '',
'xgjcjlsm': '',
'zcwd': 0.0,
'zwwd': 0.0,
'wswd': 0.0,
'sbr': 'xxx',
'sjd': '',
'initLng': '',
'initLat': '',
'dwfs': ''
} ##= 这个就是抓取的Post包的data,更新自己的数据信息
url = 'https://appservice.lzu.edu.cn/dailyReportAll/api/grtbMrsb/submit' ##提交信息时候的php
key = 'Server酱的key'
try:
s = requests.session()
response = s.post(url=url, headers=headers, data=data)
html = response.text
except:
url = 'https://sc.ftqq.com/%s.send?text=登录页访问超时,打卡失败' % key
requests.get(url)
if json.loads(response.text)['message'] == '成功':
#url = 'https://sc.ftqq.com/%s.send?text=自动打卡成功' % key
#requests.get(url)
else:
url = 'https://sc.ftqq.com/%s.send?text=自动打卡失败' % key
requests.get(url)最后就是用Windows任务计划程定时调用执行Python脚本
还用了Server酱来提示打卡成功和打卡失败,over!


