Esempio n. 1
0
def http_post(url: str, data: dict):
    """
    发送 post 请求
    :param url:
    :param data:
    :return:
    """
    http_session = session()
    http_session.headers = {'Cookie': g.bus_user.bus_session, 'user-agent': get_user_agent()}

    try:  # 发送请求
        response = http_session.post(url, data=data, allow_redirects=False)
    except OSError:
        raise NFUError('学校车票系统错误,请稍后再试')

    try:  # 处理返回的数据
        response = loads(response.text)
    except decoder.JSONDecodeError:

        if response.status_code == 200:
            raise NFUError('学校车票系统错误,请稍后再试')

        if g.refresh:
            __refresh()
            g.refresh = False
            return http_post(url, data)

    return response
Esempio n. 2
0
def get_jw_token(student_id: int, password: str = '', count: int = 0) -> str:
    """
    登陆教务系统
    :param count:
    :param student_id: 学号
    :param password: 密码,默认为空字符串
    :return token:
    """

    url = 'http://ecampus.nfu.edu.cn:2929/jw-privilegei/User/r-login'
    data = {'username': student_id, 'password': password, 'rd': ''}

    try:
        response = post(url, data=data, timeout=10)
        token = loads(response.text)['msg']
    except (OSError, decoder.JSONDecodeError):
        if count >= 5:
            raise NFUError('教务系统登录接口错误,请稍后再试')
        else:
            return get_jw_token(student_id, password, count + 1)

    if not token:
        raise NFUError('学号或密码错误!')

    return token
Esempio n. 3
0
def get_total_achievement_point(token: str, count: int = 0) -> dict:
    """
    获取学分、成绩的总体情况
    :param count:
    :param token:
    :return:
    """

    url = 'http://ecampus.nfu.edu.cn:2929/jw-amsi/AmsJxbXsZgcj/listXs'
    data = {
        'deleted': False,
        'pageSize': 65535,
        'id': get_actual_id(token),
        'jwloginToken': token
    }

    try:
        response = post(url, data=data, timeout=10)
        data = loads(response.text)['msg']['list'][0]
    except (OSError, KeyError, decoder.JSONDecodeError):
        if count >= 5:
            raise NFUError('教务系统绩点接口错误,请稍后再试')
        return get_total_achievement_point(token, count + 1)

    if not data:
        if count >= 5:
            raise NFUError('没有获取到数据,请稍后再试')
        return get_total_achievement_point(token, count + 1)

    return {
        'selected_credit': data['yxxf'],
        'get_credit': data['yhdxf'],
        'average_achievement': data['avg'],
        'average_achievement_point': data['avgJd']
    }
Esempio n. 4
0
def get_student_name(student_id: int, password: str) -> str:
    """
    与教务系统校对账号密码,并获取学生姓名

    - 字段说明
        - username 学号
        - password 密码
        - rd 随机数,可以随机,也可以不填,我也不知道来干嘛的

    :param student_id: 学号
    :param password: 教务系统的密码
    :return name:
    """

    token = get_jw_token(student_id, password)
    url = 'http://ecampus.nfu.edu.cn:2929/jw-privilegei/User/r-getMyself'
    data = {'jwloginToken': token}

    try:
        response = post(url, data=data, timeout=10)
        name = loads(response.text)['msg']['name']
    except (OSError, KeyError):
        raise NFUError('实名验证错误,请稍后再试')

    if not name:
        raise NFUError('没有获取到数据,请稍后再试')

    return name
