A.需求来源与分析
需求来源于生活,对于只是偶尔有兴趣做做题的我,力扣的每日一题对我一直有以下的不便:

太简单不想做,需要花太多时间的不想做,每天打开力扣其实只是想看一下是什么题,有意思才做。
看题需要打开电脑,而且打开电脑也不一定记得要去看看题,要是能把每日一题直接推送到我邮箱里就好了,这样每天起床的时候就能在手机的邮箱里看一看每日一题,如果确实有意思,再打开电脑的时候去做。
有几天没做后,甚至会忘记力扣的每日一题这件事情,然后就是很长一段时间不会去做题。
其实有些需求主要是因为我懒(bushi),但是,程序员要学会偷懒!于是我简单整理了一下我的需求:

每天早上的某个时候(最好是我起床的时候),能把每日一题推送到我的邮箱。
我能直接通过邮箱看到题目什么难度、考察哪些点、题目的内容,并且能直接点一下就进入题目。
说干就干,开工!于是花了一点时间把这样一个小玩意儿弄出来了。

B.技术角度分析
其实这件事情很简单,我只需要分析出力扣上每日一题的接口,然后写个python脚本把题目信息拿到,然后用smtp协议给我自己发封邮件即可,将这个脚本写入我服务器的crontab上,每天早上就自己跑了。接下来按照这些部分去分析即可。

C.具体分析步骤
大致就是:分析接口协议->获取题目信息->写脚本将信息发送到我的邮箱->将这个接口写入crontab。

1.接口协议分析
开始之前先讲点武德,我们先看一下力扣的robots.txt,看看哪些是不能爬的:

然后再去抓个包,看下哪个包最后得到了每日一题的数据:

发现这个包请求的结果就是每日一题:

幸运的是,这个接口并没有在上述robots.txt中,我们可以写个脚本模拟一下这个发包,注意到请求头中有csrf-token:

稍微找一下,可以发现返回包的cookie里面就带有csrf-token,所以我们提前请求一下即可,就可以从cookie中拿到csrf-token了。
这个请求体,很明显是graphql的请求参数,仔细看一下,发现并不需要传啥参数,所以直接调用即可。

再去看一下进入题目页面时候的关键请求接口,可以找到是这个接口:

返回的数据都是json,格式化一下就可以找到关键数据。

2.发邮件
此篇若有不清楚的见下面使用说明

3.写crontab放服务器上定时跑
每天上午11点自动提醒:(替换成自己的路径)

crontab –e
0 11 * * * python3 /home/atfwus/sheduler-script/lc-today-question/lc-day-title.py
1
2
D.成品
1.源代码
lc-day-title.py,自动采集每日一题的数据并发邮件提醒:

import requests,json,time

session = requests.session()

lc_url = ‘https://leetcode.cn’
graphql_url = ‘/graphql’

def int_csrf():
session.get(lc_url + graphql_url)

int_csrf()

user_agent = r’Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36’
headers = {
‘x-requested-with’ : ‘XMLHttpRequest’,
‘accept’ : ‘/’,
‘User-Agent’: user_agent,
‘Connection’: ‘keep-alive’,
‘origin’: ‘https://leetcode.cn’,
‘Content-Type’ :‘application/json’,
‘X-Csrftoken’: session.cookies[‘csrftoken’]
}

def get_today_question():
param = ‘’’
query questionOfToday {
todayRecord {
date
userStatus
question {
questionId
frontendQuestionId: questionFrontendId
difficulty
title
titleCn: translatedTitle
titleSlug
paidOnly: isPaidOnly
freqBar
isFavor
acRate
status
solutionNum
hasVideoSolution
topicTags {
name
nameTranslated: translatedName
id
}
extra {
topCompanyTags {
imgUrl
slug
numSubscribed
}
}
}
lastSubmission {
id
}
}
}
‘’’

data = {"query": param,"variables": {}
}r = session.post(lc_url+graphql_url, headers=headers, data=json.dumps(data))
return r.json()

