前言
看到舍友最近对爬虫感兴趣,然后尝试写一个自动签到脚本,但是他的方案好麻烦呀,遂写一篇文章分析之。
网页分析 - 登录
首先,目标是咸鱼单机-单机游戏交流分享平台,我们需要分析他的登录机制。
F12打开浏览器的开发者工具,这里有一个小技巧,勾选保留日志
,因为登录行为往往伴随页面刷新,如果不勾选保存日志,登录的具体日志就会一闪而过,不利于分析。
这登录也忒简单了吧……!没有验证码,非常nice.
登录一下看看日志具体是怎么样的。
发了一个POST请求,包含明文的username和password,然后从响应中通过“set-cookies”返回cookies信息给浏览器。
方案选型
这里有两种方法:
①我们主动存储cookies信息,然后下一次访问签到API的时候在请求头中带上
②使用requests.Session,一套搞定。
③使用selenium,模拟浏览器真实操作
这里介绍方法②。
什么是requests.Session对象?
在Python的requests库中,requests.Session对象是一个用于发送HTTP请求的实例。与直接使用requests.get()或requests.post()发送单独的请求不同,使用Session对象可以在多个请求之间保留一些状态信息,例如cookies、headers等,从而实现更高效的HTTP通信。
说白了就是,它帮我们存储cookies和header这一堆拉杂东西,极大简化代码量。哎,人生苦短,我用Python.
代码实现
import requests
# 模拟登录
session = requests.Session()
login_url = "https://www.xianyudanji.net/wp-admin/admin-ajax.php"
login_data = {
'action': 'user_login',
'username': '', #用户名
'password': '', #密码
'rememberme': '1'
}
response = session.post(login_url, data=login_data) #post和get的时候调用前文定义的对象就可以了
if response.status_code == 200 and '"status":"1"' in response.text:
print("登录成功")
else:
print("登录失败")
exit()
现在,session对象内就已经存有了cookies等一系列信息了,我们只要继续找一下签到的方法,然后下一次继续调用session.post()或者session.get()就好。
然后是签到。
网页分析 - 签到
单击按钮后发起一个POST请求。
这里的“nonce”有点意思,大概率是一个动态变化的值,我们检查一下它是怎么来的吧。
Ctrl+F激活搜索工具,输入我们刚刚的nonce e91b5f2d29:
找到了。
代码如下:<button class="btn btn-sm btn-info w-100 mt-3 go-user-qiandao" disabled data-nonce="e91b5f2d29" data-toggle="tooltip" data-placement="bottom" title="每日签到奖励: 0.3赞助币"><i class="fa fa-check-square-o"></i> 今日已签到</button>
我们需要使用bs库来拿到这个动态的nonce值:qiandao_button = soup.find('button', {'class': 'go-user-qiandao'})
另外查了一下这个nonce的用途:
这是 WordPress 的安全机制之一,称为 "nonce"(数字一次性使用密码),用于防止跨站请求伪造 (CSRF) 攻击。这个值确保请求来自合法用户而非恶意脚本。nonce 值是由服务器生成的,并在页面中通过 JavaScript 提供
代码实现
from bs4 import BeautifulSoup
#...这里就是前文的内容,我省略掉了
# 获取包含签到按钮的页面
user_page = session.get('https://www.xianyudanji.net/user')
# 解析页面获取签到按钮的状态和 nonce
soup = BeautifulSoup(user_page.text, 'html.parser')
qiandao_button = soup.find('button', {'class': 'go-user-qiandao'})
# 检查签到按钮是否被禁用
if 'disabled' in qiandao_button.attrs:
print("今日已签到,无法重复签到")
else:
# 提取 nonce 值
nonce = qiandao_button['data-nonce']
print(f"获取到的 nonce 值: {nonce}")
# 构建签到请求
qiandao_url = "https://www.xianyudanji.net/wp-admin/admin-ajax.php"
qiandao_data = {
'action': 'user_qiandao',
'nonce': nonce
}
# 发送签到请求
qiandao_response = session.post(qiandao_url, data=qiandao_data)
# 检查签到是否成功
if qiandao_response.status_code == 200 and '"status":"1"' in qiandao_response.text:
print("签到成功:", qiandao_response.json().get('msg'))
else:
print("签到失败")
结尾
最后我优化了一下,下面是成品
import requests
from bs4 import BeautifulSoup
import math
# 目标赞助币
goal_coin = 49
# 每次签到获得的赞助币
coin_per_signin = 0.3
# 模拟登录
session = requests.Session()
login_url = "https://www.xianyudanji.net/wp-admin/admin-ajax.php"
login_data = {
'action': 'user_login',
'username': ' ', #用户名
'password': ' ', #密码
'rememberme': '1'
}
response = session.post(login_url, data=login_data)
if response.status_code == 200 and '"status":"1"' in response.text:
print("登录成功")
else:
print("登录失败")
exit()
# 获取用户页面,包含余额和签到按钮
user_page = session.get('https://www.xianyudanji.net/user/aff')
# 解析页面,获取当前余额和签到按钮状态
soup = BeautifulSoup(user_page.text, 'html.parser')
# 获取当前余额(假设余额在 badge-warning-lighten 类中)
balance_span = soup.find('span', {'class': 'badge-warning-lighten'})
if balance_span:
current_balance = float(balance_span.text.strip()) # 提取当前余额,转换为 float 类型
print(f"当前赞助币余额: {current_balance}")
else:
print("无法获取当前余额")
exit()
# 计算到达目标的剩余天数
remaining_coin = goal_coin - current_balance
if remaining_coin <= 0:
print("已达到或超过目标金额")
else:
remaining_days = math.ceil(remaining_coin / coin_per_signin)
print(f"距离目标 {goal_coin} 赞助币,还需 {remaining_days} 天")
# 获取签到按钮并检查是否可以签到
qiandao_button = soup.find('button', {'class': 'go-user-qiandao'})
if 'disabled' in qiandao_button.attrs:
print("今日已签到,无法重复签到")
else:
# 提取 nonce 值
nonce = qiandao_button['data-nonce']
print(f"获取到的 nonce 值: {nonce}")
# 构建签到请求
qiandao_url = "https://www.xianyudanji.net/wp-admin/admin-ajax.php"
qiandao_data = {
'action': 'user_qiandao',
'nonce': nonce
}
# 发送签到请求
qiandao_response = session.post(qiandao_url, data=qiandao_data)
# 检查签到是否成功
if qiandao_response.status_code == 200 and '"status":"1"' in qiandao_response.text:
print("签到成功:", qiandao_response.json().get('msg'))
else:
print("签到失败")
收获
熟悉了一下request.Session的基本使用~
0 条评论