扇贝登录,不需要处理验证码,这一点使得该脚本简单许多
import requests
import random
import json
模拟浏览器,扇贝新闻PC端和移动端的阅读模式不同
headers = {'User-Agent': "Mozilla/5.0 (Windows NT 6.1; rv:49.0)
Gecko/20100101 Firefox/49.0",
'Referer': "https://www.shanbay.com/accounts/login/"}
登录链接
login_url = 'https://www.shanbay.com/accounts/login'
获得首页新闻列表的链接
news_list_url = 'http://www.shanbay.com/api/v1/read/news/?page=1'
完成某篇新闻阅读后需要post数据的链接,{}为该篇新闻的id
finish_url = 'https://www.shanbay.com/api/v1/read/article/user/{}/'
打卡链接
checkin_url = "http://www.shanbay.com/api/v1/checkin/?for_web=true"
def login(username, password):
#创建Session对象,该对象会自动保存cookie信息
s = requests.Session()
# 首先获得登录表单的csrftoken,这个在提交用户账号和密码的时候要一起提交
csrftoken = s.get(login_url).cookies['csrftoken']
login_form_data = {'username': username,
'password': password,
'csrfmiddlewaretoken': csrftoken
}
# s,即session里保存了cookie信息,下面的post之后,s中会添加更多认证信息,包括auth_token,之后用s访问其他页面
res = s.post(login_url, data=login_form_data, headers=headers)
return s```
def get_unfinished_news(s, num):
# 每天要阅读一定数量的新闻后才能打卡,这里就是要获得首页中尚未阅读过的新闻,num指今天要完成的新闻阅读篇数
# 通过保存了cookie信息的Session对象s访问news_list_url可以获得首页的新闻列表
news_list = s.get(news_list_url)
# 获得的数据是json格式的,所有的news信息都在data这个key里,为了便于处理,将其转化为python的dict对象
news_list = json.loads(news_list.text)['data']
news_id_list = []
for news in news_list:
# 先保存其中没有阅读过的news,同时保存min_used_seconds字段,稍后可根据该字段的值估计每篇文章的阅读时间,这个值是news单词数的两倍
if news['is_finished'] is False:
# 设置一下我们完成一篇news的阅读所需要的时间,这里我简单做了两倍的处理
my_used_seconds = news['min_used_seconds']*2
news_id_list.append((news['id'], my_used_seconds))
# 首页中未阅读过的news大概有10篇,我们没必要读完10篇,这里根据设定的num值获得前num篇,当然num>2
return news_id_list[:num]
def shanbay_auto_checkin(username, password, num:int):
# form_data 为提交的完成阅读信息
s = login(username, password)
unfinished_news = get_unfinished_news(s, num)
if not unfinished_news:
print('Checkin Failed! The news of first_page already were finished...')
return
for news_id, my_used_seconds in unfinished_news:
# 通过浏览器的抓包工具观察,扇贝对于每篇新闻是按照分页后每一页分别post数据的,
# 前面的分页都有三个字段,只有最有一个分页有如下两个字段,经测试,我们可以直接post最后页的数据
finished_form_data = {'operation': 'finish',
'used_time': my_used_seconds}
# 注意这里用的是put方法,至于用哪种http方法,可以通过浏览器的抓包工具查看每次请求的method和要提交的表单数据
read_res = s.put(finish_url.format(news_id), data=finished_form_data)
# 根据返回的状态码,判断完成阅读信息是否成功put
try:
if read_res.json()['status_code'] == 0:
print('Finished_news_id:{};Used_seconds:{}'.format(news_id, my_used_seconds))
else:
print('news_id:{};reading failed!'.format(news_id))
except KeyError:
print(read_res)
print('Please check your username or password!')
checkin_res = s.post(checkin_url, headers=headers)
# 这里判断是否打卡成功,一天只能打卡一次,如果已打卡一次,第二次执行该脚本时虽然完成阅读,但不能打卡
if checkin_res.json()['status_code'] == 0:
print('Checkin successfully')
else:
print('Checkin Failed! Maybe you already have a checkin...')
if __name__ == '__main__':
username = '你的用户名'
password = '密码'
num = random.randint(3, 6) #这里设置每天随机阅读3-6篇
shanbay_auto_checkin(username, password, num)
在上面输入自己的扇贝账号及密码,然后用python3执行该脚本
之后可登录扇贝中心验证一下是否成功打卡!
总结:
整个过程可分为一下几步:
1.登录验证,获得session,它包含每次请求所需的cookie等信息
2.访问新闻首页获得当天未阅读过的新闻列表,从中随机选择3-6篇
3.对于2中获得的每篇news,根据其要求的最少阅读时间,构造表单数据,
put到finish_url,这样就完成该篇news的阅读任务
4.用post方式访问一下打卡链接就可以完成打卡了
存在的问题:
上述第二步只是获得了首页中未阅读的文章,但是如果将来有几天扇贝新闻首页不更新的话,就需要更改news_list_url,使其能自动获取page=2、page=3...的新闻列表,但是通过浏览器可发现第三页访问的url类似这样多了两个参数
/api/v1/read/article/news/?ipp=15&page=3&_=1478573514739,还没有考虑到这个。。。
参考:
https://github.com/ukiy2010/shanbay_auto_checkin
https://github.com/ColdinLee/shanbay
最后提醒,本文只是学习之用,并不鼓励大家利用脚本自动打卡,有什么问题欢迎交流~
更新(2017/01/20):
扇贝登录方式变了,现在的登录流程大概是这样的,在https://www.shanbay.com/web/account/login/ 填写表单,然后提交用户名密码到https://www.shanbay.com/api/v1/account/login/web/ 这个api,请求方式为put,只需要用户名和密码:
现需要改变上面的login函数:
def login(username, password):
s = requests.Session()
# 这里也需要创建一个session对象,下面的put之后,s中会保存一些认证信息,包括auth_token、sessionid等,之后用s访问其他页面会带上这些认证信息
login_form_data = {'username': username,
'password': password,
}
ress = s.put(login_url, data=login_form_data)
print(ress.json())
print(s.cookies)
return s
这样就可以了继续打卡了!
有时候不小心登录失败后,之后登录就需要验证码,查看浏览器cookies会发现里面多了个
是这样的,第一次登录失败,服务器会在后台存入一个标识符(这个用户需要验证码),然后返回给客户端catpcha_needed=True,存在浏览器的cookies里,这个键值对的作用是在登录页面要不要弹出验证码的框框,下一次登录时,服务器根据用户名密码找到那个标识符判断是否需要验证验证码,然后会检查随着用户名和密码提交的数据中是否含有验证码及验证码是否正确,
直接改cookies里的catpcha_needed=False是没有用的:
登录还是会失败:
打印session看看里面到底有什么,
发现有一个verify=True,那将其改为False试试吧