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

扇贝网是一个非常棒的英语学习网站,大家还可以加入一些小组,一起交流学习、共同进步。但是,小组管理起来非常辛苦,尤其是在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):
        pass

站内短信

操作发送站内短信
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()

Python

上一篇 Ubuntu搭建Ruby on Rails环境
下一篇 【实验楼】HBASE教程——学习笔记

添加新评论

*
*