Esempio n. 5
0
def get_ticket_ids(order_id: int) -> dict:
    """
    因为一个订单里面可能有多张车票,所以我们爬取一下车票号
    :param order_id: 订单id
    :return:
    """

    url = 'http://nfuedu.zftcloud.com/campusbus_index/order/refund_ticket.html'
    params = {'order_id': order_id}
    response = http_get(url, params)

    route, date = get_route(response.text)

    ticket_list = []

    ticket_data = findall(r'<span class="title_name title_w">.+\n.+\n.+\n.+\n.+', response.text)

    try:
        price = search(r'<span class="fare">\d+</span>', response.text).group()[19:-7]
    except AttributeError:
        raise NFUError('学校车票系统错误,请稍后再试')

    for ticket in ticket_data:

        try:
            name = search(r'w">.+<s', ticket).group()[3:-9]
            phone = search(r'<span class="title_iphone">\d+</span>', ticket).group()[27:-7]

        except AttributeError:
            raise NFUError('学校车票系统错误,请稍后再试')

        try:
            ticket_id = search(r', \d+', ticket).group()[2:]
        except AttributeError:
            ticket_list.append({
                'state': '已退票',
                'name': name,
                'phone': phone
            })
        else:
            ticket_list.append({
                'state': f'{price}¥',
                'name': name,
                'phone': phone,
                'ticketId': ticket_id
            })

    return {
        'route': route,
        'date': date,
        'passengerList': ticket_list
    }
Esempio n. 6
0
def validate_token(token: str, token_type: str = 'ACCESS_TOKEN') -> dict:
    """
    验证令牌
    :param token: 令牌
    :param token_type: 令牌类型
    """
    s = TimedJSONWebSignatureSerializer(getenv(token_type))
    try:
        data = s.loads(token)
    except SignatureExpired:
        raise NFUError('签名已过期', code='1001')
    except BadSignature:
        raise NFUError('签名错误', code='1001')
    else:
        return data
Esempio n. 7
0
def get_token() -> str:
    """
    从请求头获取token
    :return:
    """

    try:
        token_type, token = request.headers['Authorization'].split(None, 1)
    except (KeyError, ValueError):
        raise NFUError('请重新登录', code='1001')

    if token == 'null' or token_type.lower() != 'bearer':
        raise NFUError('请重新登录', code='1001')

    return token
Esempio n. 8
0
def get_profile(student_id: int, token: str, count: int = 0):
    grade = int(f'20{str(student_id)[:2]}')
    student_data = get_student_data(token)

    url = 'http://ecampus.nfu.edu.cn:2929/jw-srsi/SrsFjflStudent/r-getZyfxRecByJbzlId'
    data = {'id': student_data['actualId'], 'jwloginToken': token}

    try:
        response = post(url, data=data, timeout=10)
        data = loads(response.text)
    except (OSError, decoder.JSONDecodeError):
        if count >= 5:
            raise NFUError('教务系统专业接口繁忙')
        return get_profile(student_id, token, count + 1)

    try:
        profile = data['msg']

    except KeyError:
        return {
            'grade': grade,
            'college_id': student_data['xyid'],
            'profession_id': student_data['zyid'],
            'direction': '未分专业方向'
        }

    else:
        return {
            'grade': grade,
            'college_id': student_data['xyid'],
            'profession_id': student_data['zyid'],
            'direction': profile['zyfxmc']
        }
Esempio n. 9
0
def get_pay_order(order_id: int, ) -> dict:
    """
    获取订单的支付数据
    :param order_id:
    :return:
    """
    url = f'http://nfuedu.zftcloud.com/campusbus_index/order/notpay_order/order_id/{order_id}.html'
    response = http_get(url)

    route, date = get_route(response.text)

    try:
        names = findall(r'<span class="title_name title_w">\D+</span>', response.text)
        phones = findall(r'<span class="title_iphone">\d+</span>', response.text)
        trade_no = search(r'var tradeNo = .+', response.text).group()[15:-2]
        price = search(r'¥<span>\d+</span>', response.text).group()[7:-7]
    except AttributeError:
        raise NFUError('学校车票系统错误,请稍后再试')

    # 把乘客信息处理成一个列表
    passengers = []
    for i, name in enumerate(names):
        passengers.append({
            'name': name[33:-7],
            'phone': phones[i][27:-7]
        })

    return {
        'route': route,
        'date': date,
        'passengers': passengers,
        'price': price,
        'alipayUrl': get_alipay_url(trade_no),
        'alipayQrUrl': f"{getenv('API_URL')}/school-bus-pro/alipay/qrcode?tradeNo={trade_no}"
    }
