热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

使用python实现了一个力扣每日一题每天自动邮件提醒的小爬虫,小但实用!!!文章目录A.需求来源与分析B.技术角度分析C.





使用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,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'''
题目名称&#xff1a;{id}.{title}&nbsp&nbsp&nbsp&nbsp&nbsp题目难度&#xff1a;<strong>{difficulty}</strong>&nbsp&nbsp&nbsp&nbsp&nbspAC率&#xff1a;{ac_rate}&nbsp&nbsp&nbsp&nbsp&nbsp题目链接&#xff1a;<a href&#61;"{url}">{url}</a><br>
题目标签&#xff1a;{tags_str}<br>
{content}
&#39;&#39;&#39;.strip()
print(generate_plain())
from mail import send_mail
send_mail(subject&#61;generate_subject(), plain&#61;generate_plain())
sf &#61; get_today_question()
s &#61; get_one_question(sf[&#39;data&#39;][&#39;todayRecord&#39;][0][&#39;question&#39;][&#39;titleSlug&#39;])
send_to_mail(s, sf[&#39;data&#39;][&#39;todayRecord&#39;][0][&#39;question&#39;])

mail.py&#xff0c;用于发邮件&#xff1a;

import smtplib
from email.mime.text import MIMEText
from email.header import Header
def init_con():
# 创建 SMTP 对象
smtp &#61; smtplib.SMTP()
# 连接&#xff08;connect&#xff09;指定服务器
smtp.connect("smtp.qq.com", port&#61;25)
# 登录&#xff0c;需要&#xff1a;登录邮箱和授权码
smtp.login(user&#61;"***", password&#61;"***")
return smtp
def send_mail(subject, plain):
smtp &#61; init_con()
# 构造MIMEText对象&#xff0c;参数为&#xff1a;正文&#xff0c;MIME的subtype&#xff0c;编码方式
message &#61; MIMEText(plain, &#39;html&#39;, &#39;utf-8&#39;)
message[&#39;From&#39;] &#61; Header("Leetcode 每日一题提醒 By ATFWUS", &#39;utf-8&#39;) # 发件人的昵称
message[&#39;To&#39;] &#61; Header("ATFWUS", &#39;utf-8&#39;) # 收件人的昵称
message[&#39;Subject&#39;] &#61; Header(subject, &#39;utf-8&#39;) # 定义主题内容
smtp.sendmail(from_addr&#61;"***", to_addrs&#61;"***", msg&#61;message.as_string())

2.效果

每日一题来咯&#xff01;&#xff01;&#xff01;

请添加图片描述请添加图片描述


3.使用说明

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

在这里插入图片描述




免责申明

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





ATFWUS 2022-12-05








推荐阅读
  • django项目中使用手机号登录
    本文使用聚合数据的短信接口,需要先获取到申请接口的appkey和模板id项目目录下创建ubtils文件夹,定义返回随机验证码和调取短信接口的函数function.py文件se ... [详细]
  • 本文详细介绍了Python的multiprocessing模块,该模块不仅支持本地并发操作,还支持远程操作。通过使用multiprocessing模块,开发者可以利用多核处理器的优势,提高程序的执行效率。 ... [详细]
  • Python Requests模块中的身份验证机制
    随着Web服务的发展,身份验证成为了确保数据安全的重要环节。本文将详细介绍如何利用Python的Requests库实现不同类型的HTTP身份验证,包括基本身份验证、摘要式身份验证以及OAuth 1认证等。 ... [详细]
  • 利用Selenium框架解决SSO单点登录接口无法返回Token的问题
    针对接口自动化测试中遇到的SSO单点登录系统不支持通过API接口返回Token的问题,本文提供了一种解决方案,即通过UI自动化工具Selenium模拟用户登录过程,从浏览器的localStorage或sessionStorage中提取Token。 ... [详细]
  • SecureCRT 使用指南与技巧
    本文详细介绍 SecureCRT 软件的基本功能,并分享了一些实用的操作技巧,旨在帮助用户提高远程管理效率。 ... [详细]
  • 使用Objective-C实现苹果官方NSLayoutConstraint页面布局
    本文详细介绍了如何在iOS开发中使用Objective-C语言通过NSLayoutConstraint来实现页面布局。示例代码展示了如何创建和应用约束,以确保界面元素能够正确地响应不同屏幕尺寸的变化。 ... [详细]
  • 本文介绍了一种算法,用于在一个给定的二叉树中找到一个节点,该节点的子树包含最大数量的值小于该节点的节点。如果存在多个符合条件的节点,可以选择任意一个。 ... [详细]
  • 本文探讨了SQLAlchemy ORM框架中如何利用外键和关系(relationship)来建立表间联系,简化复杂的查询操作。通过示例代码详细解释了relationship的定义、使用方法及其与外键的相互作用。 ... [详细]
  • Fiddler 安装与配置指南
    本文详细介绍了Fiddler的安装步骤及配置方法,旨在帮助用户顺利抓取用户Token。文章还涵盖了一些常见问题的解决方案,以确保安装过程顺利。 ... [详细]
  • 自然语言处理(NLP)——LDA模型:对电商购物评论进行情感分析
    目录一、2020数学建模美赛C题简介需求评价内容提供数据二、解题思路三、LDA简介四、代码实现1.数据预处理1.1剔除无用信息1.1.1剔除掉不需要的列1.1.2找出无效评论并剔除 ... [详细]
  • DVWA学习笔记系列:深入理解CSRF攻击机制
    DVWA学习笔记系列:深入理解CSRF攻击机制 ... [详细]
  • Django框架进阶教程:掌握Ajax请求的基础知识与应用技巧
    本教程深入探讨了Django框架中Ajax请求的核心概念与实用技巧,帮助开发者掌握异步数据交互的方法,提升Web应用的响应速度和用户体验。通过实例解析,详细介绍了如何在Django项目中高效实现Ajax请求,涵盖从基础配置到复杂场景的应用。 ... [详细]
  • 中间件的概念中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实 ... [详细]
  • 在尝试使用 Android 发送 SOAP 请求时遇到错误,服务器返回 '无法处理请求' 的信息,并指出某个值不能为 null。本文探讨了可能的原因及解决方案。 ... [详细]
  • 在Django中提交表单时遇到值错误问题如何解决?
    在Django项目中,当用户提交包含多个选择目标的表单时,可能会遇到值错误问题。本文将探讨如何通过优化表单处理逻辑和验证机制来有效解决这一问题,确保表单数据的准确性和完整性。 ... [详细]
author-avatar
我的
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有