def get_one_question(title_slug):
param = ‘’’
query questionData($titleSlug: String!) {
question(titleSlug: $titleSlug) {
questionId
questionFrontendId
categoryTitle
boundTopicId
title
titleSlug
content
translatedTitle
translatedContent
isPaidOnly
difficulty
likes
dislikes
isLiked
similarQuestions
contributors {
username
profileUrl
avatarUrl
__typename
}
langToValidPlayground
topicTags {
name
slug
translatedName
__typename
}
companyTagStats
codeSnippets {
lang
langSlug
code
__typename
}
stats
hints
solution {
id
canSeeDetail
__typename
}
status
sampleTestCase
metaData
judgerAvailable
judgeType
mysqlSchemas
enableRunCode
envInfo
book {
id
bookName
pressName
source
shortDescription
fullDescription
bookImgUrl
pressImgUrl
productUrl
__typename
}
isSubscribed
isDailyQuestion
dailyRecordStatus
editorType
ugcQuestionId
style
exampleTestcases
jsonExampleTestcases
__typename
}
}
‘’’
data = {
“operationName”: “questionData”,
“variables”: {
“titleSlug”: title_slug
},
“query”: param
}
r = session.post(lc_url + graphql_url, headers=headers, data=json.dumps(data))
return r.json()

