前段时间通过活动获得了pptv3个月的会员,有了会员偶尔看下动漫、收费电影还是不错的,免去了广告的干扰,pptv还可以通过积分兑换会员,每天签到获可以取积分,为了避免繁复的每天签到,因而写了一个脚本进行签到,将签到任务交给计算机去完成。 脚本很简单,使用python3编写,requests库进行网络请求操作。
签到:
要实现签到首先要实现登录,登录后才能获取到用户的凭证,再chrome中打开pptv并进行登录,通过浏览器的开发者工具(F12)记录浏览器发送的请求。
在点击登录后可以看到向https://passport.pptv.com/v3/login/login.do这个地址发送了一次get请求,可以判定这就是pptv的登录入口,因为pptv使用的是get请求,可以很容易将request url部分内容复制过来,在浏览器的地址栏中输入这串地址,得到请求返回的内容。
登录返回了两个重要的参数:username和token,token和cookie是最常见的登录信息,具体使用cookie或是token,需要分析签到的http请求,前面的jQuery18307559810754289582_1483115348288有什么作用?仔细看看format参数为jsonp,这是jsonp的一种常见格式,使用了jsonp估计是为了实现跨域资源访问,也解释了为什么登录使用get请求而不是常用的post,经测试,尝试将jsonp改为json同样可以正常实现登录,而且返回的是标准的json数据,在进行登录时必须的只需format、username、password三个参数,就可通过脚本进行模拟登录。
import requests
login_url = 'https://passport.pptv.com/v3/login/login.do'
# 请求参数
login_params = {
'format': 'jsonp',
'username': 'your name or email',
'password': 'your password'
}
# 构造一个get请求
resp = requests.get(login_url, login_params)
# 获取到用户信息并解析成一个字典
user_info = resp.json()['result']
登录信息已经获取了,下一步就是分析签到的http请求,使用同样的方法获知签到所触发的请求:http://api.usergrowth.pptv.com/doDailyPcard
该次请求携带username、token、from、format等参数,但其中还有index、add_str两个参数不清楚从哪里来,暂时认为这两个参数不需要,通过去除部分参数进行请求,知道username、token、format、version、from、index、addstr这些参数是必须的,现在username、token可以通过登录后获取,format、version参数直接复制过来就行,经尝试format参数的值同样可以设置为json,这样返回的是一个容易处理的json数据,index、addstr两个参数不能随便填写,为了得知index、addstr的生成方式和作用,通过chrome的开发者工具分析html源码。
可以看到触发了docard这个方法进行签到处理,在浏览器的console中输入docard便可以查看该方法的源码,得到下面一段代码:
window.docard = function() {
var index = "";
for (var i = 0; i < 6; i++) {
var nu = Math.floor(Math.random() * 10);
if (nu == 0) {
nu = 1;
}
index += nu;
}
var doDailyPcardurl = "http://api.usergrowth.pptv.com/doDailyPcard?username=" + mylogin.username + "&from=web&version=unknown&index=" + index + "&addstr=" + md5.hex_md5(encodeURIComponent(mylogin.username + "$DAILY_PCARD$" + index)) + "&format=jsonp&cb=?&token=" + mylogin.token;
$.getJSON(doDailyPcardurl, function(data) {
if (data["flag"] == "0") {
var getJifen = data["result"]["obtainAward"].match(/\d+/)[0];
$(".id-center-ui-getnum").html("+" + getJifen);
$("#nosign").hide();
$("#signed").fadeIn();
$(".id-center-ui-getnum").animate({
"opacity": "1",
"top": "0px"
});
} else {
console.log("dakashibai");
}
});
}
可以看到index其实是一个随机的6位数字组成的字符串
addstr=" + md5.hex_md5(encodeURIComponent(mylogin.username + "$DAILY_PCARD$" + index))
addstr是通过hex_md5编码后的字符串,这是网站常用的校验方式,将特定信息与随机数合并进行一次编码,可以达到避免敏感信息泄露的效果,看来是要在脚本中构造一个index和对应的addstr才能正常发起请求,机智的我直接将这次请求中的index、addstr当作请求,因为index就是一个随机数,也不涉及到服务器端的额外校验信息,代码如下:
import urllib.parse
signed_url = 'http://api.usergrowth.pptv.com/doDailyPcard'
# 因为之前返回的token其实是经过url编码后端token,所以需要先解码
signed_params = {
'username': user_info['username'],
'token': urllib.parse.unquote(user_info['token']),
'format': 'jsonp',
'from': 'client',
'version': 'unknown',
'index': 756429,
'addstr': 'e68e5a53b9467f4a739f009c6e351de1'
}
signed_resp = requests.get(signed_url, signed_params)
至此,签到的脚本已完成。
脚本自动执行:
为了实现自动签到,需要在系统中注册定时任务让签到脚本在每天运行,*nix系统中可以使用crontab控制脚本的执行,使用crontab -e对crontab配置文件进行编辑。
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
# 设定每天晚上9点执行签到
# /usr/bin/python 根据安装的python的路径填写, 如果使用了虚拟环境则根据相应的python路径填写
0 21 * * * /user/bin/python /path/to/your/script
配置好之后,在终端输入crontab -l 验证是否正确添加到定时任务,这样系统会在每天执行签到的脚本,就实现了每天定时签到,前提是系统在这个时间点出于运行状态,一般会将程序放在vps或者支持openwrt之类系统的路由器之类7*24小时运行的机器上,如果每天都需要启动系统,可以将脚本设置为开机或者登录时执行,在windows下则可以通过计划任务程序图形化进行配置。
好久没写文章了,随便写下,没技术含量。源码地址