starry成见

python+selenuim实现web自动打卡

Toretto·2022-01-16 21:59·770 次阅读

python+selenuim实现web自动打卡

python+selenuim实现web自动打卡#

摘要:

​ 大概就是在XX背景下,需要每天登录网站填报体温,所在地信息等,分析登录时发送请求逻辑,通过python-selenium实现自动打卡。

思路#

​ 通过selenium操作浏览器,完成登录->填充表单信息->定时重复打卡。

  1. 登录: 使用机器完成登录有两种方法,一种通过定位验证码位置通过ocr识别字符,登录后保存cookie,之后往浏览器中填入cookie即可跳过登录, 其次就是手动维护cookie。分析得到当发起登录请求时,客户端将生成随机字符串塞入Request-Header的cookie中,ASP.NET_SessionId=ryhrbiqalg14hgrxhmhd4ie5,服务端在Response-Header的Set-Cookie中塞入 CenterSoftWeb=xxxxx; expires=Sun, 23-Jan-2022 07:45:06 GMT; path=/; HttpOnly,由此组成完整的可跳过登录的cookie
  2. 填充表单信息 通过selenium操作浏览器中元素,完成一系列逻辑操作,(需要下载浏览器所对应的驱动driver,chrome+chromedriver)
  3. 定时重复打卡 Crontab+shell 即可实现每日定时启动

关于selenium-python,请到网站查看

具体实现#

image-20220116144155199

​ 定位验证码位置,由机器识图,首先启动操作selenium在当前运行环境下获取浏览器截图,再将图片导入ps中定位验证码四角位置像素值。

获取到四角位置时,即可保存验证码图片传入ocr机器识别。

Copy
#保存截图 browser.save_screenshot('verification/'+stunumber+'.png') #填入信息 browser.find_element_by_id("StudentId").send_keys(stunumber) browser.find_element_by_xpath("/html/body/div[1]/div[2]/div/div[2]/form/div[2]/div[2]/input").send_keys(pwd) #图片剪切 left = 781 top = 336 right = 870 bottom = 369 picture = Image.open('verification/'+stunumber+'.png') picture = picture.crop((left, top, right, bottom)) picture.save('verification/'+stunumber+'-ed.png') #ocr识别 接入的是api yzm_code = moyunocr.getYzm('verification/'+stunumber+'-ed.png') #获取cookie写入文件 dictCookies = browser.get_cookies() jsonCookies = json.dumps(dictCookies) with open('cookies/'+stunumber+'_cookie.txt', 'w') as f: f.write(jsonCookies)

存储的cookie内容#

ps:获取到的Cookie通过json库对象转为文本了,因此格式与官方定义的cookie格式略有差别。

Copy
[ {"domain": "dxg.cxxu.edu.cn", "expiry": 1615705350, "httpOnly": true, "name": "CenterSoftWeb", "path": "/", "secure": false, "value": "08CBB2BBDCB3E268D3EE9D0C8046B4C979910509ACF95A1F302336B2826DCAD9CE60311213F70E114CAF84ED18695CB3C6260D17B502F8D42ADC8966B6886C5C78D8B479AC5F152E8CC526E9517C1CF3783D3462632A5EDC0104C19C58AFCE9B020937BD766C253F8A327AE72F11F5ECD4F91E72021B3ECC9C7232BFBCAEF0BA38ACD4246EA9CD293CD7ADFD1BC682DF7FEB194CB8E433804D93B3CF00B299E55DA5530BF7D32523977316BAF9486DBAB85221C5348E587F05220BC9A44EE8901C33ADD15097D87E8305C0FEF8A4A3B9D2B358172EA280D622DE78B53CAE5EE88379B2600F38740BD2D33CFC0192CCD9B2DCE5C8BE4124A4466623C8A96B2499B25C16C9EA128D19C88BA0FD8BC4746F"}, {"domain": "dxg.cxxu.edu.cn", "httpOnly": true, "name": "ASP.NET_SessionId", "path": "/", "secure": false, "value": "qe45ulzkfahnqjvvexj45kcr"} ]

What Cookie#

cookie文档

