本文僅用于學習用途,轉載請注明出處
關鍵詞
python、fiddler抓包、伺服器、我在校園、HTTP
0-引言
因學校要求,班委需提醒未完成打卡同學打卡,否則扣除德育分,影響德育成績。是以為實作班委我在校園的自動化管理,嘗試使用python編寫一個爬蟲程式挂靠在伺服器運作,實作每天的自動提醒管理。
經前期搜尋,網際網路上的我在校園爬蟲未涉及班委的自動化管理,且僅僅通過token或者JWSESSION實作登入,時效性不好且操作麻煩。例如github上面的我在校園自動簽到程式,通過token值實作簽到,但現已經停止維護,且token值登入已經被我在校園登入給禁止。csdn和部落格園的部分文章僅僅涉及通過抓包擷取JWSESSION實作登入簽到,但是有效期不長。
1-總流程圖
2.1-抓包解析過程
部分關鍵資訊已經打碼
打開fiddler和我在校園小程式,登入,抓取到登入資訊如下
由其中發現,我在校園登入是通過url中的符号 ? 來實作傳值的,由于登入的時候沒有後面的openid等值,猜測傳入賬号和密碼就可以實作登入。
經檢驗,猜測正确。
按照正常流程進入班級管理界面,依次進入日漸日報管理和班級簽到管理,而後檢查抓包資訊
我在校園班級管理界面
日檢日報界面
同理進入簽到頁面檢查,發現出入的參數有一個id
經檢查,在上一級頁面的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-配置檔案
檔案如圖配置
2.5-打包并且配置到伺服器上
利用pyinstaller打包auto_tips.py
然後用指令控制符的mstsc指令,連接配接遠端伺服器,把整個檔案夾上傳到伺服器運作。
3-過程碰到的問題
3.1-抓取不到登入界面
問題描述打開微信小程式,進入我在校園後,隻獲得了get資訊,然後就自動轉接微信授權登入,無法抓取到post資訊
解決方法換另一台電腦登入後,再重新傳回本電腦登入我在校園,微信授權登入就會失敗,然後就可以賬号密碼登入,抓取到對應的資訊
3.2-擷取不了郵箱的授權碼
問題描述我用的是阿裡雲購買的域名,解析到騰訊企業郵箱的伺服器上,注冊了域名郵箱。找不到對應的授權碼
解決方法打開騰訊企業郵箱,給對應的郵箱開頭SMTP服務,然後進入郵箱,設定中處理就可以了。詳細教程網上可以查到
3.3nssm-把exe檔案注冊成服務
問題描述把exe檔案通過nssm程式注冊成計算機服務,背景運作服務時候,運作失敗
暫未解決