Esempio n. 10
0
def __refresh() -> None:
    """
    刷新 车票session
    :return:
    """
    http_session = session()
    http_session.headers = {'user-agent': get_user_agent()}
    url = 'http://nfuedu.zftcloud.com/campusbus_index/ticket_checked/index'
    params = {
        'school_code': 11557,
        'alipay_user_id': g.bus_user.alipay_user_id,
        'idcard': g.bus_user.id_card,
        'avatar': g.bus_user.avatar,
        'phone': '',
        'real_name': g.user.name
    }

    try:  # 发送请求
        http_session.get(url, params=params)
    except OSError:
        raise NFUError('学校车票系统错误,请稍后再试')

    # 把新的session写入MySql
    g.bus_user.bus_session = f"PHPSESSID={http_session.cookies['PHPSESSID']}"
    db.session.add(g.bus_user)
    db.session.commit()
Esempio n. 11
0
def get_bus_schedule(route_id: int, date: list) -> dict:
    """
    若日期在车票预售期内,获取班车时刻表。

    - 字段说明
        - route_id 路线id:南苑 -> 河堤公园:21,
                          河堤公园 -> 南苑:22,
                          南苑 -> 中大南校区:13,
                          中大南校区 -> 南苑:14

        - time     乘车日期

    :param route_id: 校车路线
    :param date: 乘车日期
    :return:
    """

    url = 'http://nfuedu.zftcloud.com/campusbus_index/ticket/show_schedule.html'
    params = {
        'route_id': route_id,
        'time': date
    }
    response = http_get(url, params)

    try:
        data = loads(search(r'var msg = .+', response.text).group()[10:-1])
    except (AttributeError, decoder.JSONDecodeError):
        raise NFUError('学校车票系统错误,请稍后再试')
    else:
        return data
Esempio n. 12
0
def get_achievement_list(token: str,
                         school_year: int,
                         semester: int,
                         count: int = 0) -> list:
    """
    获取成绩单
    :param count:
    :param token:
    :param school_year:
    :param semester:
    :return:
    """

    url = 'http://ecampus.nfu.edu.cn:2929/jw-amsi/AmsJxbXsZgcj/r-list'
    data = {
        'deleted': False,
        'pg': 1,
        'pageSize': 50,
        'kkxn': school_year,
        'xnxq': semester,
        'jwloginToken': token
    }

    try:
        response = post(url, data=data, timeout=10)
    except OSError:
        if count >= 5:
            raise NFUError('教务系统成绩接口错误,请稍后再试')
        else:
            return get_achievement_list(token, school_year, semester,
                                        count + 1)

    try:
        course = loads(response.text)['msg']
    except (KeyError, decoder.JSONDecodeError):
        if count >= 5:
            raise NFUError('教务系统错误,请稍后再试')
        else:
            return get_achievement_list(token, school_year, semester,
                                        count + 1)

    try:
        course = course['list']
    except KeyError:
        raise NFUError(course)

    return course
