天天看點

基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務

本文僅用于學習用途,轉載請注明出處

關鍵詞

python、fiddler抓包、伺服器、我在校園、HTTP

0-引言

因學校要求,班委需提醒未完成打卡同學打卡,否則扣除德育分,影響德育成績。是以為實作班委我在校園的自動化管理,嘗試使用python編寫一個爬蟲程式挂靠在伺服器運作,實作每天的自動提醒管理。

經前期搜尋,網際網路上的我在校園爬蟲未涉及班委的自動化管理,且僅僅通過token或者JWSESSION實作登入,時效性不好且操作麻煩。例如github上面的我在校園自動簽到程式,通過token值實作簽到,但現已經停止維護,且token值登入已經被我在校園登入給禁止。csdn和部落格園的部分文章僅僅涉及通過抓包擷取JWSESSION實作登入簽到,但是有效期不長。

1-總流程圖

基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務

2.1-抓包解析過程

部分關鍵資訊已經打碼

打開fiddler和我在校園小程式,登入,抓取到登入資訊如下

基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務
基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務

由其中發現,我在校園登入是通過url中的符号 ? 來實作傳值的,由于登入的時候沒有後面的openid等值,猜測傳入賬号和密碼就可以實作登入。

經檢驗,猜測正确。

按照正常流程進入班級管理界面,依次進入日漸日報管理和班級簽到管理,而後檢查抓包資訊

我在校園班級管理界面

基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務

日檢日報界面

基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務

同理進入簽到頁面檢查,發現出入的參數有一個id

基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務

經檢查,在上一級頁面的respond的中,發現了該天的id,圖略

2.2-建構爬蟲程式

代碼有注釋,變量均采用英文命名,可直接閱讀

#!/usr/bin/env Python
# coding=utf-8
import requests
import json
import time


