使用python实现了一个力扣每日一题每天自动邮件提醒的小爬虫,小但实用!!!


文章目录

  • A.需求来源与分析
  • B.技术角度分析
  • C.具体分析步骤
    • 1.接口协议分析
    • 2.发邮件
    • 3.写crontab放服务器上定时跑
  • D.成品
    • 1.源代码
    • 2.效果
    • 3.使用说明
  • 免责申明

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

D.成品

1.源代码

lc-day-title.py,自动采集每日一题的数据并发邮件提醒:

import requests,json,timesession = 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 {dateuserStatusquestion {questionIdfrontendQuestionId: questionFrontendIddifficultytitletitleCn: translatedTitletitleSlugpaidOnly: isPaidOnlyfreqBarisFavoracRatestatussolutionNumhasVideoSolutiontopicTags {namenameTranslated: translatedNameid}extra {topCompanyTags {imgUrlslugnumSubscribed}}}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) {questionIdquestionFrontendIdcategoryTitleboundTopicIdtitletitleSlugcontenttranslatedTitletranslatedContentisPaidOnlydifficultylikesdislikesisLikedsimilarQuestionscontributors {usernameprofileUrlavatarUrl__typename}langToValidPlaygroundtopicTags {nameslugtranslatedName__typename}companyTagStatscodeSnippets {langlangSlugcode__typename}statshintssolution {idcanSeeDetail__typename}statussampleTestCasemetaDatajudgerAvailablejudgeTypemysqlSchemasenableRunCodeenvInfobook {idbookNamepressNamesourceshortDescriptionfullDescriptionbookImgUrlpressImgUrlproductUrl__typename}isSubscribedisDailyQuestiondailyRecordStatuseditorTypeugcQuestionIdstyleexampleTestcasesjsonExampleTestcases__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_mailsend_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'])

mail.py,用于发邮件:

import smtplib
from email.mime.text import MIMEText
from email.header import Headerdef init_con():# 创建 SMTP 对象smtp = smtplib.SMTP()# 连接(connect)指定服务器smtp.connect("smtp.qq.com", port=25)# 登录,需要:登录邮箱和授权码smtp.login(user="***", password="***")return smtpdef 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())

2.效果

每日一题来咯!!!

3.使用说明

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


免责申明

本文仅供技术交流学习使用,严禁使用于任何商业用途,若有任何侵权行为请联系我删除!


ATFWUS 2022-12-05

【爬虫】力扣每日一题每天自动邮件提醒!!!相关推荐

  1. 力扣每日一题每天自动邮件提醒

    A.需求来源与分析 需求来源于生活,对于只是偶尔有兴趣做做题的我,力扣的每日一题对我一直有以下的不便: 太简单不想做,需要花太多时间的不想做,每天打开力扣其实只是想看一下是什么题,有意思才做. 看题需 ...

  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. 4G EPS 中建立 UE 和 MME 之间的 NAS(非接入服务)信令连接
  2. Linux/Unix the definition of cpu-nice
  3. Gradle不匹配报错的终极大招(gradle插件版本和gradle版本对应关系)
  4. HDU 3507 Print Article(斜率优化DP)
  5. 【机器学习】数据挖掘算法——关联规则(三),FP-growth算法
  6. 第四届数据科学国际会议(ICDS2017)将于5月在上海召开
  7. 我最开始学dancing link的HTML5的时候
  8. 谈论源码_当我们谈论开放音乐时,我们指的是什么?
  9. php 5.6 闭包,PHP 闭包那点事儿
  10. 《Linux》美轮美奂的Arch, 详解Arch虚拟机安装
  11. DHCP服务原理(转载)
  12. LeetCode_88、合并两个数组(python)
  13. 适用于ActiveX v18.6 x86的Codejock Xtreme Suite Pro
  14. 微信公众号如何做推送?微信日常图文推送怎么做?
  15. C/C++编程:仿函数
  16. 怎样学手机拼音打字html t=45,在手机上怎么学拼音打字
  17. 修复iPhone8白屏的3种方法,可保留设备数据
  18. Androi开发基础
  19. 手把手带你使用EFR32 -- 土壤湿度传感器变身第二形态,以 ZigBee 形态出击
  20. 机器学习、深度学习面试知识点汇总

热门文章

  1. 关于高压开关柜在线测温方案的应用探讨
  2. 高通手机基带镜像解压混合基带制作教程(A850K工程机混合基带解决通话黑屏)
  3. anaconda中安装xgboost_ML学习笔记之Anaconda中命令形式安装XGBoost(pip install)
  4. 福禄克FLUKE 438-II与435-II电能质量及电机效率分析仪主要特性
  5. Echarts实现空气质量仪表盘网页
  6. VS各个版本下载地址
  7. Qt开源版 vs 商业版
  8. eis电子防抖好还是光学防抖好_“快板声”带来的科普 手机镜头防抖模组有哪些...
  9. 别踩白块java程序代码_用Java实现别踩白块游戏,白块、黑块适合用哪个组建来实现...
  10. 制作自己的ui组件库