Esempio n. 13
0
    def __set_wechat_pay(self, json_data, signature) -> tuple:
        """
        设置支付方式为微信支付

        返回 json、signature 为向支付页面 post 的 body
        只要设置好创建订单数据的 cookie,并重定向回安心付支付接口,即可调用安心付支付接口
        学校安心付接口为 post 提交,但后端并无验证,故 body 数据在 url 带上并重定向即可

        - 字段说明
            - json json_data
            - signature signature
            - payChannel 设置为微信支付

        :param json_data: ready_pay 返回的订单数据
        :param signature: ready_pay 返回的数字签名
        """

        url = 'http://nfu.zhihuianxin.net/paycenter/gateway_web'
        data = {'json': json_data, 'signature': signature}
        header = {'Referer': 'http://nfu.zhihuianxin.net/electric/pay/doPay'}

        try:
            # 向安心付接口 post 订单数据,无需返回值
            self.__http_session.post(url, data=data, headers=header)
        except OSError:
            raise NFUError('与安心付服务器连接超时,请稍后再试')

        url = 'http://nfu.zhihuianxin.net/paycenter/payGateway_web'
        data = {'payChannel': 'WxPay'}
        header = {
            'Referer': 'http://nfu.zhihuianxin.net/paycenter/gateway_web'
        }

        try:
            response = self.__http_session.post(url, data=data, headers=header)
        except OSError:
            raise NFUError('与安心付服务器连接超时,请稍后再试')

        try:
            json_data = search(r'name="json" value=.+',
                               response.text).group()[19:-5]
            signature = search(r'name="signature" value=.+',
                               response.text).group()[24:-5]
        except AttributeError:
            raise NFUError('与安心付服务器连接超时,请稍后再试')

        return json_data, signature
Esempio n. 14
0
def verification_code(code: int) -> None:
    """
    验证验证码
    :return:
    """

    r = Redis(host='localhost', password=getenv('REDIS_PASSWORD'), port=6379)

    try:
        if int(r.get(g.user.id)) == code:

            # 删除缓存中的数据
            r.delete(g.user.id)

        else:
            raise NFUError('验证码错误', code='2001')

    except TypeError:
        raise NFUError('验证码错误', code='2001')
Esempio n. 15
0
    def __ready_pay(self) -> tuple:
        """
        准备支付,获取智能电表签名

        - 字段说明
            - amt 充值金额
            - custNo 学生学号
            - custName 学生姓名
            - roomId 房间号
            - areaName 学校名字,写死南方学院就行
            - architectureName 宿舍楼
            - floorName 楼层
            - roomName 楼号
        """

        url = 'http://nfu.zhihuianxin.net/electric/pay/doPay'
        data = {
            'amt': self.amount,
            'custNo': self.user_id,
            'custName': self.name,
            'roomId': self.room_id,
            'areaName': '南方学院',
            'architectureName': self.building,
            'floorName': self.floor,
            'roomName': self.room
        }

        try:
            response = self.__http_session.post(url, data=data, timeout=1)
        except OSError:
            raise NFUError('与安心付服务器连接超时,请稍后再试')

        try:
            # 尝试获取签名
            json_data = search(r'name="json" value=.+',
                               response.text).group()[19:-4]
            signature = search(r'name="signature" value=.+',
                               response.text).group()[24:-4]
        except AttributeError:
            raise NFUError('与安心付服务器连接超时,请稍后再试')

        return json_data, signature
Esempio n. 16
0
def get_passenger_data() -> list:
    """
    获取乘车人数据
    :return:
    """
    url = 'http://nfuedu.zftcloud.com/campusbus_index/my/passenger_puls.html'
    response = http_get(url)

    try:
        passenger = loads(search(r'var passenger = .+', response.text).group()[16:-1])
    except (AttributeError, decoder.JSONDecodeError):
        raise NFUError('学校车票系统错误,请稍后再试')
    else:
        return passenger
Esempio n. 17
0
def get_electric_log(room_id: int, page_index: int) -> dict:
    """
    电费充值记录
    :param room_id:
    :param page_index:
    :return:
    """
    url = 'http://nfu.zhihuianxin.net/electric/order/page'
    data = {'ammeterId': room_id, 'pageIndex': page_index, 'pageSize': 10}

    try:
        response = post(url, data=data, timeout=1)
        electric_create = loads(response.text)['data']
    except (OSError, KeyError, decoder.JSONDecodeError):
        raise NFUError('安心付服务器错误')

    return electric_create
