您的位置:首页 > 编程语言 > Python开发

Python项目:扇贝网小组查卡助手

2016-03-26 18:42 561 查看
扇贝网是一个非常棒的英语学习网站,大家还可以加入一些小组,一起交流学习、共同进步。但是,小组管理起来非常辛苦,尤其是在0点前踢出不打卡的成员,因此考虑利用程序来实现小组查卡自动化。

登录

操作扇贝网登录
URLhttp://www.shanbay.com/accounts/login/
方式POST
数据csrfmiddlewaretokenCSRF令牌
username用户名
password密码
CSRF令牌存在于Cookie中,我们需要先以GET方式访问该URL,就能取到CSRF令牌了。

# -*- coding: utf-8 -*-
import requests

class Shanbay():

def __init__(self, username, password):
self.request = requests.Session()
self.username = username
self.password = password

def login(self):
url = 'http://www.shanbay.com/accounts/login/'
r = self.request.get(url)
csrftoken = r.cookies['csrftoken']
data = {
'csrfmiddlewaretoken': csrftoken,
'username': self.username,
'password': self.password,
}
return self.request.post(url, data=data).ok


成员管理

如果我们获取小组管理后台所有组员的信息,比较费时间。考虑实际需求,不妨仅获取当天未打卡的组员的信息,这样能大大提高查卡效率。

踢人需要data-id,这个在小组管理后台页面就能获取到。但是,如果我们想发站内短信,就需要username,而username在小组管理后台页面里是没有的,这个需要查看个人打卡日记。

从个人打卡日记不仅能看到username,还能看到该贝友入组后最近已连续有多少天未打卡(这往往也是组规限定的内容)等等。

操作踢人
URLhttp://www.shanbay.com/api/v1/team/member/
方式PUT
数据 action动作('dispel')
idsdata-id
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
from Journal import Journal
import re

class Domain():

def __init__(self, shanbay):
self.shanbay = shanbay
self.request = shanbay.request

def get_not_checked_members(self):
'''
data_id          : 踢人时需要data_id
role             : 身份标识
nickname         : 昵称
user_id          : 发短信时需要user_id
username         : 用户名
points           : 贡献值
days             : 组龄
rate             : 打卡率
checked_yesterday: 昨天是否打卡
checked          : 今天是否打卡
off_dyas         : 入组后最近连续未打卡天数
'''
members = []
for page in range(1, 48):
html = self.request.get('http://www.shanbay.com/team/manage/?t=checkin_today&page=%d' % page).text
soup = BeautifulSoup(html, 'html5lib')
for member in soup.find_all('tr', class_='member'):
checked = member.find_all(class_='checked')[1].find('span').text.strip() == '已打卡'
if checked:
break
days = int(member.find(class_='days').text)
user_id = re.findall('\d+', member.find(class_='user').find('a')['href'])[0]
user = Journal(shanbay=self.shanbay, user_id=user_id)
checked_yesterday = member.find_all(class_='checked')[0].find('span').text.strip() == '已打卡'
if checked_yesterday:
off_days = 1
else:
off_days = user.get_off_days(days)
data = {
'data_id':member['data-id'],
'role':member['role'],
'nickname':member.find(class_='user').find('a').text,
'user_id':user_id,
'username':user.get_username(),
'points':int(member.find(class_='points').text),
'days':days,
'rate':float(member.find(class_='rate').find('span').text[:-2]),
'checked_yesterday':checked_yesterday,
'checked':checked,
'off_dyas':off_days
}
members.append(data)
else:
continue
break
return members

def dismiss(self, data_ids):
url = 'http://www.shanbay.com/api/v1/team/member/'
data = {
'action': 'dispel',
}
data['ids'] = ','.join(map(str, data_ids))
r = self.request.put(url, data=data)
return r.json()['msg'] == "SUCCESS"


(这里用到了Python跳出两层循环的技巧*^_^*)

打卡日记

通过打卡日记,我们可以获得一些基本信息,例如:用户名、最近连续未打卡天数等。

# -*- coding: utf-8 -*-

