【2020.07.20更新】
自動打卡簽到已經失效,需要手動打卡,但是自動邀請仍然正常,手動打卡后每天仍然可以獲得11天+的會員。


前言
WPS是一款經常用的軟件,但是會員又不想買, 有些功能還必須會員使用,本來WPS是有一個【打卡簽到】可以免費領取會員的,但是每天總是忘,因此想到利用“雲函數”+Server醬實現基於Python的自動打卡簽到,這樣每天就會自動獲得會員了,效果還不錯,由於內置了一些小號來接受打卡邀請,因此我們的賬號還可獲得邀請獎勵,2020.07.17日親測是每天最少獲得11天的會員,下面是這幾天的實測效果:


一.需要的一些配置說明
廢話不多說,直接說怎么實現,我們需要進行一些簡單的配置。
1.1 獲得自己WPS帳號的[sid]和[userid]
首先我們就是要知道自己的【sid】和【userid】,這兩個是我們帳號的標志符或者說是自己的WPS帳號的ID身份證明,那么我們去哪里獲得這兩個參數呢?
其實很簡單,首先我們需要知道一些基礎的抓包操作,一般瀏覽器都是【F12】鍵開啟控制台調試,以谷歌瀏覽器為例,首先跳轉到WPS官方的簽到網站:https://zt.wps.cn/2018/clock_in/,界面截圖如下:

此時我們按【F12】,點擊【網絡】,進入抓包調試界面, 這時候我們在簽到頁面點擊登錄,按照提示登錄后,因為抓包已經開啟,故就可在【clock_in】頁面獲取到自己登陸后返回的【sid】了,需要注意的是WPS賬號一定要先綁定手機號和微信,否則可能會提示出錯。具體操作截圖如下:

我們把【sid】記錄下來先,接下來繼續找到我們的【userid】,此信息就是我們手機WPS個人信息中的用戶ID,舉例:【191641526】這一串數字就是我們的【userid】,如下圖示:

知道這兩個我們就獲取了自己的信息了,就可以進行下一步了。
1.2 配置server醬用於信息推送
接下來我們需要配置的是【server醬】,它是用來在push微信信息來告訴我們每天簽到是否成功還是失敗,使用很簡單,只需要按照網站上的流程來即可,網站如下:http://sc.ftqq.com
配置好拿到SERVER醬的SCKEY即可,舉例:SCUXXXXXXXXXXXXXXXX
1.3 配置雲函數
雲函數可以理解為在雲上運行的代碼,好處就是可以自動執行,不需要你在自己電腦上運行,目前各個商家的雲函數每個月都會給用戶免費提供一些次數,在這里我用的是騰訊雲函數,一個月是100萬次的免費次數,實際上我們實現WPS自動簽到一個月只需要30次就夠了,因此是綽綽有余的。
首先登陸騰訊雲:https://cloud.tencent.com/ ,登陸后找到雲函數選項,進入,之后新建一個雲函數,配置一下點下一步,詳情如下圖:



之后在代碼編輯欄里輸入一下代碼,注意下面的代碼中請依次修改 23、27、28、33、34行中的需要修改的部分內容!
# !/usr/bin/env python
# coding=utf-8
import requests
import time
import json
import sys
import pytz
import datetime
import re
from io import StringIO
# Python版本 3.6
# 20200717更新:添加簽到失敗提醒
# 請依次修改 23、27、28、33、34行中的需要修改的部分內容
# 邀請用戶簽到可以額外獲得會員,每日可邀請最多10個用戶,已預置了13個小號用於接受邀請,89-101行信息可選刪改
# 參考以下代碼解決https訪問警告
# from requests.packages.urllib3.exceptions import InsecureRequestWarning,InsecurePlatformWarning
# requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
# 初始化信息
SCKEY = '*********復制SERVER醬的SCKEY進來*************(保留引號)'
data = {
"wps_checkin": [
{
"name": "*********請自行輸入,僅用於顯示*************(保留雙引號)",
"sid": "*********復制'http://zt.wps.cn'網址Cookie中的sid進來*************(保留雙引號)"
}
],
"wps_invite": [
{
"name": "*********請自行輸入,僅用於顯示*************(保留雙引號)",
"invite_userid": "*********復制手機WPS個人信息中的用戶ID進來,類似括號內容(191641526)*************(不保留雙引號)",
"sid": []
}
]
}
# 初始化日志
sio = StringIO('WPS簽到日志\n\n')
sio.seek(0, 2) # 將讀寫位置移動到結尾
s = requests.session()
tz = pytz.timezone('Asia/Shanghai')
nowtime = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
sio.write("--------------------------"+nowtime+"----------------------------\n\n")
# 微信推送
def pushWechat(desp,nowtime):
ssckey = SCKEY
send_url='https://sc.ftqq.com/' + ssckey + '.send'
if '失敗' in desp :
params = {
'text': 'WPS小程序簽到失敗提醒' + nowtime,
'desp': desp
}
else:
params = {
'text': 'WPS小程序簽到提醒' + nowtime,
'desp': desp
}
requests.post(send_url,params=params)
# 主函數
def main():
# sio.write("\n ===模擬wps小程序簽到===")
sid = data['wps_checkin']
for item in sid:
sio.write("\n為{}簽到---↓\n\n".format(item['name']))
bl = wps_clockin(item['sid'])
if bl == 1:
# 獲取當前會員信息
member_url = 'https://zt.wps.cn/2018/clock_in/api/get_data?member=wps'
r1 = s.get(member_url, headers={'sid': item['sid']})
# 累計獲得會員天數
total_add_day = re.search('"total_add_day":(\d+)', r1.text).group(1)
sio.write('累計獲得會員天數: {}天\n\n'.format(total_add_day))
userinfo_url = 'https://vip.wps.cn/userinfo'
r2 = s.get(userinfo_url, headers={'sid': item['sid']})
resp = json.loads(r2.text)
sio.write('會員信息: {{ "類型":{}, '.format(resp['data']['vip']['name']))
sio.write('"過期時間":{} }}\n\n'.format(datetime.datetime.fromtimestamp(
resp['data']['vip']['expire_time']).strftime("%Y--%m--%d %H:%M:%S")))
# sys.exit()
wps_inv = data['wps_invite']
# 這13個賬號被邀請
invite_sid = [
"V02StVuaNcoKrZ3BuvJQ1FcFS_xnG2k00af250d4002664c02f",
"V02SWIvKWYijG6Rggo4m0xvDKj1m7ew00a8e26d3002508b828",
"V02Sr3nJ9IicoHWfeyQLiXgvrRpje6E00a240b890023270f97",
"V02SBsNOf4sJZNFo4jOHdgHg7-2Tn1s00a338776000b669579",
"V02ScVbtm2pQD49ArcgGLv360iqQFLs014c8062e000b6c37b6",
"V02S2oI49T-Jp0_zJKZ5U38dIUSIl8Q00aa679530026780e96",
"V02ShotJqqiWyubCX0VWTlcbgcHqtSQ00a45564e002678124c",
"V02SFiqdXRGnH5oAV2FmDDulZyGDL3M00a61660c0026781be1",
"V02S7tldy5ltYcikCzJ8PJQDSy_ElEs00a327c3c0026782526",
"V02SPoOluAnWda0dTBYTXpdetS97tyI00a16135e002684bb5c",
"V02Sb8gxW2inr6IDYrdHK_ywJnayd6s00ab7472b0026849b17",
"V02SwV15KQ_8n6brU98_2kLnnFUDUOw00adf3fda0026934a7f",
"V02SC1mOHS0RiUBxeoA8NTliH2h2NGc00a803c35002693584d"
]
sio.write("\n\n==========wps邀請==========\n\n")
for item in wps_inv:
sio.write("為{}邀請---↓\n\n".format(item['name']))
if type(item['invite_userid']) == int:
wps_invite(invite_sid, item['invite_userid'])
else:
sio.write("邀請失敗:用戶ID錯誤,請重新復制手機WPS個人信息中的用戶ID並修改'invite_userid'項,注意不保留雙引號\n\n")
desp = sio.getvalue()
pushWechat(desp,nowtime)
#print(desp)
return desp
# wps接受邀請
def wps_invite(sid: list, invite_userid: int) -> None:
invite_url = 'http://zt.wps.cn/2018/clock_in/api/invite'
for index, i in enumerate(sid):
headers = {
'sid': i
}
r = s.post(invite_url, headers=headers, data={
'invite_userid': invite_userid})
sio.write("ID={}, 狀態碼: {}, \n\n 請求信息{}\n\n".format(str(index+1).zfill(2), r.status_code, r.text))
# wps簽到
def wps_clockin(sid: str):
if len(sid) == 0:
sio.write("簽到失敗:用戶sid為空,請重新輸入\n\n")
return 0
elif "*" in sid or sid[0] != "V":
sio.write("簽到失敗:用戶sid錯誤,請重新輸入\n\n")
return 0
# 打卡簽到
clockin_url = 'http://zt.wps.cn/2018/clock_in/api/clock_in?member=wps'
r = s.get(clockin_url, headers={'sid': sid})
if len(r.history) != 0:
if r.history[0].status_code == 302:
sio.write("簽到失敗:用戶sid錯誤,請重新輸入\n\n")
return 0
resp = json.loads(r.text)
# 判斷是否已打卡
if resp['msg'] == '已打卡':
sio.write("簽到信息: {}\n\n".format(r.text))
return 1
# 判斷是否綁定手機
elif resp['msg'] == '未綁定手機':
sio.write('簽到失敗: 未綁定手機,請綁定手機后重新運行簽到\n\n')
return 0
# 判斷是否重新報名
elif resp['msg'] == '前一天未報名':
sio.write('前一天未報名\n\n')
signup_url = 'http://zt.wps.cn/2018/clock_in/api/sign_up'
r=s.get(signup_url, headers={'sid': sid})
resp = json.loads(r.text)
if resp['result'] == 'ok':
sio.write('報名信息: 已自動報名,報名后第二天簽到\n\n')
return 1
else:
sio.write('報名失敗: 請手動報名,報名后第二天簽到\n\n')
return 0
# 打卡簽到需要參加活動
elif resp['msg'] == '答題未通過':
getquestion_url = 'http://zt.wps.cn/2018/clock_in/api/get_question?member=wps'
r = s.get(getquestion_url, headers={'sid': sid})
'''
{
"result": "ok",
"data": {
"multi_select": 1,
"options": [
"30天文檔分享鏈接有效期",
"遠程下載助手",
"輸出長圖片去水印",
"PDF轉圖片"
],
"title": "以下哪些特權是WPS會員和超級會員共同擁有的?"
},
"msg": ""
}
'''
answer_set = {
'WPS會員全文檢索',
'100G',
'WPS會員數據恢復',
'WPS會員PDF轉doc',
'WPS會員PDF轉圖片',
'WPS圖片轉PDF插件',
'金山PDF轉WORD',
'WPS會員拍照轉文字',
'使用WPS會員修復',
'WPS全文檢索功能',
'有,且無限次',
'文檔修復'
}
resp = json.loads(r.text)
# sio.write(resp['data']['multi_select'])
# 只做單選題 multi_select==1表示多選題
while resp['data']['multi_select'] == 1:
r = s.get(getquestion_url, headers={'sid': sid})
resp = json.loads(r.text)
# sio.write('選擇題類型: {}'.format(resp['data']['multi_select']))
answer_id = 3
for i in range(4):
opt = resp['data']['options'][i]
if opt in answer_set:
answer_id = i+1
break
sio.write("選項: {}\n\n".format(resp['data']['options']))
sio.write("選擇答案: {}\n\n".format(answer_id))
# 提交答案
answer_url = 'http://zt.wps.cn/2018/clock_in/api/answer?member=wps'
r = s.post(answer_url, headers={'sid': sid}, data={'answer': answer_id})
resp = json.loads(r.text)
# 答案錯誤
if resp['msg'] == 'wrong answer':
sio.write("答案不對,挨個嘗試\n\n")
for i in range(4):
r = s.post(answer_url, headers={'sid': sid}, data={'answer': i+1})
resp = json.loads(r.text)
sio.write(i+1)
if resp['result'] == 'ok':
sio.write(r.text)
break
# 打卡簽到
clockin_url = 'http://zt.wps.cn/2018/clock_in/api/clock_in?member=wps'
r = s.get(clockin_url, headers={'sid': sid})
sio.write("簽到信息: {}\n\n".format(r.text))
return 1
# 判斷是否不在簽到時間內
elif resp['msg'] == '不在打卡時間內':
sio.write('簽到失敗: 不在打卡時間內\n\n')
signup_url = 'http://zt.wps.cn/2018/clock_in/api/sign_up'
r=s.get(signup_url, headers={'sid': sid})
resp = json.loads(r.text)
if resp['result'] == 'ok':
sio.write('已自動報名,報名后請設置在規定時間內簽到\n\n')
return 1
else:
sio.write('報名失敗: 請手動報名,報名后第二天簽到\n\n')
return 0
# 其他錯誤
elif resp['result'] == 'error':
sio.write('簽到失敗信息: {}\n\n'.format(r.text))
signup_url = 'http://zt.wps.cn/2018/clock_in/api/sign_up'
r=s.get(signup_url, headers={'sid': sid})
resp = json.loads(r.text)
if resp['result'] == 'ok':
sio.write('已自動報名,報名后請設置在規定時間內簽到\n\n')
return 1
else:
sio.write('報名失敗: 請手動報名,報名后第二天簽到\n\n')
return 0
def main_handler(event, context):
return main()
if __name__ == '__main__':
main()
按照說明修改完以上代碼后,我們可以先測試觸發一下看看是否配置正確,點擊下面的【測試】按鈕,會返回測試結果,如下圖所示:

確認代碼無誤后,我們點擊完成,之后配置雲函數的觸發規則,首先點擊【觸發管理】,之后選擇【創建觸發器】,具體操作如下圖:

創建完觸發器后,我們配置觸發器規則,首先在觸發方式里選擇【定時觸發】,觸發周期里選擇【自定義觸發周期】,在下面的Cron表達式里填入:0 10 8 * * * *
如下圖示:

以上完成后,便可解放雙手,每天在8點10分自動簽到,會員就到手了。