Esempio n. 18
0
def return_ticket(order_id: int, ticket_id: int) -> str:
    """
    退票

    :param order_id: 订单id
    :param ticket_id: 车票id
    :return:
    """

    url = 'http://nfuedu.zftcloud.com/campusbus_index/order/refund_ticket.html'

    data = {'order_id': order_id, 'ticket_id': ticket_id}

    response = http_post(url, data)

    if response['code'] != '0000':
        raise NFUError(response['desc'])

    return response['desc']
Esempio n. 19
0
def get_route(response):
    """
    从html中获取路径数据
    :param response:
    :return:
    """
    try:
        route = '{} -> {}'.format(
            search(r'<span class="site_from">.+</span>', response).group()[24:-7],
            search(r'<span class="site_to">.+</span>', response).group()[22:-7]
        )
        date = '{} {}'.format(
            search(r'<span class="time_go">\S+</span>', response).group()[22:-7],
            search(r'<span class="time_day">\S+</span>', response).group()[23:-7]
        )
    except AttributeError:
        raise NFUError('学校车票系统错误,请稍后再试')

    return route, date
Esempio n. 20
0
def get_student_data(token: str, count: int = 0) -> dict:
    """
    获取学生信息
    :param token:
    :param count:
    :return:
    """
    url = 'http://ecampus.nfu.edu.cn:2929/jw-privilegei/User/r-getMyself'
    data = {'jwloginToken': token}

    try:
        response = post(url, data=data, timeout=10)
        data = loads(response.text)['msg']

    except (OSError, KeyError, decoder.JSONDecodeError):
        if count >= 5:
            raise NFUError('教务系统专业接口繁忙')
        return get_student_data(token, count + 1)

    return data
Esempio n. 21
0
def create_order(passenger_ids: str, connect_id: int, schedule_id: int,
                 date: str, take_station: str) -> dict:
    """
    创建车票订单

    支付宝H5开发文档,支付篇:
    https://myjsapi.alipay.com/alipayjsapi/util/pay/tradepay.html

    :param passenger_ids: 乘客id
    :param connect_id: 联系人id
    :param schedule_id: 班车id
    :param date: 日期
    :param take_station: 乘车车站
    :return: 错误信息,或订单数据
    """

    url = 'http://nfuedu.zftcloud.com/campusbus_index/order/create_order.html'
    data = {
        'passenger_ids': passenger_ids,
        'connect_id': connect_id,
        'schedule_id': schedule_id,
        'date': date,
        'take_station': take_station,
        'seat_num': ''  # 此数据为座位号,抢票要什么座位要求,直接为空
    }

    response = http_post(url, data)

    if not response['code'] == '10000':
        raise NFUError(response['desc'], code=response['code'])

    return {
        'tradeNo': response['trade_no'],
        'outTradeNo': response['out_trade_no'],
        'orderId': response['order_id']
    }
Esempio n. 22
0
def http_get(url: str, params=None):
    """
    发送 get 请求
    :param url:
    :param params:
    :return:
    """
    http_session = session()
    http_session.headers = {'Cookie': g.bus_user.bus_session, 'user-agent': get_user_agent()}

    try:  # 发送请求
        response = http_session.get(url, params=params, allow_redirects=False)

        if response.status_code != 200 and g.refresh:
            __refresh()

            # 防止递归死循环
            g.refresh = False
            return http_get(url, params)

    except OSError:
        raise NFUError('学校车票系统错误,请稍后再试')

    return response
