← 返回所有文章

自动打卡

兰大自动打卡

参考博主伍尔夫的猫的博文如何通过Python自动完成移动校园“每日健康”打卡和博主CookiePie的文章Python—利用Requests实现每日微信自动打卡,拿来主义可耻,所以还是自己写一篇博客记录一下解决问题的过程,主要是为了学习,顺便激励自己好好写论文,坚持写代码,早日去实习。

一、前期准备

1、抓包

不细说了,安装Fiddler或者在浏览器端的话直接用谷歌开发者工具。(我是在浏览器端完成的,小程序端会复杂些)

2、安装selenium

我用的也是Pycharm,参考这个博主的Python配置Selenium+Chrome环境和Selenium+PhantomJS环境

3、配置Phantomjs

如果参考上面安装过程中测试代码没有问题就可以跳过了

driver = webdriver.Chrome()

如果会报错,那么奖励你,继续看Python配置Selenium+Chrome环境和Selenium+PhantomJS环境,其中,第5点说明了无界面的浏览器包PhantomJS的应用。如果还会报错,可以将selenium的版本修改为了selenium2.48.0版本,亲测可以。

代码

代码参考了原博主的,然后根据学校的网站进行抓包分析,思路和原博主基本上是一致的。

  1. 抓包分析
  2. 模拟登录
  3. 伪装Header发送Cookie,data

但是!!!,正是由于抓取的post包里面有Authorization,

〔原文配图在旧站中已缺失〕

并且它还是刷新的,如果Header中没有授权码,则服务器默认收到的是非法数据。所以耗费了一天时间才搞定。所以重点记录解决这个问题的思路,因为我看的好几篇博客并没有遇见这个问题,只需要Cookie和User-Agent就可以了。

直接说Authorization,先读读这个[权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token](https://www.cnblogs.com/wuwuyong/p/12210842.html) ,说实话我这个菜鸡开始也不是很懂,不过看见这个,那没事了。

〔原文配图在旧站中已缺失〕

也就是说我们需要去找到服务端返回给客户端的token,也就是刷新的Authorization。所以

  1. 找到它
  2. 获取并使用它
  3. 更新它

那么我们已经在包里面找到它了,但是实际上还是没有找到它…因为我们需要将它的值获取到且随着它更新,而不是复制出来。

那么到这里,我当时有两个思路:

  1. 我有一个大胆(笨比)的想法,就是webdriver.Chrome()既然是模拟浏览器操作,那么我们
  • 模拟登录后,得到新的网页
  • 然后点击“健康打卡”又可以进入打卡界面
  • 终于只需要点击上报就ok啦! 这不是有手就行!? 然后我写了如下代码:
driver = 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截图测位置测了半天没找到,只能放弃。 2. 暴力无奈之下,只能另寻他路。结果突然发现这个Authorization就是token,并且它还保存在sessionStorage里面,真的得来全不费功夫。真的需要认真读文档和博客,而不是自己瞎弄。后面就是打开切换到这个内嵌iframe上,然后获取到token值,这样就解决问题了。代码如下:

import 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!

搜索文章

搜索这些年写下的文字。

输入关键词搜索 · Esc 关闭