网站地址 aHR0cHM6Ly93d3cuamF2YXh4ei5jb20=
首先进入登陆页面
sp230315_213745.png (29.07 KB, 下载次数: 0)
下载附件
2023-3-15 22:27 上传
用Charles抓包分析获取二维码图片的链接 实际上测试这些都是固定值. 那个小数应该是为了避免浏览器缓存.
每次刷新页面都不一样.我们可以在python直接发请求.
sp230315_213930.png (21.58 KB, 下载次数: 0)
下载附件
2023-3-15 22:28 上传
也可以直接从登陆页面直接拿链接请求
image.png (17.4 KB, 下载次数: 0)
下载附件
2023-3-15 22:31 上传
image.png (18.44 KB, 下载次数: 0)
下载附件
2023-3-15 21:51 上传
image.png (18.44 KB, 下载次数: 0)
下载附件
2023-3-15 21:51 上传
然后问题就是识别二维码. 这个问题先放一放.看下登陆请求.
sp230315_214109.png (35.1 KB, 下载次数: 0)
下载附件
2023-3-15 22:30 上传
其中formhash参数不知道哪里来的 在Charles搜一下,或者控制台搜索,发现是登陆页面隐藏字段.
拿过来用就是了.
image.png (63.16 KB, 下载次数: 0)
下载附件
2023-3-15 21:55 上传
同样的path也可以直接从form的action拿.其余的账号密码填上就是了 其中
seccodeverify cr27这个是验证码.
好了整个流程还是很简单.没有加密没有混淆.好多参数直接在页面就可以拿到.
image.png (50.58 KB, 下载次数: 0)
下载附件
2023-3-15 21:57 上传
接下来说说怎么识别验证码.使用的 ddddocr
ddddocr是由sml2h3开发的专为验证码厂商进行对自家新版本验证码难易强度进行验证的一个python库,
其由作者与kerlomz共同合作完成,通过大批量生成随机数据后进行深度网络训练,本身并非针对任何一家验证码厂商而制作,
本库使用效果完全靠玄学,可能可以识别,可能不能识别。
ddddocr奉行着开箱即用、最简依赖的理念,尽量减少用户的配置和使用成本,希望给每一位测试者带来舒适的体验
项目地址: https://github.com/sml2h3/ddddocr.
我下面的代码是采用的部署成服务方式调用来处理的.我签到任务是在青龙面板docker中执行的.在青龙面板中安装ddddocr依赖失败了.
就调用部署在宿主机的接口来进行识别.
可以参考python | 傻瓜式一键搭建图片验证码识别接口https://blog.csdn.net/qq_41437542/article/details/129193844部署api.
如果你在环境安装ddddocr依赖没问题就直接把decodeYzm改成直接用ddddocr方式去处理.就不需要http方式去处理.
base64_data = base64.b64decode(ImageBase64)
ocr = ddddocr.DdddOcr(show_ad=False)
res = ocr.classification(base64_data)
return {"result": res}
下面代码支持多账号.
需要修改的有几个地方.
domain 改为正确的域名,
push_plus_token 的值.
账号密码.
验证码识别接口地址.或者直接修改成ddddocr直接识别.
最后效果
1678890001(1).png (46.75 KB, 下载次数: 0)
下载附件
2023-3-15 22:20 上传
代码有详细注释可以参考
[Python] 纯文本查看 复制代码import base64
import sys
import requests
import os
from bs4 import BeautifulSoup
import random
# 很重要 用session方式 就不用手动处理cookie.注意换账号登陆时候记得清除cookie
session = requests.Session()
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.69"
}
# 域名请自行解码
domain = "aHR0cHM6Ly93d3cuamF2YXh4ei5jb20="
# 这样开着代{过}{滤}理的时候不会报连接错误 方便测试
os.environ['NO_PROXY'] = domain
#在 https://www.pushplus.plus 免费获取
push_plus_token = "你的token"ocrapi = "http://ip:port"accounts = [{"username": "账号1", "password": "密码1"},
{"username": "账号2", "password": "密码2"},
{"username": "账号3", "password": "密码3"},
{"username": "账号4", "password": "密码4"}
]
# 模拟随机生产五位数字
def getNums(length):
the_str = ""
for i in range(length):
ch = chr(random.randrange(ord('0'), ord('9') + 1))
the_str += ch
return the_str
# 获取验证码
def getYzmImg():
rdnum = getNums(5)
url = f"{domain}/misc.php?mod=seccode&update={rdnum}&idhash=cS"
getHeader = {"referer": f"{domain}/member.php?mod=logging&action=login&phonelogin=no",
"user-agent": headers['User-Agent']}
get = session.get(url, headers=getHeader)
# print(get.content)
# print(f"getYzmImg cookie:{session.cookies}")
return get.content
# 调用搭建的验证码识别api服务.采用这种方式是因为在青龙面板中安装相关依赖失败了.
def decodeYzm(img_types):
img_base64 = base64.b64encode(img_types).decode()
# print(img_base64)
post_headers = {"content-type": "application/json"}
res = session.post(url=f"{ocrapi}/code/", headers=post_headers, json={'ImageBase64': img_base64})
# print(res.text)
return eval(res.text)['result']
# 获取登陆需要的formhash参数 action时间上好像是定值,不过在form里面就顺便拿过来了
def getLoginParam():
url = f"{domain}/member.php?mod=logging&action=login&phonelogin=no"
response = session.get(url, headers=headers)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, "html.parser")
formhash = soup.find('input', attrs={'name': 'formhash'})["value"]
action = soup.find('form', attrs={'name': 'login'})["action"]
# print(f"formhash:{formhash}")
# print(f"action:{action}")
param = {"formhash": formhash, "action": action}
return param
# 执行登陆逻辑
def doLoginOnce(param, user, yzm):
login_dict = {
"formhash": param['formhash'],
"referer": f"{domain}/./",
"loginfield": "username",
"username": user["username"],
"password": user["password"],
"questionid": "0",
"answer": "",
"seccodemodid": "member::logging",
"seccodeverify": yzm
}
res = session.post(url=f"{domain}/{param['action']}", headers=headers, data=login_dict)
# 登陆成功后返回的页面内容会包含用户名
if user["username"] in res.text:
# print(f"登陆结果:{res.text}")
return True
return False
# 登陆并签到
def doLoginAndSign(user):
i = 1
login_param = getLoginParam()
login_suc = doLoginOnce(login_param, user, decodeYzm(getYzmImg()))
# 验证码识别错误,登陆失败的话 重试
while i