class auto_tips:
    def __init__(self, username, password):
        self.not_heat_names_list = []
        self.not_sign_names_list = []
        # 保留登入資訊
        self.session = requests.session()
        self.cookies = None

        # 登入界面的post資訊
        self.login_url = 'https://gw.wozaixiaoyuan.com/basicinfo/mobile/login/username'
        self.login_data = {
            'username': username,
            'password': password
        }
        self.login_headers = {
            'Host': 'gw.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'Content-Length': '2',
            'Accept': 'application/json, text/plain, */*',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'Content-Type': 'application/json;charset=UTF-8',
            'Sec-Fetch-Site': 'same-origin',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Dest': 'empty',
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept-Language': 'en-us,en'
        }
        # 班級日檢日報的資訊
        self.getHeatUsers_url = 'https://student.wozaixiaoyuan.com/heat/getHeatUsers.json'
        self.getHeatUsers_headers = {
            'Host': 'student.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'content-type': 'application/x-www-form-urlencoded',
            'Accept-Encoding': 'gzip, deflate, br'
        }
        self.getHeatUsers_data = {'seq': '1', 'date': str(time.strftime("%Y%m%d")), 'type': '0'}  # 測試用的,後邊程式會更改
        # 校區簽到的清單
        self.getList_url = 'https://student.wozaixiaoyuan.com/gradeManage/sign/getList.json'
        self.getList_headers = {
            'Host': 'student.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'content-type': 'application/x-www-form-urlencoded',
            'Accept-Encoding': 'gzip, deflate, br'
        }
        self.getList_date = {
            'keyword': '',
            'page': '1'
        }
        # 校區簽到的班級成員情況
        self.getSignResult_url = 'https://student.wozaixiaoyuan.com/gradeManage/sign/getSignResult.json'
        self.getSignResult_headers = {
            'Host': 'student.wozaixiaoyuan.com',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
            'content-type': 'application/x-www-form-urlencoded',
            'Accept-Encoding': 'gzip, deflate, br'
        }
        self.getSignResult_data = {
            'id': ''
        }

    def login(self):  # 登入賬号
        self.login_url = self.login_url + "?username=" + str(self.login_data['username']) + "&password=" + str(
            self.login_data['password'])  # 通過 url 的 '?' 方法寫入參數  # 更新url
        res = self.session.post(url=self.login_url, headers=self.login_headers, data='{}')
        try:
            if json.loads(res.text)['code'] == 0:
                self.session.cookies.set('JWSESSION', res.headers['JWSESSION'])  # 更新JWSESSION值
                print('{}\t登入成功'.format(time.strftime("%H:%M:%S")))
            else:
                print('{}\t登入失敗:{}'.format(time.strftime("%H:%M:%S"), json.loads(res.text)['message']))  # 輸出登入錯誤的錯誤原因
        except:
            print('{}\t登入錯誤'.format(time.strftime("%H:%M:%S")))

    def get_HeatUsers(self):
        try:
            res = self.session.post(url=self.getHeatUsers_url, headers=self.getHeatUsers_headers,
                                    data=self.getHeatUsers_data)
            if json.loads(res.text)['code'] == 0:  # 檢查是否請求成功且正确
                # print('{}\t成功獲得班級成員日檢日報資訊'.format(time.strftime("%H:%M:%S")))
                data = json.loads(res.text)['data']   # 觀察是否有不晨檢的同學
                if len(data) != 0:
                    for inf in data:  # 如果有,則更新不晨檢清單
                        name = inf['name']
                        self.not_heat_names_list.append(name)
                    print('{}\t未完成日檢日報的班級成員為{}'.format(time.strftime("%H:%M:%S"), self.not_heat_names_list))
                else:
                    print('{}\t班級成員全部完成日檢日報'.format(time.strftime("%H:%M:%S")))

            else:
                print('{}\t獲得班級成員日檢日報資訊失敗:{}'.format(time.strftime("%H:%M:%S"), json.loads(res.text)['message']))  # 輸出登入錯誤的錯誤原因
        except:
            print('{}\t獲得班級成員日檢日報資訊失敗'.format(time.strftime("%H:%M:%S")))

    def get_SignResult(self):
        # 擷取當天的簽到 id 值
        try:
            res = self.session.post(url=self.getList_url, headers=self.getList_headers,
                                    data=self.getList_date)
            if json.loads(res.text)['data'][0]['end'].split(' ')[0] == time.strftime("%Y-%m-%d"):  # 判斷第一個簽到是不是當天的簽到
                self.getSignResult_data['id'] = json.loads(res.text)['data'][0]['id']  # 如果判斷成功,則更新 查詢簽到的id
                res = self.session.post(url=self.getSignResult_url, headers=self.getSignResult_headers,  # 查詢簽到
                                        data=self.getSignResult_data)
                data = json.loads(res.text)['data']
                if len(data['notSign']) != 0:  # 判斷是否有成員不簽到
                    for inf in data['notSign']:
                        name = inf['name']
                        self.not_sign_names_list.append(name)
                    print('{}\t未完成簽到的班級成員為{}'.format(time.strftime("%H:%M:%S"), self.not_sign_names_list))
                else:
                    print('{}\t班級成員全部完成簽到'.format(time.strftime("%H:%M:%S")))
        except:
            print('{}\t獲得班級成員簽到資訊失敗'.format(time.strftime("%H:%M:%S")))


if __name__ == '__main__':
    obj = auto_tips('賬号名', '密碼')
    obj.login()
    obj.get_HeatUsers()
    obj.get_SignResult()           

2.3-建構郵件提醒程式

同上,可直接閱讀

import smtplib
from email.mime.text import MIMEText
# email 用于建構郵件内容
from email.header import Header