Esempio n. 23
0
def get_ticket_data(order_id: int) -> tuple:
    """
    获取电子票的数据

    - 字段说明
        road_from       始发车站
        road_to         终点站
        year            乘车年份
        week            乘车星期
        time            发车时间
        bus_id          班车号
        take_station    乘车车站

    :param order_id: 订单id
    :return bus_data: 班车数据,同个订单,统一即可
    :return ticket: 车票数据
    :return javascript: 处理车票的js,动态生成js,实在是太骚了。
    """

    url = 'http://nfuedu.zftcloud.com/campusbus_index/order/ticket.html'
    params = {'order_id': order_id}
    response = http_get(url, params)

    try:
        bus_data = {
            'roadFrom':
            search(r'<span class="road_from">.+', response.text).group()[:-1],
            'roadTo':
            search(r'<span class="road_to">.+', response.text).group()[:-1],
            'year':
            search(r'<span class="data_y">.+', response.text).group()[:-1],
            'week':
            search(r'<span class="data_week">.+', response.text).group()[:-1],
            'time':
            search(r'<span class="data_hm">.+', response.text).group()[:-1],
            'busId':
            search(r'<div class="data_bc">.+', response.text).group()[:-1],
            'takeStation':
            search(r'上车点:.+', response.text).group()[:-5]
        }
        javascript = search(r'<script>.+</script>', response.text, S).group()

    except AttributeError:
        raise NFUError('学校车票系统错误,请稍后再试')

    ticket_ids = findall(r'<p class="erwei_num">电子票号:.+', response.text)
    passengers = findall(
        r'<p class="erwei_num erwei_c"..style="text-align: center;text-indent:0.2.+',
        response.text)
    seats = findall(
        r'<p class="erwei_num erwei_c" style="text-align: center;text-indent:.5rem;">座.+',
        response.text)

    ticket = []

    for i, ticket_id in enumerate(ticket_ids):
        ticket.append({
            'ticketId': ticket_id[:-1],
            'passenger': passengers[i][:-1],
            'seat': seats[i][:-1]
        })

    return bus_data, ticket, javascript
Esempio n. 24
0
def get_class_schedule(token: str,
                       school_year: int,
                       semester: int,
                       count: int = 0) -> list:
    """
    向教务系统请求课程表数据

    :param count:
    :param token:
    :param school_year:
    :param semester:
    :return:
    """
    course_data = []
    url = 'http://ecampus.nfu.edu.cn:2929/jw-cssi/CssStudent/r-listJxb'
    data = {'xn': school_year, 'xq': semester, 'jwloginToken': token}

    try:
        response = post(url, data=data, timeout=10)
        course_list = loads(response.text)['msg']
    except (OSError, KeyError, decoder.JSONDecodeError):
        if count >= 5:
            raise NFUError('教务系统课程表接口错误,请稍后再试')
        else:
            return get_class_schedule(token, school_year, semester, count + 1)

    # 判断获取的数据是否是列表,如果不是列表,可能教务系统又炸了
    if not isinstance(course_list, list):
        if count >= 5:
            raise NFUError('教务系统错误,请稍后再试')
        else:
            return get_class_schedule(token, school_year, semester, count + 1)

    for course in course_list:  # 循环所有课程
        for merge in course['kbMergeList']:  # 课程可能有不同上课时间,循环取出

            teacher = []
            for teacher_list in merge['teacherList']:
                teacher.append(teacher_list['xm'])

            try:
                course_data.append({
                    'course_name':
                    course['name'],
                    'subdivision_type':
                    course['l3mc'],
                    'course_id':
                    course['pkbdm'],
                    'credit':
                    float(course['kcxf']),
                    'teacher':
                    teacher,
                    'classroom':
                    merge['classroomList'][0]['jsmc'],
                    'weekday':
                    merge['xq'],
                    'start_node':
                    merge['qsj'],
                    'end_node':
                    merge['jsj'],
                    'start_week':
                    merge['qsz'],
                    'end_week':
                    merge['jsz']
                })
            except IndexError:
                course_data.append({
                    'course_name': course['name'],
                    'subdivision_type': course['l3mc'],
                    'course_id': course['pkbdm'],
                    'credit': float(course['kcxf']),
                    'teacher': teacher,
                    'classroom': '未分配教室',
                    'weekday': merge['xq'],
                    'start_node': merge['qsj'],
                    'end_node': merge['jsj'],
                    'start_week': merge['qsz'],
                    'end_week': merge['jsz']
                })

    course_data.sort(key=lambda x: x['course_id'])
    return course_data