def send_to_mail(q, sf):
q = q[‘data’][‘question’]
id = q[‘questionFrontendId’]
title = q[‘translatedTitle’]
url = ‘https://leetcode.cn/problems/’ + q[‘titleSlug’]
ac_rate = ‘{:.2%}’.format(sf[‘acRate’])
def generate_subject():
day_str = time.strftime(‘%m月%#d日’, time.localtime(time.time()))
return f’力扣{day_str}每日一题来咯!!!({id}.{title})’
print(generate_subject())

def generate_plain():content = q['translatedContent']difficulty = q['difficulty']tags = []for i in q['topicTags']:tags.append(i['translatedName'])tags_str = ' '.join(tags)return f'''题目名称:{id}.{title}&nbsp&nbsp&nbsp&nbsp&nbsp题目难度:<strong>{difficulty}</strong>&nbsp&nbsp&nbsp&nbsp&nbspAC率:{ac_rate}&nbsp&nbsp&nbsp&nbsp&nbsp题目链接:<a href="{url}">{url}</a><br>题目标签:{tags_str}<br>{content}'''.strip()
print(generate_plain())from mail import send_mail
send_mail(subject=generate_subject(), plain=generate_plain())

sf = get_today_question()
s = get_one_question(sf[‘data’][‘todayRecord’][0][‘question’][‘titleSlug’])

send_to_mail(s, sf[‘data’][‘todayRecord’][0][‘question’])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
mail.py,用于发邮件:

import smtplib
from email.mime.text import MIMEText
from email.header import Header

def init_con():
# 创建 SMTP 对象
smtp = smtplib.SMTP()
# 连接(connect)指定服务器
smtp.connect(“smtp.qq.com”, port=25)
# 登录,需要:登录邮箱和授权码
smtp.login(user=““, password=””)

return smtp

def send_mail(subject, plain):
smtp = init_con()

# 构造MIMEText对象,参数为:正文,MIME的subtype,编码方式
message = MIMEText(plain, 'html', 'utf-8')
message['From'] = Header("Leetcode 每日一题提醒 By ATFWUS", 'utf-8')  # 发件人的昵称
message['To'] = Header("ATFWUS", 'utf-8')  # 收件人的昵称
message['Subject'] = Header(subject, 'utf-8')  # 定义主题内容smtp.sendmail(from_addr="***", to_addrs="***", msg=message.as_string())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2.效果
每日一题来咯!!!

3.使用说明
只需要修改mail.py中的邮箱和密码即可,然后将两个py文件放在云服务器上,crontab定时任务自动执行。
下面是密码的获取方式:
qq邮箱中,点设置,在这个地方找到授权码,申请授权码,并填在上面mail.py脚本的password上。

力扣每日一题每天自动邮件提醒相关推荐

  1. 【爬虫】力扣每日一题每天自动邮件提醒!!!

    使用python实现了一个力扣每日一题每天自动邮件提醒的小爬虫,小但实用!!! 文章目录 A.需求来源与分析 B.技术角度分析 C.具体分析步骤 1.接口协议分析 2.发邮件 3.写crontab放服 ...

  2. 【JAVA】交错字符串——力扣每日一题(六)(2020.07.18)

    目录 题目:97. 交错字符串 思路 如果你从本文中学习到丝毫知识,那么请您点点关注.点赞.评论和收藏 大家好,我是爱做梦的鱼,我是东北大学大数据实验班大三的小菜鸡,非常渴望优秀,羡慕优秀的人,个人博 ...

  3. leetcode 力扣每日一题系列详解——总目录

    这是总目录,该系列持续更新中........ leetcode 力扣每日一题系列详解--总目录

  4. 力扣每日一题:1720.解码异或后的数组 python异或操作

    1720.解码异或后的数组 https://leetcode-cn.com/problems/decode-xored-array/ 难度:简单 题目: 未知 整数数组 arr 由 n 个非负整数组成 ...

  5. LeetCode 力扣每日一题 488.祖玛游戏

    题目描述: 你正在参与祖玛游戏的一个变种. 在这个祖玛游戏变体中,桌面上有 一排 彩球,每个球的颜色可能是:红色 'R'.黄色 'Y'.蓝色 'B'.绿色 'G' 或白色 'W' .你的手中也有一些彩 ...

  6. 力扣每日一题——两数相加II

    发现做的题难度始终不高,今天Leecode给了一个稍微难一点的题目.(前两天没更是因为去拔牙了~~>_<~~) 给你两个 非空 链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每 ...

  7. 2022.1.4 力扣-每日一题-猫和老鼠

    题目描述: 两位玩家分别扮演猫和老鼠,在一张 无向 图上进行游戏,两人轮流行动. 图的形式是:graph[a] 是一个列表,由满足 ab 是图中的一条边的所有节点 b 组成. 老鼠从节点 1 开始,第 ...

  8. 力扣每日一题——独一无二出现的次数

    难度:简单 题目: 给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数. 如果每个数的出现次数都是独一无二的,就返回 true:否则返回 false. 示例 1: 输入:arr = [1,2 ...

  9. 【04-25】力扣每日一题

    本文首发于馆主君晓的博客,04-25每日一题 题目描述   话不多说,先放题目链接和题目截图,398.随机数索引,题目如下图所示: 题目分析   一般人看到这道题的思路就是使用哈希表去做,首先建立一个 ...

最新文章

  1. 利用OpenGL渲染并用OpenCV输出显示二维图像
  2. Java读写文件,中文乱码解决
  3. office2013安装程序找不到office.zh-cn\officeMUI.xml 最新解决方案
  4. 【SSL】openssl 提取 PKCS 证书库中的公钥、私钥、证书、密钥、CA证书
  5. 【Leetcode】113. 路径总和 II
  6. Android 串口开发——粘包解决方法,定时查询心跳数据,解析心跳数据。——持续更新中
  7. 【R】语言第二课----- 变量的使用方法
  8. Android静态代码扫描效率优化与实践
  9. 计算机二级python考试大纲2020_【2020年9月全国计算机二级Python考试大纲】- 环球网校...
  10. c#对PL/SQL查询结果列复制的结果生成指定格式
  11. 电子设计教程22:虚短与虚断
  12. hello world!——VS使用教程
  13. windows2003下ISA防火墙的安装及简单配置
  14. 带你通关全栈树型结构设计:从数据库到前端
  15. Spring 实战-第六章-渲染Web视图-6.2创建JSP视图
  16. 手机/微信/浏览器的字体设置太大,rem 计算不准确
  17. LINUX磁盘分区和添加磁盘的一些命令
  18. Ai智能语音机器人系统搭建和私有云部署
  19. PS中矢量形状图层的合并交叉等运算
  20. 远程视图 RemoteViews

热门文章

  1. JDK环境配置和eclipse安装
  2. 【有利可图网】PS教程:用PS合成立体特效的穿插照片效果
  3. TOP10 区块链游戏关注榜
  4. 媒体查询 iPad 竖屏
  5. 2.1 法学的历史(一):西方法学的历史
  6. ReactNative报错null is not an object (evaluating '_rngesturehandlermodule.default.direction')
  7. lol1月8日服务器维护,LOL1月16日更新维护公告 LOL8.1新版本更新到几点
  8. 智能手表音频特性测试_Kido × 蜻蜓FM打造音频内容营销新范本,高效精准助品牌弯道超车...
  9. 商用在线客服软件测试报告
  10. 小白鼠与毒药解题过程分析