from bs4 import BeautifulSoup
import re
import datetime
import time

class Journal():

def __init__(self, shanbay, user_id):
self.shanbay = shanbay
self.request = shanbay.request
self.user_id = user_id
self.soup = self.__get_journal_soup()

def __get_journal_soup(self):
html = self.request.get('http://www.shanbay.com/checkin/user/%s/' % self.user_id).text
return BeautifulSoup(html)

def get_username(self):
return re.findall(u'(\w+)\s*的日记', self.soup.find_all(class_='page-header')[0].find('h2').text)[0]

def get_off_days(self, days=0):
date_arr = []
for a in self.soup.find_all(class_='target'):
mon, day, year = re.findall(u'(\S+)月\s*(\d+)\s*,\s*(\d+)', a.text)[0]
mon = mon.replace('十一', '11').replace('十二', '12').replace('一', '1').replace('二', '2').replace('三', '3').replace('四', '4').replace('五', '5').replace('六', '6').replace('七', '7').replace('八', '8').replace('九', '9').replace('十', '10')
date_arr.append(datetime.datetime(*(time.strptime('-'.join((year, mon, day)), '%Y-%m-%d'))[:3]))
today = datetime.datetime(*(time.localtime())[:3])
for day in range(0, days):
if today - datetime.timedelta(days=day) in date_arr:
return day
return days


站内短信

操作发送站内短信
URLhttp://www.shanbay.com/api/v1/message/
方式POST
数据recipient收件人(username)
subject标题
body内容
csrfmiddlewaretokenCSRF令牌
# -*- coding: utf-8 -*-

class Message():

def __init__(self, shanbay):
self.shanbay = shanbay
self.request = shanbay.request

def send_msg(self,recipient, subject, body):
url = 'http://www.shanbay.com/api/v1/message/'
data = {
'recipient': recipient,
'subject': subject,
'body': body,
'csrfmiddlewaretoken': self.request.cookies['csrftoken']
}
return self.request.post(url, data=data).ok


小组管理

操作设定加组条件
URLhttp://www.shanbay.com/team/setqualification/{team_id}
方式POST
数据value天数
kind类型
condition条件
team小组id
csrfmiddlewaretokenCSRF令牌
若需要在小组发帖或回帖,需要forum_id而不是小组id,而forum_id可以通过小组主页找到。

操作发帖
URLhttp://www.shanbay.com/api/v1/forum/{forum_id}/thread/
方式post
数据title标题
body内容
csrfmiddlewaretokenCSRF令牌
操作回帖
URLhttp://www.shanbay.com/api/v1/forum/thread/{post_id}/post/
方式POST
数据body内容
csrfmiddlewaretokenCSRF令牌
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup

class Team():

def __init__(self, shanbay, team_id):
self.shanbay = shanbay
self.request = shanbay.request
self.team_id = team_id
self.forum_id = self.__get_forum_id()

def set_join_limit(self, days, kind=2, condition='>='):
url = 'http://www.shanbay.com/team/setqualification/%s' % self.team_id
data = {
'value': days,
'kind': kind,
'condition': condition,
'team': self.team_id,
'csrfmiddlewaretoken': self.request.cookies['csrftoken']
}
r = self.request.post(url, data=data)
return 'http://www.shanbay.com/referral/invite/?kind=team' == r.url

def __get_forum_id(self):
html = self.request.get('http://www.shanbay.com/team/detail/%s/' % str(self.teamId)).text
soup = BeautifulSoup(html)
return soup.find(id='forum_id')['value']

def new_post(self, title, content):
url = 'http://www.shanbay.com/api/v1/forum/%s/thread/' % self.forum_id
data = {
'title': title,
'body': content,
'csrfmiddlewaretoken': self.request.cookies['csrftoken']
}
return self.request.post(url, data=data).json()

def reply_post(self, post_id, content):
url = 'http://www.shanbay.com/api/v1/forum/thread/%s/post/' % post_id
data = {
'body': content,
'csrfmiddlewaretoken': self.request.cookies.get('csrftoken')
}
return self.request.post(url, data=data).json()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: