Python + GitHub Actions 实现 CSDN 自动签到与抽奖(非 selenium 版本)
文章目錄
- 【1x00】技術(shù)棧
- 【2x00】代碼實(shí)現(xiàn)簽到與抽獎(jiǎng)
- 【3x00】簽到結(jié)果通知
- 【03x01】Server 醬
- 【03x02】企業(yè)微信
- 【03x03】釘釘
- 【4x00】自動(dòng)簽到
- 【5x00】完整代碼
- 【6x00】如何使用
- 【06x01】方法一:直接 Fork 代碼(推薦)
- 【06x01】方法二:自己上傳代碼
-
本文旨在交流 Python 編程技術(shù),若有侵犯 CSDN 利益,請(qǐng)聯(lián)系我刪除文章(直接給我刪了也行😁)。
-
其他爬蟲(chóng)實(shí)戰(zhàn)代碼合集(持續(xù)更新):https://github.com/TRHX/Python3-Spider-Practice
-
爬蟲(chóng)實(shí)戰(zhàn)專(zhuān)欄(持續(xù)更新):https://itrhx.blog.csdn.net/article/category/9351278
>>> 如果你想直接使用,不想看廢話,請(qǐng)直接看【6x00】如何使用部分<<<
【1x00】技術(shù)棧
- 語(yǔ)言:Python
- 功能:簽到、抽獎(jiǎng)(可選)
- 自動(dòng)簽到:GitHub Actions
- 簽到結(jié)果通知:Server 醬(可選)、企業(yè)微信(可選)、釘釘(可選)
【2x00】代碼實(shí)現(xiàn)簽到與抽獎(jiǎng)
對(duì)簽到和抽獎(jiǎng)的過(guò)程抓包分析,可以揪出以下兩個(gè)鏈接:
- 簽到:https://me.csdn.net/api/LuckyDraw_v2/signIn
- 抽獎(jiǎng):https://me.csdn.net/api/LuckyDraw_v2/goodLuck
兩者的請(qǐng)求方式都是 post,且兩者的 Request headers 和 Request Payload 都一樣。重要參數(shù)有三個(gè):cookie、username、uuid,cookie 參數(shù)暫時(shí)沒(méi)辦法解決,只能自己登陸后復(fù)制過(guò)來(lái),username 是你的 id,可以在【個(gè)人中心】—【個(gè)人資料】—【基本信息】—【用戶 ID】查看,uuid 就是 cookie 里面第一個(gè)參數(shù) uuid_tt_dd 的值。用 Python 實(shí)現(xiàn)基本的簽到與抽獎(jiǎng)功能如下(此代碼可直接運(yùn)行,需要將 CSDN_ID 和 COOKIE 換成你的,COOKIE 可以在已經(jīng)登錄的任意頁(yè)面 F12 獲取):
import requests import jsonCSDN_ID = '' # 你的 CSDN ID COOKIE = '' # 你的 cookie IF_LUCK_DRAW = True # 是否開(kāi)啟抽獎(jiǎng)class CSDN:def __init__(self):self.UUID = COOKIE.split(';', 1)[0].split('=', 1)[1]self.USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36'self.SIGN_IN_URL = 'https://me.csdn.net/api/LuckyDraw_v2/signIn'self.LUCKY_DRAW_URL = 'https://me.csdn.net/api/LuckyDraw_v2/goodLuck'self.DRAW_TIMES = 0 # 可抽獎(jiǎng)次數(shù)self.HEADERS = {'accept': 'application/json, text/plain, */*','accept-encoding': 'gzip, deflate, br','accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7','content-length': '243','content-type': 'application/json;charset=UTF-8','cookie': COOKIE,'origin': 'https://i.csdn.net','referer': 'https://i.csdn.net/','sec-fetch-dest': 'empty','sec-fetch-mode': 'cors','sec-fetch-site': 'same-site','user-agent': self.USER_AGENT}self.DATA = {'ip': '','platform': 'pc-my','product': 'pc','user_agent': self.USER_AGENT,'username': CSDN_ID,'uuid': self.UUID}def csdn_sign_in(self):response = requests.post(url=self.SIGN_IN_URL, headers=self.HEADERS, data=self.DATA)result = json.loads(response.text)# print(result)if result['code'] == 200:if not result['data']['isSigned'] and result['data']['signed']:keep_count = result['data']['keepCount']total_count = result['data']['totalCount']total_signed_count = result['data']['totalSignedCount']# self.STAR = result['data']['star']self.DRAW_TIMES = result['data']['drawTimes']print('簽到成功!你已連續(xù)簽到 {} 天,累計(jì)簽到 {} 天,當(dāng)前已有 {} 人簽到。'.format(keep_count, total_count, total_signed_count))elif result['data']['isSigned']:print('你今天已經(jīng)簽到過(guò)了喲!')else:print('簽到失敗!')elif result['code'] == 400102:print('簽到失敗!{} 用戶不存在或者 cookie 錯(cuò)誤!請(qǐng)檢查 CSDN ID 或嘗試重置 cookie!'.format(CSDN_ID))else:print('簽到失敗!')def csdn_luck_draw(self):if self.DRAW_TIMES != 0:response = requests.post(url=self.LUCKY_DRAW_URL, headers=self.HEADERS, data=self.DATA)result = json.loads(response.text)# print(result)if result['code'] == 200:if result['data']['can_draw']:prize_title = result['data']['prize_title']print('抽獎(jiǎng)成功!恭喜你獲得{}'.format(prize_title))elif not result['data']['can_draw']:print('抽獎(jiǎng)機(jī)會(huì)已經(jīng)用完了喲!')else:print('抽獎(jiǎng)失敗!')elif result['code'] == 400102:print('抽獎(jiǎng)失敗!{} 用戶不存在或者 cookie 錯(cuò)誤!請(qǐng)檢查 CSDN ID 或嘗試重置 cookie!'.format(CSDN_ID))else:print('抽獎(jiǎng)失敗!')def run():c = CSDN()c.csdn_sign_in()if IF_LUCK_DRAW:c.csdn_luck_draw()if __name__ == '__main__':run()【3x00】簽到結(jié)果通知
【03x01】Server 醬
Server 醬首頁(yè):sc.ftqq.com
什么是 Server 醬?簡(jiǎn)單來(lái)說(shuō),登錄 Server 醬后,會(huì)分配給你一個(gè) SCKEY,通過(guò)向?qū)iT(mén)的 URL 發(fā)送 get 或者 post 請(qǐng)求,你的微信就會(huì)收到對(duì)應(yīng)的消息,對(duì)于不使用企業(yè)微信和釘釘?shù)挠脩魜?lái)說(shuō),這種方法是最方便的。目前有標(biāo)準(zhǔn)版和 Turbo 版,據(jù)說(shuō)標(biāo)準(zhǔn)版會(huì)下線,目前還能使用,所以暫時(shí)使用的是標(biāo)準(zhǔn)版。若被棄用,我會(huì)第一時(shí)間更新。實(shí)現(xiàn)效果:
【03x02】企業(yè)微信
如果你是一個(gè)企業(yè)微信群的群主,那么可以在群名右鍵添加一個(gè)機(jī)器人,添加成功后會(huì)給你一個(gè)機(jī)器人的 URL 地址,向這個(gè) URL 發(fā)送 post 請(qǐng)求就可以在群里看到對(duì)應(yīng)的消息,支持 markdown、text、圖片等多種格式,具體可以查看機(jī)器人配置說(shuō)明。
【03x03】釘釘
和企業(yè)微信類(lèi)似,如果你是一個(gè)釘釘群的群主,依次右鍵【群設(shè)置】—【群智能助手】—【添加機(jī)器人】,選擇自定義(通過(guò)webhook接入自定義訪問(wèn))機(jī)器人,安全設(shè)置里面選擇【加簽】,添加完成后你會(huì)得到一個(gè)機(jī)器人的 Webhook URL 和一個(gè)加簽的密鑰,之后使用特定的算法將一些參數(shù)和 URL 組成新的 URL,再向這個(gè) URL 發(fā)送 post 請(qǐng)求就可以在群里收到消息了,具體使用方法參見(jiàn)官方文檔:https://developers.dingtalk.com/document/app/custom-robot-access
【4x00】自動(dòng)簽到
這里自動(dòng)簽到使用的是 GitHub Actions,這是 GitHub 提出的一項(xiàng)持續(xù)集成服務(wù),它提供了一個(gè)高效易用的 CI/CD 工作流,能夠幫助我們自動(dòng)構(gòu)建、測(cè)試和部署我們的代碼,簡(jiǎn)單來(lái)說(shuō),對(duì)于我們的自動(dòng)簽到程序,它能夠每天定時(shí)運(yùn)行一遍,以達(dá)到每天簽到的目的,如果有 cookie,密鑰之類(lèi)的參數(shù),可以在倉(cāng)庫(kù)的 【Settings】—【Secrets】里面添加。定時(shí)任務(wù)和運(yùn)行環(huán)境等其他參數(shù)統(tǒng)一在一個(gè) .yml 文件中配置。
GitHub Actions 官方文檔:https://docs.github.com/cn/actions
【5x00】完整代碼
CSDN 簽到抽獎(jiǎng)主程序代碼 CSDN.py :
注:代碼不能直接運(yùn)行,這是放到 GitHub Actions 上執(zhí)行的代碼,使用方法見(jiàn)【6x00】,如果要本地運(yùn)行,則需要將配置項(xiàng)目 1 2 3 中 os.environ["xxxxx"] 換成各自對(duì)應(yīng)的值!
# ==================================== # --*-- coding: utf-8 --*-- # @Time : 2021-05-29 # @Author : TRHX ? 鮑勃 # @Blog : www.itrhx.com # @CSDN : itrhx.blog.csdn.net # @FileName: CSDN.py # @Software: PyCharm # ====================================import requests import json import os import time import hmac import hashlib import base64 import urllib.parse# ============== 1.CSDN 個(gè)人信息 ============== # CSDN_ID = os.environ["CSDN_ID"] # 必填!CSDN 的 ID COOKIE = os.environ["COOKIE"] # 必填!已登錄的 cookie# ============== 2.功能開(kāi)關(guān)配置項(xiàng) ============== # # 填 on 則開(kāi)啟,開(kāi)啟的同時(shí)也需要配置3中的選項(xiàng),不填或填其他則關(guān)閉 IF_LUCK_DRAW = os.environ["IF_LUCK_DRAW"] # 選填!是否開(kāi)啟抽獎(jiǎng) IF_SEVER = os.environ["IF_SEVER"] # 選填!是否開(kāi)啟 server 醬通知 IF_WECHAT = os.environ["IF_WECHAT"] # 選填!是否開(kāi)啟企業(yè)微信通知 IF_DING = os.environ["IF_DING"] # 選填!是否開(kāi)啟釘釘通知# ============== 3.消息通知配置項(xiàng) ============== # SEVER_SCKEY = os.environ["SEVER_SCKEY"] # 選填!server 醬的 SCKEY WECHAT_URL = os.environ["WECHAT_URL"] # 選填!企業(yè)微信機(jī)器人地址 DING_URL = os.environ["DING_URL"] # 選填!釘釘機(jī)器人地址 DING_SECRET = os.environ["DING_SECRET"] # 選填!釘釘機(jī)器人加簽 SECRET# ============== 4.準(zhǔn)備發(fā)送的消息 ============== # TEXT = '' DESP = ''class CSDN:def __init__(self):self.DRAW_TIMES = 0 # 可抽獎(jiǎng)次數(shù)self.UUID = COOKIE.split(';', 1)[0].split('=', 1)[1]self.USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36'self.SIGN_IN_URL = 'https://me.csdn.net/api/LuckyDraw_v2/signIn'self.LUCKY_DRAW_URL = 'https://me.csdn.net/api/LuckyDraw_v2/goodLuck'self.HEADERS = {'accept': 'application/json, text/plain, */*','accept-encoding': 'gzip, deflate, br','accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7','content-length': '243','content-type': 'application/json;charset=UTF-8','cookie': COOKIE,'origin': 'https://i.csdn.net','referer': 'https://i.csdn.net/','sec-fetch-dest': 'empty','sec-fetch-mode': 'cors','sec-fetch-site': 'same-site','user-agent': self.USER_AGENT}self.DATA = {'ip': '','platform': 'pc-my','product': 'pc','user_agent': self.USER_AGENT,'username': CSDN_ID,'uuid': self.UUID}def csdn_sign_in(self):global TEXT, DESPresponse = requests.post(url=self.SIGN_IN_URL, headers=self.HEADERS, data=self.DATA)result = json.loads(response.text)# print(result)if result['code'] == 200:if not result['data']['isSigned'] and result['data']['signed']:keep_count = result['data']['keepCount']total_count = result['data']['totalCount']total_signed_count = result['data']['totalSignedCount']# self.STAR = result['data']['star']self.DRAW_TIMES = result['data']['drawTimes']TEXT = 'CSDN 簽到成功!'DESP = 'CSDN 簽到成功!你已連續(xù)簽到 {} 天,累計(jì)簽到 {} 天,當(dāng)前已有 {} 人簽到。'.format(keep_count, total_count, total_signed_count)print('簽到成功!你已連續(xù)簽到 {} 天,累計(jì)簽到 {} 天,當(dāng)前已有 {} 人簽到。'.format(keep_count, total_count, total_signed_count))elif result['data']['isSigned']:TEXT = 'CSDN 簽到失敗!'DESP = 'CSDN 簽到失敗!你今天已經(jīng)簽到過(guò)了喲!'print('你今天已經(jīng)簽到過(guò)了喲!')else:TEXT = 'CSDN 簽到失敗!'print('簽到失敗!')elif result['code'] == 400102:TEXT = 'CSDN 簽到失敗!'DESP = 'CSDN 簽到失敗!{} 用戶不存在或者 cookie 錯(cuò)誤!請(qǐng)檢查 CSDN ID 或嘗試重置 cookie!'.format(CSDN_ID)print('簽到失敗!{} 用戶不存在或者 cookie 錯(cuò)誤!請(qǐng)檢查 CSDN ID 或嘗試重置 cookie!'.format(CSDN_ID))else:TEXT = 'CSDN 簽到失敗!'print('簽到失敗!')def csdn_luck_draw(self):if self.DRAW_TIMES != 0:global TEXT, DESPresponse = requests.post(url=self.LUCKY_DRAW_URL, headers=self.HEADERS, data=self.DATA)result = json.loads(response.text)print(result)if result['code'] == 200:if result['data']['can_draw']:prize_title = result['data']['prize_title']TEXT += 'CSDN 抽獎(jiǎng)成功!'DESP += '抽獎(jiǎng)成功!恭喜你獲得{}'.format(prize_title)print('抽獎(jiǎng)成功!恭喜你獲得{}'.format(prize_title))elif not result['data']['can_draw']:TEXT += 'CSDN 抽獎(jiǎng)失敗!'DESP += 'CSDN 抽獎(jiǎng)失敗!抽獎(jiǎng)機(jī)會(huì)已經(jīng)用完了喲!'print('抽獎(jiǎng)機(jī)會(huì)已經(jīng)用完了喲!')else:TEXT += 'CSDN 抽獎(jiǎng)失敗!'print('抽獎(jiǎng)失敗!')elif result['code'] == 400102:TEXT = 'CSDN 抽獎(jiǎng)失敗!'DESP = 'CSDN 抽獎(jiǎng)失敗!{} 用戶不存在或者 cookie 錯(cuò)誤!請(qǐng)檢查 CSDN ID 或嘗試重置 cookie!'.format(CSDN_ID)print('抽獎(jiǎng)失敗!{} 用戶不存在或者 cookie 錯(cuò)誤!請(qǐng)檢查 CSDN ID 或嘗試重置 cookie!'.format(CSDN_ID))else:TEXT += 'CSDN 抽獎(jiǎng)失敗!'print('抽獎(jiǎng)失敗!')class Notice:@staticmethoddef sever():requests.get('https://sc.ftqq.com/{}.send?text={}&desp={}'.format(SEVER_SCKEY, TEXT, DESP))@staticmethoddef wechat():data = {'msgtype': 'text','text': {'content': DESP}}headers = {'content-type': 'application/json'}requests.post(url=WECHAT_URL, headers=headers, data=json.dumps(data))@staticmethoddef ding():timestamp = str(round(time.time() * 1000))secret = DING_SECRETsecret_enc = secret.encode('utf-8')string_to_sign = '{}\n{}'.format(timestamp, secret)string_to_sign_enc = string_to_sign.encode('utf-8')hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))headers = {'Content-Type': 'application/json'}complete_url = DING_URL + '×tamp=' + timestamp + "&sign=" + signdata = {"text": {"content": DESP},"msgtype": "text"}requests.post(url=complete_url, data=json.dumps(data), headers=headers)def run():c = CSDN()n = Notice()c.csdn_sign_in()if IF_LUCK_DRAW == 'on':c.csdn_luck_draw()if IF_SEVER == 'on':n.sever()if IF_WECHAT == 'on':n.wechat()if IF_DING == 'on':n.ding()if __name__ == '__main__':run()GitHub Actions 工作流配置文件 csdn-sign-in.yml:
# This workflow will install Python dependencies, run tests and lint with a single version of Python # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actionsname: CSDN Sign Inon:push:branches: [ main ]pull_request:branches: [ main ]schedule:- cron: 0 16 * * *jobs:build:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v2- name: Set up Python 3.9uses: actions/setup-python@v2with:python-version: 3.9- name: Install dependenciesrun: |python -m pip install --upgrade pippip install requestsif [ -f requirements.txt ]; then pip install -r requirements.txt; fi- name: CSDNrun: |python3 CSDN.py env: CSDN_ID: ${{ secrets.CSDN_ID }}COOKIE: ${{ secrets.COOKIE }}IF_LUCK_DRAW: ${{ secrets.IF_LUCK_DRAW }}IF_SEVER: ${{ secrets.IF_SEVER }}IF_WECHAT: ${{ secrets.IF_WECHAT }}IF_DING: ${{ secrets.IF_DING }}SEVER_SCKEY: ${{ secrets.SEVER_SCKEY }}WECHAT_URL: ${{ secrets.WECHAT_URL }}DING_URL: ${{ secrets.DING_URL }}DING_SECRET: ${{ secrets.DING_SECRET }}所需環(huán)境 requirements.txt:
requests【6x00】如何使用
【06x01】方法一:直接 Fork 代碼(推薦)
代碼地址:https://github.com/TRHX/CSDNSignIn
點(diǎn)擊右上角【Fork】代碼到你的賬戶,然后點(diǎn)擊【Settings】—【Secret】—【New repository secret】,依次填入以下 Name 以及對(duì)應(yīng)的 Value:
| CSDN_ID | 是 | CSDN 的 ID | qq_36759224 |
| COOKIE | 是 | 已登錄的 cookie | uuid_tt_dd=10_287647… |
| IF_LUCK_DRAW | 否 | 是否開(kāi)啟抽獎(jiǎng) | on |
| IF_SEVER | 否 | 是否開(kāi)啟 server 醬通知 | on |
| IF_WECHAT | 否 | 是否開(kāi)啟企業(yè)微信通知 | on |
| IF_DING | 否 | 是否開(kāi)啟釘釘通知 | on |
| SEVER_SCKEY | 取決于 IF_SEVER | server 醬的 SCKEY | SCU165692T… |
| WECHAT_URL | 取決于 IF_WECHAT | 企業(yè)微信機(jī)器人地址 | https://qyapi.weixin.qq.com/cgi-bin/webhook/… |
| DING_URL | 取決于 IF_DING | 釘釘機(jī)器人地址 | https://oapi.dingtalk.com/robot/send… |
| DING_SECRET | 取決于 IF_DING | 釘釘機(jī)器人加簽 SECRET | SEC1cb948ba… |
舉例:我需要開(kāi)啟抽獎(jiǎng)和 server 醬通知,則需要填的有:
| CSDN_ID | qq_36759224 |
| COOKIE | uuid_tt_dd=10_287647… |
| IF_LUCK_DRAW | on |
| IF_SEVER | on |
| SEVER_SCKEY | SCU165692T… |
如果你需要更改每天簽到的時(shí)間,則需要更改 .github/workflows/csdn-sign-in.yml 文件里面 cron: 0 16 * * * 的值,這里使用的是 Linux crontab 定時(shí)任務(wù)命令,0 16 * * * 表示每天凌晨運(yùn)行一次,注意這里使用的是 UTC 國(guó)際標(biāo)準(zhǔn)時(shí)間,與北京時(shí)間相差 8 個(gè)小時(shí),所以 UTC 時(shí)間 16 點(diǎn)也就是北京時(shí)間的 24 點(diǎn)。
注意:
-
cookie 的值需要你登錄后 F12 查看復(fù)制過(guò)來(lái),cookie 的有效期是多久暫時(shí)不得而知,等下次失效了我再回來(lái)告訴你們有效期是多久,如果我沒(méi)說(shuō),那就代表一直沒(méi)失效!😁
-
經(jīng)過(guò)測(cè)試,cookie 的有效期在 45 天左右,失效后需要重新復(fù)制一個(gè)新 cookie 過(guò)來(lái)!
-
如果你開(kāi)啟了自動(dòng)抽獎(jiǎng),程序會(huì)識(shí)別你當(dāng)前還有多少次抽獎(jiǎng)次數(shù),如果抽獎(jiǎng)次數(shù)為0,則仍然不執(zhí)行抽獎(jiǎng)任務(wù)!
【06x01】方法二:自己上傳代碼
將【5x00】完整代碼中的 CSDN.py 以及所需環(huán)境 requirements.txt 上傳到自己的 GitHub 倉(cāng)庫(kù),點(diǎn)擊倉(cāng)庫(kù)的 【Actions】,選擇【Python application】,點(diǎn)擊【Set up this workflow】創(chuàng)建工作流,之后會(huì)出來(lái)一個(gè) python-app.yml,參考【5x00】完整代碼中的 csdn-sign-in.yml,添加定時(shí)任務(wù)和參數(shù)配置,編輯完成后點(diǎn)擊【Start commit】提交。
當(dāng)然也可以直接在本地編寫(xiě)好配置文件 csdn-sign-in.yml 直接和源碼一起提交,GitHub 會(huì)自動(dòng)識(shí)別,注意路徑為:.github\workflows\csdn-sign-in.yml。
以上步驟完成之后,再參考步驟【06x01】,完成參數(shù)設(shè)置即可。
總結(jié)
以上是生活随笔為你收集整理的Python + GitHub Actions 实现 CSDN 自动签到与抽奖(非 selenium 版本)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 余承东大赞舒适度超越所有豪车!问界M7实
- 下一篇: 【Python CheckiO 题解】H