class email_obj:
    def __init__(self, to_addr=None, email_Subject=None, email_content=None):
        data_inf_path = r'系統日志\email_data.txt'   # 郵箱資訊的存儲路徑
        with open(data_inf_path, 'r+', encoding='UTF-8') as f:
            data_inf = eval(f.read())  # 讀取郵箱資訊
            f.close()
        self.from_addr = data_inf['發信郵箱']  # 發信郵箱
        self.password = data_inf['郵箱授權碼']  # 發信郵箱的授權碼
        self.smtp_server = data_inf['發信伺服器']  # 發信伺服器的域名
        self.to_addr = to_addr  # 收信郵箱
        self.email_Subject = email_Subject  # 郵件标題
        self.email_content = email_content  # 郵件内容

        # 開啟發信服務,這裡使用的是加密傳輸
        self.server = smtplib.SMTP_SSL(host=self.smtp_server)  # POP3/SMTP 協定的發送郵件伺服器
        self.server.connect(self.smtp_server, 465)  # 使用SSL,端口号465
        # 登入發信郵箱
        self.server.login(self.from_addr, self.password)

    def change_email_inf_to(self, to_addr, email_Subject, email_content):
        self.to_addr = to_addr  # 收信郵箱
        self.email_Subject = email_Subject  # 郵件标題
        self.email_content = email_content  # 郵件内容

    def send(self):
        # 郵箱正文内容,第一個參數為内容,第二個參數為格式(plain 為純文字),第三個參數為編碼
        msg = MIMEText(self.email_content, 'plain', 'utf-8')

        # 郵件頭資訊
        msg['From'] = Header(self.from_addr)
        msg['To'] = Header(self.to_addr)
        msg['Subject'] = Header(self.email_Subject)

        # 發送郵件
        self.server.sendmail(self.from_addr, self.to_addr, msg.as_string())

    def close(self):
        # 關閉伺服器
        self.server.quit()


if __name__ == '__main__':
    to_addr = '[email protected]'
    email_Subject = 'send by python'
    email_content = 'python test'
    obj = email_obj(to_addr, email_Subject, email_content)
    obj.send()           

定時觸發程式

#!/usr/bin/env Python
# coding=utf-8
import tips
import send_email
import pandas as pd
import time


def heat_tip(file):  # 晨檢提醒
    obj = tips.auto_tips('真實賬号', '真實密碼')
    obj.login()
    obj.get_HeatUsers()
    name_list = obj.not_heat_names_list
    if len(name_list) != 0:
        user_email = send_email.email_obj()  # 登入郵箱
        for i in range(len(name_list)):  # 依次編輯檔案
            name_i = name_list[i]
            for j in range(len(file)):
                name_j = file.iloc[j, 0]
                if name_i == name_j:
                    qq = file.iloc[j, 1]
                    qq_email = qq + '@qq.com'
                    email_Subject = '日檢日報提醒'
                    email_content = '趕緊晨檢了,現在已經是{}了'.format(time.strftime("%H:%M:%S"))
                    user_email.change_email_inf_to(to_addr=qq_email, email_Subject=email_Subject,
                                                      email_content=email_content)
                    user_email.send()
        user_email.close()  # 退出郵箱


def sign_tip(file):  # 簽到提醒
    obj = tips.auto_tips('真實賬号', '真實密碼')
    obj.login()
    obj.get_SignResult()
    name_list = obj.not_sign_names_list
    if len(name_list) != 0:
        user_email = send_email.email_obj()  # 登入郵箱
        for i in range(len(name_list)):  # 依次編輯檔案
            name_i = name_list[i]
            for j in range(len(file)):
                name_j = file.iloc[j, 0]
                if name_i == name_j:
                    qq = file.iloc[j, 1]
                    qq_email = qq + '@qq.com'
                    email_Subject = '簽到提醒'
                    email_content = '趕緊晨檢了,現在已經是{}了'.format(time.strftime("%H:%M:%S"))
                    user_email.change_email_inf_to(to_addr=qq_email, email_Subject=email_Subject,
                                                   email_content=email_content)
                    user_email.send()
        user_email.close()  # 退出郵箱


def seconds(now_time):  # 把時間轉化為秒
    hour = int(now_time.split(':')[0])
    minute = int(now_time.split(':')[1])
    second = int(now_time.split(':')[2])
    now_seconds = hour * 60 * 60 + minute * 60 + second
    return now_seconds


