文章目录
- 【1x00】技术栈
- 【2x00】代码实现签到与抽奖
- 【3x00】签到结果通知
- 【03x01】Server 酱
- 【03x02】企业微信
- 【03x03】钉钉
- 【4x00】自动签到
- 【5x00】完整代码
- 【6x00】如何使用
- 【06x01】方法一:直接 Fork 代码(推荐)
- 【06x01】方法二:自己上传代码
-
本文旨在交流 Python 编程技术,若有侵犯 CSDN 利益,请联系我删除文章(直接给我删了也行😁)。
-
其他爬虫实战代码合集(持续更新):https://github.com/TRHX/Python3-Spider-Practice
-
爬虫实战专栏(持续更新):https://itrhx.blog.csdn.net/article/category/9351278
>>> 如果你想直接使用,不想看废话,请直接看【6x00】如何使用部分<<<
【1x00】技术栈
- 语言:Python
- 功能:签到、抽奖(可选)
- 自动签到:GitHub Actions
- 签到结果通知:Server 酱(可选)、企业微信(可选)、钉钉(可选)
【2x00】代码实现签到与抽奖
对签到和抽奖的过程抓包分析,可以揪出以下两个链接:
- 签到:https://me.csdn.net/api/LuckyDraw_v2/signIn
- 抽奖:https://me.csdn.net/api/LuckyDraw_v2/goodLuck
两者的请求方式都是 post,且两者的 Request headers 和 Request Payload 都一样。重要参数有三个:cookie、username、uuid,cookie 参数暂时没办法解决,只能自己登陆后复制过来,username 是你的 id,可以在【个人中心】—【个人资料】—【基本信息】—【用户 ID】查看,uuid 就是 cookie 里面第一个参数 uuid_tt_dd 的值。用 Python 实现基本的签到与抽奖功能如下(此代码可直接运行,需要将 CSDN_ID 和 COOKIE 换成你的,COOKIE 可以在已经登录的任意页面 F12 获取):
import requests
import jsonCSDN_ID = '' # 你的 CSDN ID
COOKIE = '' # 你的 cookie
IF_LUCK_DRAW = True # 是否开启抽奖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 # 可抽奖次数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('签到成功!你已连续签到 {} 天,累计签到 {} 天,当前已有 {} 人签到。'.format(keep_count, total_count, total_signed_count))elif result['data']['isSigned']:print('你今天已经签到过了哟!')else:print('签到失败!')elif result['code'] == 400102:print('签到失败!{} 用户不存在或者 cookie 错误!请检查 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('抽奖成功!恭喜你获得{}'.format(prize_title))elif not result['data']['can_draw']:print('抽奖机会已经用完了哟!')else:print('抽奖失败!')elif result['code'] == 400102:print('抽奖失败!{} 用户不存在或者 cookie 错误!请检查 CSDN ID 或尝试重置 cookie!'.format(CSDN_ID))else:print('抽奖失败!')def run():c = CSDN()c.csdn_sign_in()if IF_LUCK_DRAW:c.csdn_luck_draw()if __name__ == '__main__':run()
【3x00】签到结果通知
【03x01】Server 酱
Server 酱首页:sc.ftqq.com
什么是 Server 酱?简单来说,登录 Server 酱后,会分配给你一个 SCKEY,通过向专门的 URL 发送 get 或者 post 请求,你的微信就会收到对应的消息,对于不使用企业微信和钉钉的用户来说,这种方法是最方便的。目前有标准版和 Turbo 版,据说标准版会下线,目前还能使用,所以暂时使用的是标准版。若被弃用,我会第一时间更新。实现效果:
【03x02】企业微信
如果你是一个企业微信群的群主,那么可以在群名右键添加一个机器人,添加成功后会给你一个机器人的 URL 地址,向这个 URL 发送 post 请求就可以在群里看到对应的消息,支持 markdown、text、图片等多种格式,具体可以查看机器人配置说明。
【03x03】钉钉
和企业微信类似,如果你是一个钉钉群的群主,依次右键【群设置】—【群智能助手】—【添加机器人】,选择自定义(通过webhook接入自定义访问)机器人,安全设置里面选择【加签】,添加完成后你会得到一个机器人的 Webhook URL 和一个加签的密钥,之后使用特定的算法将一些参数和 URL 组成新的 URL,再向这个 URL 发送 post 请求就可以在群里收到消息了,具体使用方法参见官方文档:https://developers.dingtalk.com/document/app/custom-robot-access
【4x00】自动签到
这里自动签到使用的是 GitHub Actions,这是 GitHub 提出的一项持续集成服务,它提供了一个高效易用的 CI/CD 工作流,能够帮助我们自动构建、测试和部署我们的代码,简单来说,对于我们的自动签到程序,它能够每天定时运行一遍,以达到每天签到的目的,如果有 cookie,密钥之类的参数,可以在仓库的 【Settings】—【Secrets】里面添加。定时任务和运行环境等其他参数统一在一个 .yml 文件中配置。
GitHub Actions 官方文档:https://docs.github.com/cn/actions
【5x00】完整代码
CSDN 签到抽奖主程序代码 CSDN.py
:
注:代码不能直接运行,这是放到 GitHub Actions 上执行的代码,使用方法见【6x00】,如果要本地运行,则需要将配置项目 1 2 3 中 os.environ["xxxxx"]
换成各自对应的值!
# ====================================
# --*-- 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 个人信息 ============== #
CSDN_ID = os.environ["CSDN_ID"] # 必填!CSDN 的 ID
COOKIE = os.environ["COOKIE"] # 必填!已登录的 cookie# ============== 2.功能开关配置项 ============== #
# 填 on 则开启,开启的同时也需要配置3中的选项,不填或填其他则关闭
IF_LUCK_DRAW = os.environ["IF_LUCK_DRAW"] # 选填!是否开启抽奖
IF_SEVER = os.environ["IF_SEVER"] # 选填!是否开启 server 酱通知
IF_WECHAT = os.environ["IF_WECHAT"] # 选填!是否开启企业微信通知
IF_DING = os.environ["IF_DING"] # 选填!是否开启钉钉通知# ============== 3.消息通知配置项 ============== #
SEVER_SCKEY = os.environ["SEVER_SCKEY"] # 选填!server 酱的 SCKEY
WECHAT_URL = os.environ["WECHAT_URL"] # 选填!企业微信机器人地址
DING_URL = os.environ["DING_URL"] # 选填!钉钉机器人地址
DING_SECRET = os.environ["DING_SECRET"] # 选填!钉钉机器人加签 SECRET# ============== 4.准备发送的消息 ============== #
TEXT = ''
DESP = ''class CSDN:def __init__(self):self.DRAW_TIMES = 0 # 可抽奖次数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 签到成功!你已连续签到 {} 天,累计签到 {} 天,当前已有 {} 人签到。'.format(keep_count, total_count, total_signed_count)print('签到成功!你已连续签到 {} 天,累计签到 {} 天,当前已有 {} 人签到。'.format(keep_count, total_count, total_signed_count))elif result['data']['isSigned']:TEXT = 'CSDN 签到失败!'DESP = 'CSDN 签到失败!你今天已经签到过了哟!'print('你今天已经签到过了哟!')else:TEXT = 'CSDN 签到失败!'print('签到失败!')elif result['code'] == 400102:TEXT = 'CSDN 签到失败!'DESP = 'CSDN 签到失败!{} 用户不存在或者 cookie 错误!请检查 CSDN ID 或尝试重置 cookie!'.format(CSDN_ID)print('签到失败!{} 用户不存在或者 cookie 错误!请检查 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 抽奖成功!'DESP += '抽奖成功!恭喜你获得{}'.format(prize_title)print('抽奖成功!恭喜你获得{}'.format(prize_title))elif not result['data']['can_draw']:TEXT += 'CSDN 抽奖失败!'DESP += 'CSDN 抽奖失败!抽奖机会已经用完了哟!'print('抽奖机会已经用完了哟!')else:TEXT += 'CSDN 抽奖失败!'print('抽奖失败!')elif result['code'] == 400102:TEXT = 'CSDN 抽奖失败!'DESP = 'CSDN 抽奖失败!{} 用户不存在或者 cookie 错误!请检查 CSDN ID 或尝试重置 cookie!'.format(CSDN_ID)print('抽奖失败!{} 用户不存在或者 cookie 错误!请检查 CSDN ID 或尝试重置 cookie!'.format(CSDN_ID))else:TEXT += 'CSDN 抽奖失败!'print('抽奖失败!')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 }}
所需环境 requirements.txt
:
requests
【6x00】如何使用
【06x01】方法一:直接 Fork 代码(推荐)
代码地址:https://github.com/TRHX/CSDNSignIn
点击右上角【Fork】代码到你的账户,然后点击【Settings】—【Secret】—【New repository secret】,依次填入以下 Name 以及对应的 Value:
Name | 是否为必填项 | 含义 | Value 示例 |
---|---|---|---|
CSDN_ID | 是 | CSDN 的 ID | qq_36759224 |
COOKIE | 是 | 已登录的 cookie | uuid_tt_dd=10_287647… |
IF_LUCK_DRAW | 否 | 是否开启抽奖 | on |
IF_SEVER | 否 | 是否开启 server 酱通知 | on |
IF_WECHAT | 否 | 是否开启企业微信通知 | on |
IF_DING | 否 | 是否开启钉钉通知 | on |
SEVER_SCKEY | 取决于 IF_SEVER | server 酱的 SCKEY | SCU165692T… |
WECHAT_URL | 取决于 IF_WECHAT | 企业微信机器人地址 | https://qyapi.weixin.qq.com/cgi-bin/webhook/… |
DING_URL | 取决于 IF_DING | 钉钉机器人地址 | https://oapi.dingtalk.com/robot/send… |
DING_SECRET | 取决于 IF_DING | 钉钉机器人加签 SECRET | SEC1cb948ba… |
举例:我需要开启抽奖和 server 酱通知,则需要填的有:
Name | Value |
---|---|
CSDN_ID | qq_36759224 |
COOKIE | uuid_tt_dd=10_287647… |
IF_LUCK_DRAW | on |
IF_SEVER | on |
SEVER_SCKEY | SCU165692T… |
如果你需要更改每天签到的时间,则需要更改 .github/workflows/csdn-sign-in.yml
文件里面 cron: 0 16 * * *
的值,这里使用的是 Linux crontab 定时任务命令,0 16 * * *
表示每天凌晨运行一次,注意这里使用的是 UTC 国际标准时间,与北京时间相差 8 个小时,所以 UTC 时间 16 点也就是北京时间的 24 点。
注意:
-
cookie 的值需要你登录后 F12 查看复制过来,cookie 的有效期是多久暂时不得而知,等下次失效了我再回来告诉你们有效期是多久,如果我没说,那就代表一直没失效!😁 -
经过测试,cookie 的有效期在 45 天左右,失效后需要重新复制一个新 cookie 过来!
-
如果你开启了自动抽奖,程序会识别你当前还有多少次抽奖次数,如果抽奖次数为0,则仍然不执行抽奖任务!
【06x01】方法二:自己上传代码
将【5x00】完整代码中的 CSDN.py
以及所需环境 requirements.txt
上传到自己的 GitHub 仓库,点击仓库的 【Actions】,选择【Python application】,点击【Set up this workflow】创建工作流,之后会出来一个 python-app.yml
,参考【5x00】完整代码中的 csdn-sign-in.yml
,添加定时任务和参数配置,编辑完成后点击【Start commit】提交。
当然也可以直接在本地编写好配置文件 csdn-sign-in.yml
直接和源码一起提交,GitHub 会自动识别,注意路径为:.github\workflows\csdn-sign-in.yml
。
以上步骤完成之后,再参考步骤【06x01】,完成参数设置即可。