​ 基于HTTP协议本身是无状态的,无法辨别每次的请求是否由同一个用户发起,因此可以通过在每次请求头中放入可识别状态的信息。由此引生出cookie与token等两种身份验证方式,可简单理解为 身份识别器。

​ Cookie发起请求时存在于Request-Header中。

格式:

​ cookie为一组 name=value形式的数据并以';'分割的列表 例:PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1

What Set-Cookie#

​ Set-Cookie HTTP响应头用于将Cookie从服务器发送到用户代理,以便用户代理稍后可以将其发送回服务器。要发送多个Cookie,应在同一响应中发送多个Set Cookie头

Attributes属性

属性项 描述 是否必须
cookie-name=cookie-value name自定但要唯一,value依据业务存值
Expires=date 1.cookie的最长生存期,2.不设置则是会话cookie 3.截止日期与设置cookie的客户端相关,过期删除
Max-Age=number 类似Expires但优先级比Expires高
Domain=domain-value 1.定义接收cookie的主机 2.[.example.com]写法包含子级域名但可能被忽略
Path=path-value 1.cookie生效路径 URL中必须存在的路径
Secure 只有在用https进行请求时才将cookie发送到服务器
HttpOnly 禁止JavaScript访问cookie
SameSite=samesite-value 控制cookie是否随跨源请求一起发送 可选[Strict(禁止跨域),Lax(在用户从外部网站导航到原网站时发送cookie,默认),None(允许跨域,同时设置Secure)]

请求携带Cookie#

Copy
with open('cookies/'+stunumber+'_cookie.txt', 'r', encoding='utf8') as f: listCookies = json.loads(f.read()) # 往browser里添加cookies for cookie in listCookies: cookie_dict = { 'domain': '.mnnu.edu.cn', 'name': cookie.get('name'), 'value': cookie.get('value'), "expires": '', 'path': '/', 'httpOnly': False, 'HostOnly': False, 'Secure': False } browser.add_cookie(cookie_dict) browser.refresh()

Linux下selenium配置#

前提:由于linux浏览器无法界面化,因此在初始化browser时需要额外指定配置

Copy
chrome_options = webdriver.ChromeOptions() # 无头模式 chrome_options.add_argument('--headless') # 禁用GPU加速 chrome_options.add_argument('--disable-gpu') browser = webdriver.Chrome(chrome_options=chrome_options, executable_path='/root/chromedriver') #全局隐式等待时间 browser.implicitly_wait(10)

脚本监听cookie过期#

遍历指定文件夹下cookie文件的最后一次修改时间与现在时间的间隔,当间隔超过6天时邮件提醒更新

Copy
SIX_DAY_SECONDS=6*24*60*60 SEVEN_DAY_SECONDS=7*24*60*60 def listFile(rootpath): todayStamp = time.time() todayTime = dateFormat(todayStamp) logging.info("==========="+todayTime+"====START====") fileList = os.listdir(rootpath) email_msg ="" for i in range(0,len(fileList)): fullpath = os.path.join(rootpath,fileList[i]) # 判断是否是文件 if os.path.isfile(fullpath): # 获取最后修改日期 lastTimeStamp = os.path.getmtime(fullpath) # 相差秒数 diffSeconds = daysDiff(todayStamp,lastTimeStamp) if SEVEN_DAY_SECONDS-diffSeconds <=0: logging.info(stunumber+ "您的cookie已经过期") if diffSeconds<=SEVEN_DAY_SECONDS : if diffSeconds>=SIX_DAY_SECONDS : logging.info(stunumber+"您的cookie即将过期 有效时间还剩:"+str((SEVEN_DAY_SECONDS-diffSeconds)//3600)+"小时") # 发送邮件提醒 email_msg+=stunumber+"您的cookie即将过期 有效时间还剩:"+str((SEVEN_DAY_SECONDS-diffSeconds)//3600)+"小时\n" else: logging.info(stunumber+"您的cookie有效时间还剩:"+str((SEVEN_DAY_SECONDS-diffSeconds)//3600)+"小时")
posted @   成见  阅读(770)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
zz
点击右上角即可分享
微信分享提示
目录