def get_sleep_time(now_time, to_time):  # 獲得程式睡眠時間
    sleep_time = seconds(to_time) - seconds(now_time)
    return sleep_time  # 機關是s


def auto_tips():
    file = pd.read_excel(r'使用者資訊\班級成員資訊.xlsx')
    print('開始運作')
    # 晨檢提醒時間
    heat_tip_time_1 = '11:00:00'
    heat_tip_time_2 = '11:30:00'
    heat_tip_time_3 = '11:50:00'
    # 簽到提醒時間
    sign_tip_time_1 = '22:05:00'
    sign_tip_time_2 = '22:15:00'
    sign_tip_time_3 = '22:25:00'
    tips_time_list = [heat_tip_time_1, heat_tip_time_2, heat_tip_time_3, sign_tip_time_1, sign_tip_time_2,
                      sign_tip_time_3]  # 按順序放好
    ####
    while True:
        flag = 0  # 判斷目前時間是否在提醒時間前
        tip_name = None  # 提醒的事件名稱
        sleep_time = None  # 睡眠時間
        for i in range(len(tips_time_list)):  # 判斷目前時間
            tip_time = tips_time_list[i]
            now_time = time.strftime("%H:%M:%S")  # 時:分:秒
            if seconds(now_time) < seconds(tip_time): 
                sleep_time = get_sleep_time(now_time=now_time, to_time=tip_time)
                if i <= 2:
                    tip_name = '晨檢'
                else:
                    tip_name = '簽到'
                flag = 1
                break
        if flag == 0:
            now_time = time.strftime("%H:%M:%S")  # 時:分:秒
            sleep_time = get_sleep_time(now_time=now_time, to_time='24:00:00') + get_sleep_time(now_time='00:00:00',
                                                                                                to_time=tips_time_list[0])
            tip_name = '晨檢'
        print('{}\t即将休眠{}秒'.format(time.strftime("%H:%M:%S"), sleep_time))
        time.sleep(sleep_time)
        if tip_name == '晨檢':
            heat_tip(file)
        elif tip_name == '簽到':
            sign_tip(file)
        print('{}\t提醒資訊已經發送'.format(time.strftime("%H:%M:%S")))


if __name__ == '__main__':
    # print(seconds('07:10:12'))
    auto_tips()           

2.4-配置檔案

檔案如圖配置

基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務
基于阿裡雲伺服器的我在校園班委自動管理系統關鍵詞0-引言1-總流程圖2.1-抓包解析過程2.2-建構爬蟲程式2.3-建構郵件提醒程式定時觸發程式2.4-配置檔案2.5-打包并且配置到伺服器上3-過程碰到的問題3.1-抓取不到登入界面3.2-擷取不了郵箱的授權碼3.3nssm-把exe檔案注冊成服務

2.5-打包并且配置到伺服器上

利用pyinstaller打包auto_tips.py

然後用指令控制符的mstsc指令,連接配接遠端伺服器,把整個檔案夾上傳到伺服器運作。

3-過程碰到的問題

3.1-抓取不到登入界面

問題描述打開微信小程式,進入我在校園後,隻獲得了get資訊,然後就自動轉接微信授權登入,無法抓取到post資訊

解決方法換另一台電腦登入後,再重新傳回本電腦登入我在校園,微信授權登入就會失敗,然後就可以賬号密碼登入,抓取到對應的資訊

3.2-擷取不了郵箱的授權碼

問題描述我用的是阿裡雲購買的域名,解析到騰訊企業郵箱的伺服器上,注冊了域名郵箱。找不到對應的授權碼

解決方法打開騰訊企業郵箱,給對應的郵箱開頭SMTP服務,然後進入郵箱,設定中處理就可以了。詳細教程網上可以查到

3.3nssm-把exe檔案注冊成服務

問題描述把exe檔案通過nssm程式注冊成計算機服務,背景運作服務時候,運作失敗

暫未解決