背景
经常写 leetcode 的题解博客,博客中的很多模块逐渐固定下来,形式逐渐趋同。除了思路部分,剩下的部分都是复制粘贴的重复性工作,一直想着写一个脚本出来(一直懒得做 😛),今天终于终于把它做出来了。
脚本思路
主要参考的 leetcode每日一题信息抓取 早安语录 定时任务 中的 抓取leetcode每日一题数据
部分的代码。根据这部分提供的题目数据,然后按照我的题解博客的形式,生成了一个模板字符串放到剪切板中。
快速使用
不加参数默认是每日一题。执行结束后会将 博客模板内容字符串 放到剪贴板中,直接打开 CSDN 写文章,粘贴即可。PS: 博客模板内容的最后一行是博客题目。
python leet_everyday.py
不只是每日一题,提供每道题url(https://leetcode-cn.com/problems/two-sum/
)后面的题目名(two-sum
)作为命令行参数(-t
或 -title
),即可得到特定题目的模板。
python leet_everyday.py -t two-sum
python 代码
# coding=<encoding name> : # coding=utf-8
from datetime import datetime
import requests
import json
import smtplib
from email.mime.text import MIMEText
import pyperclip
import re
import argparse
parser = argparse.ArgumentParser(description='Test for argparse')
parser.add_argument('--title', '-t', help='题名,非必要参数,默认每日一题', default='EVERYDAY')
args = parser.parse_args()
class Leetcode(object):
"""docstring for Leetcode"""
def __init__(self, arg):
super(Leetcode, self).__init__()
self.arg = arg
self.base_url = 'https://leetcode-cn.com'
def get_problem_jsonText_by_title(self, leetcodeTitle):
# 获取今日每日一题的所有信息
response = requests.post(self.base_url + "/graphql",
json={"operationName": "questionData", "variables": {"titleSlug": leetcodeTitle},
"query": "query questionData($titleSlug: String!) { question(titleSlug: $titleSlug) { questionId questionFrontendId 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 __typename }}"})
# 转化成json格式
jsonText = json.loads(response.text).get('data').get("question")
return jsonText
def get_everyday_problem_title(self):
# 获取今日每日一题的题名(英文)
response = requests.post(self.base_url + "/graphql", json={
"operationName": "questionOfToday",
"variables": {},
"query": "query questionOfToday { todayRecord { question { questionFrontendId questionTitleSlug __typename } lastSubmission { id __typename } date userStatus __typename }}"
})
leetcodeTitle = json.loads(response.text).get('data').get('todayRecord')[0].get("question").get('questionTitleSlug')
return leetcodeTitle
def blog_arch_str(self):
if self.arg['title'] == 'EVERYDAY':
leetcodeTitle = self.get_everyday_problem_title()
else :
leetcodeTitle = self.arg['title']
jsonText = self.get_problem_jsonText_by_title(leetcodeTitle)
# 题目题号
no = jsonText.get('questionFrontendId')
# 题名(中文)
leetcodeTitle_cn = jsonText.get('translatedTitle')
# 题目难度级别
level = jsonText.get('difficulty')
if level == 'Hard':
level = '困难'
elif level == 'Medium':
level = '中等'
elif level == 'Easy':
level = '简单'
else :
print("ERROR level")
exit(0)
# 题目内容
context = jsonText.get('translatedContent')
# 找出两个字符串在原始字符串中的位置
idx = [m.start() for m in re.finditer('<p> </p>', context)]
# 找出两个字符串之间的内容,将内容替换为控制符串
if idx:
context = context.replace(context[idx[0]:idx[-1]+len('<p> </p>')+1], "")
idx = [m.start() for m in re.finditer('<p> </p>', context)]
if idx:
context = context.replace(context[idx[0]:idx[-1]+len('<p> </p>')+1], "")
url = self.base_url + "/problems/" + leetcodeTitle + "/"
arch_str = f"## 链接\n[{url}]({url})\n\n## 耗时\n解题:xx min\n题解:xx min\n\n## 题意\n{context}\n\n## 思路\n\n\n时间复杂度:$O()$\n\n## AC代码\n```cpp\n\n```"
blog_title = f"【leetcode】{no}. {leetcodeTitle_cn}({leetcodeTitle})()[{level}]"
arch_str = arch_str + "\n\n" + blog_title
return arch_str
def main():
lc = Leetcode({'title':args.title})
arch_str = lc.blog_arch_str()
pyperclip.copy(arch_str)
# print(arch_str)
if __name__ == '__main__':
main()
参考
爬虫部分
字符串处理部分
- Python String Formatting Best Practices (在字符串里嵌入变量)
- 关于python:如何查找所有出现的子字符串? (正则找
<p> </p>
,为了去掉 示例 部分) - python | 删除两个指定字符串之间的内容