04-03 周三 使用印象笔记API批量更新笔记标题

04-03 周三 使用印象笔记API批量更新笔记标题
时间版本修改人描述
2024年4月3日11:13:50V0.1宋全恒新建文档

简介

安利印象笔记

 在阅读这篇博客之前,首先给大家案例一下印象笔记这个应用,楼主之前使用onenote来记录自己的生活的,也记录了许多的内容,但是,有一天自己的同事和自己说了印象笔记这个工具,然后在使用了之后,就发现确实是不错的,包括模板功能啊,大纲,XMind支持,以及剪藏功能,而且在多个终端可以非常方便的同步,而且每个笔记有300M的空间(超级用户),最新的印象笔记也上线了视图功能,让自己非常的方便。

 这样让自己的复盘非常的便利,因为自己已经基本养成了周盘、月盘、年盘的习惯了

 我们每天都有不同的生活,而生活是需要记录的,当时间过去之后,如果我们忘记了当时的心情,当时的事情也是有些遗憾的事。所以呢,建议大家养成记录的习惯,记录自己的开心和不快,记录自己的挣扎和痛苦,然后通过不断的反省,然后让自己辽阔。因为

痛苦 + 反思 = 进步

 这是瑞·达利欧在原则中所说的话。还是很受益的。

问题

 印象笔记写了很多年,也有了7000多条记录了,当然不仅仅是自己的日记笔记,也有通过剪藏收集的关于专业的内容,主要是包括

  • 专业程序类,
  • 戒色修身,改过迁善的文章
  • 日记,当然也有许多自己的经历和看法,

 主要是比较真实的。都真实的记录了自己的人生过去。然后在使用过程中,自己发现在手机和app端有一个功能那年今日,可以把过去的每一年的今天写的日记给重新显示(手机的助手),可遗憾的是,电脑端没有这个功能。怎么能够在电脑端印象笔记快速的检索出来那年今日的文章呢?

 在之前的时候,自己主要是使用created:这个快捷键智能检索,根据笔记的创建时间来过滤出来那年今日的内容,这样就形成了下面的解决方案:

 但是这种方式有问题,第一,就是得每年新增一个这样的搜索,第二就是在查询的时候,必须挨个点击,而我又是一个高级的程序猿,忍受不了这种低效的方式。所以我应该怎么解决这个问题呢?

 就是有一天工作的时候突然想到,自己可以接入印象笔记的API吧,然后使用印象笔记的高级检索intitle:04-03这样只要输入今天的日期,就可以检索笔记标题中含有04-03的内容了,哈哈,当时因为这个念头就很兴奋。因为之前没有想到使用API,就一直手动修改,但是7000多条笔记真的修改起来太机械(mechanic),太枯燥了。本篇文章就是记录了使用API批量修改笔记标题的过程的过程。

前提

  • 印象笔记的API库,由于楼主最近使用Python,因此,使用Python的印象API,即ever-sdk-python,需要注意的是,只支持Python2.7
  • 官方提供的Quciker start可以参考, 关于沙盒 和Evernote API key,如果你是修改自己的笔记,则是不需要的。
  • 需要Developer Token,进入该网站生成TOken
  • Python SDK参考目录 API Reference,具体如下所示:

代码片段

 程序使用Python实现,基本功能是将标题

完成GitHub自托管运行器的实践,发表印象笔记博客

修改成

04-03 完成GitHub自托管运行器的实践,发表印象笔记博客

 当然日期,根据笔记的创建日期进行转换

# -*- coding: utf-8 -*-
#
# A simple Evernote API demo script that lists all notebooks in the user's
# account and creates a simple test note in the default notebook.
#
# Before running this sample, you must fill in your Evernote developer token.
#
# To run (Unix):
#   export PYTHONPATH=../../lib; python EDAMTest.py
#

import hashlib
import binascii
import evernote.edam.userstore.constants as UserStoreConstants
import evernote.edam.type.ttypes as Types
from evernote.edam.notestore.ttypes import NoteFilter, NotesMetadataResultSpec


from evernote.api.client import EvernoteClient
import codecs

# Real applications authenticate with Evernote using OAuth, but for the
# purpose of exploring the API, you can get a developer token that allows
# you to access your own Evernote account. To get a developer token, visit
# https://SERVICE_HOST/api/DeveloperToken.action
#
# There are three Evernote services:
#
# Sandbox: https://sandbox.evernote.com/
# Production (International): https://www.evernote.com/
# Production (China): https://app.yinxiang.com/
#
# For more information about Sandbox and Evernote China services, please 
# refer to https://dev.evernote.com/doc/articles/testing.php 
# and https://dev.evernote.com/doc/articles/bootstrap.php
    

from datetime import datetime

def get_time_str(timestamp):
    # 将时间戳转换为datetime对象  # 注意时间戳是毫秒,需要除以1000转换为秒
    dt_object = datetime.utcfromtimestamp(timestamp / 1000) 

    # 定义日期格式
    date_format = "%Y-%m-%d %H:%M:%S"

    # 格式化日期
    formatted_date = dt_object.strftime(date_format)

    # 打印结果
    return formatted_date

import re
def is_data_prefix_with_space(title):
    """
    检查标题的前六位字符是否符合日期格式(dd-mm)。并且包含一个空格

    参数:
    title (str): 需要检查格式的标题字符串。

    返回:
    bool: 如果标题的前六位字符符合日期格式,返回 True;否则返回 False。
    """
    # 正则表达式匹配前六位是否为两位数字-两位数字
    pattern = r'^\d{2}-\d{2} '
    if re.match(pattern, title[:6]):  # 限制检查的字符串长度为6
        return True
    
    if re.match("^\d{2}-\d{2}", title[:5]) and len(title.strip())==5:
        return True
    return False
    
def is_data_prefix_without_space(title):
    """
    检查标题的前六位字符是否符合日期格式(dd-mm)。并且包含一个空格

    参数:
    title (str): 需要检查格式的标题字符串。

    返回:
    bool: 如果标题的前六位字符符合日期格式,返回 True;否则返回 False。
    """
    # 正则表达式匹配前六位是否为两位数字-两位数字
    pattern = r'^\d{2}-\d{2}'
    if re.match(pattern, title[:6]):  # 限制检查的字符串长度为6
        return True
    else:
        return False
    
def get_title_with_date(title, timestamp_ms):
    """
    将毫秒时间戳转换为日期格式,并与标题拼接,确保标题中的日期后跟有空格。

    参数:
    title (str): 需要拼接的标题字符串。
    timestamp_ms (int): 时间戳,表示自1970年1月1日以来的毫秒数。

    返回:
    str: 转换并拼接后的字符串,格式为 "xx-xx title"。
    """
    

    # 正则表达式匹配以 "xx-xx" 开头且后面没有空格的模式
    match = re.match(r'(\d{2}-\d{2})[^\s]*', title)
    if match:
        # 如果标题符合模式,添加空格
        title = match.group(1) + " " + title[len(match.group(1)):]
        return title

    # 将毫秒时间戳转换为秒
    timestamp = timestamp_ms / 1000.0
    # 将时间戳转换为datetime对象
    dt_object = datetime.fromtimestamp(timestamp)

    # 格式化日期为 "xx-xx" 格式
    date_str = dt_object.strftime("%02m-%02d")

    # 拼接标题和日期,中间有一个空格
    formatted_title = date_str +" " + title
    return formatted_title


def write_array_to_file(array, filename='success_books.txt'):
    """
    将数组写入文件,每个元素占一行。

    参数:
    array (list): 要写入文件的数组。
    filename (str): 文件名,默认为 'success_books.txt'。
    """
    with open(filename, 'w') as file:  # 移除 encoding 参数
        for item in array:
            file.write("%s\n" % item)

def read_array_from_file(filename='success_books.txt'):
    """
    从文件中读取数组,如果文件不存在则返回空数组。

    参数:
    filename (str): 文件名,默认为 'success_books.txt'。

    返回:
    list: 从文件中读取的数组,或者空数组(如果文件不存在)。
    """
    try:
        with open(filename, 'r') as file:  # 尝试以只读模式打开文件
            array = [line.strip() for line in file.readlines()]
        return array
    except OSError:
        # 如果发生OSError异常(包括FileNotFoundError),返回空数组
        return []
    except IOError:
        # 如果发生其他IOError异常(如权限问题),也返回空数组
        return []

# 请修改为自己的auth_token,这个是楼主的无效的token
auth_token = "S=s43:U=91d3be:E=18ead076f78:C=18e88fae9a8:P=1cd:A=en-devtoken:V=2:H=d0d841403a8c584016c327591d12852"

if auth_token == "your developer token":
    print "Please fill in your developer token"
    print "To get a developer token, visit " \
        "https://sandbox.evernote.com/api/DeveloperToken.action"
    exit(1)


# To access Sandbox service, set sandbox to True 
# To access production (International) service, set both sandbox and china to False
# To access production (China) service, set sandbox to False and china to True
# 请修改
sandbox = False
china = True

# Initial development is performed on our sandbox server. To use the production
# service, change sandbox=False and replace your
# developer token above with a token from
# https://www.evernote.com/api/DeveloperToken.action
client = EvernoteClient(token=auth_token, sandbox=sandbox, china=china)

user_store = client.get_user_store()

version_ok = user_store.checkVersion(
    "Evernote EDAMTest (Python)",
    UserStoreConstants.EDAM_VERSION_MAJOR,
    UserStoreConstants.EDAM_VERSION_MINOR
)
print "Is my Evernote API version up to date? ", str(version_ok)
print ""
if not version_ok:
    exit(1)

note_store = client.get_note_store()

# List all of the notebooks in the user's account
notebooks = note_store.listNotebooks()
print "Found ", len(notebooks), " notebooks:"
for notebook in notebooks:
    success_books=read_array_from_file()
    if notebook.guid in success_books:
        continue
    print "notebook name:",notebook.name," notebook guid: ", notebook.guid
    print "--------------------------------------------------------------"
    filter = NoteFilter()
    filter.notebookGuid = notebook.guid
    
    result_spec = NotesMetadataResultSpec()
    result_spec.includeTitle=True
    result_spec.includeCreated=True
    notes_metadata_list = note_store.findNotesMetadata(filter, 0, 1000, result_spec)
    print "totalNotes:", notes_metadata_list.totalNotes
    
    for note in notes_metadata_list.notes:
        if is_data_prefix_with_space(note.title):
            continue
        old_title = note.title
        new_title = get_title_with_date(note.title, note.created)
        note.title = new_title
        print "Modify title From", old_title.ljust(50, ' '), "  To    ", new_title.ljust(50, ' ')
        note_store.updateNote(auth_token, note)
    print "--------------------------------------------------------------"
    print "notebook name:",notebook.name,"处理完成"
    success_books.append(notebook.guid)
    write_array_to_file(success_books)
    


# # To create a new note, simply create a new Note object and fill in
# # attributes such as the note's title.
# note = Types.Note()
# note.title = "Test note from EDAMTest.py"

# # To include an attachment such as an image in a note, first create a Resource
# # for the attachment. At a minimum, the Resource contains the binary attachment
# # data, an MD5 hash of the binary data, and the attachment MIME type.
# # It can also include attributes such as filename and location.
# image = open('enlogo.png', 'rb').read()
# md5 = hashlib.md5()
# md5.update(image)
# hash = md5.digest()

# data = Types.Data()
# data.size = len(image)
# data.bodyHash = hash
# data.body = image

# resource = Types.Resource()
# resource.mime = 'image/png'
# resource.data = data

# # Now, add the new Resource to the note's list of resources
# note.resources = [resource]

# # To display the Resource as part of the note's content, include an <en-media>
# # tag in the note's ENML content. The en-media tag identifies the corresponding
# # Resource using the MD5 hash.
# hash_hex = binascii.hexlify(hash)

# # The content of an Evernote note is represented using Evernote Markup Language
# # (ENML). The full ENML specification can be found in the Evernote API Overview
# # at http://dev.evernote.com/documentation/cloud/chapters/ENML.php
# note.content = '<?xml version="1.0" encoding="UTF-8"?>'
# note.content += '<!DOCTYPE en-note SYSTEM ' \
#     '"http://xml.evernote.com/pub/enml2.dtd">'
# note.content += '<en-note>Here is the Evernote logo:<br/>'
# note.content += '<en-media type="image/png" hash="' + hash_hex + '"/>'
# note.content += '</en-note>'

# Finally, send the new note to Evernote using the createNote method
# The new Note object that is returned will contain server-generated
# attributes such as the new note's unique GUID.
#created_note = note_store.createNote(note)

# print "Successfully created a new note with GUID: ", created_note.guid

代码解读

修改部分

 要设置自己的auth_token,并且,不需要使用沙盒并且使用国内印象笔记服务。

程序主题流程

代码执行效果

总结

 手动修改,真的太痛苦了,通过程序来解决问题,真香。

 通过上述的过程,就可以将所有的笔记标题均修改成包含日期的标题了,这样只要保证以后在写日记或剪藏的时候,手动添加上标题,就可以保持一致性了,这样整体就非常的方便了。轻轻松松可以实现通过intitle:04-03 查询出每年的今天所撰写的笔记。

 还是那句话,无论过去每个人多么的痛苦和难以接受,无论现状多么糟糕和难以忍受,但是我们就是踏着那样的道路走到了现在的样子,不抗拒,不抱怨,接纳然后从记录中获取问题,分析问题,然后解决问题,这或许就是成长的样子吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/543474.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UI设计规范

一套商城系统的诞生&#xff0c;除了代码的编写&#xff0c;UI设计也至关重要。UI设计关系到商城系统的最终呈现效果&#xff0c;关乎整体商城的风格展现&#xff0c;如果UI设计做不好&#xff0c;带来的负面影响也是不容小觑的。 1、在很多商城系统开发中&#xff0c;有时会有…

基于Java+Vue的校园代购服务管理系统(源码+文档+包运行)

一.系统概述 在新发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且学生越来越追求更个性的需求。在这种时代背景下&#xff0c;学生对校园代购服务订单管理越来越重视&#xff0c;更好的实现校园代购服务的有效发挥&#xf…

YOLTV8 — 大尺度图像目标检测框架(欢迎star)

YOLTV8 — 大尺度图像目标检测框架【ABCnutter/YOLTV8: &#x1f680;】 针对大尺度图像&#xff08;如遥感影像、大尺度工业检测图像等&#xff09;&#xff0c;由于设备的限制&#xff0c;无法利用图像直接进行模型训练。将图像裁剪至小尺度进行训练&#xff0c;再将训练结果…

Redis-更新策略,缓存穿透,缓存雪崩,缓存击穿

Redis-更新策略,缓存穿透,缓存雪崩,缓存击穿 1.缓存更新 策略 淘汰策略超时剔除主动更新 更新策略&#xff1a;先修改数据库还是先删除缓存 结论&#xff1a;先修改数据库&#xff0c;因为缓存的操作比较快&#xff0c;容易产生数据不一致更新缓存还是删除缓存&#xff1f; …

强化学习-Reinforcement learning | RL

目录 什么是强化学习? 强化学习的应用场景 强化学习的主流算法 强化学习是机器学习的一种学习方式,它跟监督学习、无监督学习是对应的。本文将详细介绍强化学习的基本概念、应用场景和主流的强化学习算法及分类。 什么是强化学习? 强化学习并不是某一种特定的算法,而是…

2001-2022年上市公司异常审计费用指标包含原始数据 参考顶刊文献含构造过程Stata代码

01、数据介绍 异常审计费用则是指实际审计费用超过或低于正常审计费用的部分&#xff0c;该部分审计费用受不可观测因素的影响&#xff0c;可能来源于审计师所付出的额外努力或者审计师与被审计单位间的特殊关系&#xff0c;也可能产生于被审计单位在审计买方市场中的优势地位…

(学习日记)2024.04.17:UCOSIII第四十五节:中断管理

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

【操作系统专题】详解操作系统 | 操作系统的目标和功能 | 操作系统如何工作

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1.操作系统的目标和功能2…

【菜狗学前端】原生Ajax笔记(包含原生ajax的get/post传参方式、返回数据等)

这回图片少&#xff0c;给手动替换了~祝看得愉快&#xff0c;学的顺畅&#xff01;哈哈 一 原生ajax经典四步 (一) 原生ajax经典四步 第一步&#xff1a;创建网络请求的AJAX对象&#xff08;使用XMLHttpRequest&#xff09; JavaScript let xhr new XMLHttpRequest() 第二…

为什么你的LDO输出不稳定?

原文来自微信公众号&#xff1a;工程师看海&#xff0c;与我联系&#xff1a;chunhou0820 看海原创视频教程&#xff1a;《运放秘籍》 大家好&#xff0c;我是工程师看海。 前一阵朋友和我说当初用某型号LDO时&#xff0c;发现输出异常&#xff0c;仔细阅读datasheet后&#x…

Clip下游任务解读

相关代码链接见文末 1.DALL-1 (1)VQGAN https://arxiv.org/pdf/2012.09841.pdf VQGAN(Vector Quantized Generative Adversarial Networks)是一种基于向量化量化的生成对抗网络。这种技术首先将图像转换为一系列向量,每个向量代表图像中的一小块区域(或称为“patch”)。…

在Mac上更好的运行Windows,推荐这几款Mac虚拟机 mac运行windows虚拟机性能

想要在Mac OS上更好的运行Windows系统吗&#xff1f;推荐你使用mac虚拟机。虚拟机通过生成现有操作系统的全新虚拟镜像&#xff0c;它具有真实windows系统完全一样的功能&#xff0c;进入虚拟系统后&#xff0c;所有操作都是在这个全新的独立的虚拟系统里面进行&#xff0c;可以…

Linux的文件操作中的静态库的制作

Linux操作系统支持的函数库分为&#xff1a; 静态库&#xff0c;libxxx.a&#xff0c;在编译时就将库编译进可执行程序中。 优点&#xff1a;程序的运行环境中不需要外部的函数库。 缺点&#xff1a;可执行程序大 &#xff08;因为需要 编译&#xff09; 动态库&#xff0c…

自动化测试Junit

1.什么是Junit JUint是Java编程语言的单元测试框架&#xff0c;用于编写和运行可重复的自动化测试。 JUnit 促进了“先测试后编码”TDD的理念&#xff0c;强调建立测试数据的一段代码&#xff0c;可以先测试&#xff0c;然后再应用。这个方法就好比“测试一点&#xff0c;编码一…

Qt QProcess详解

1.简介 QProcess提供了在 Qt 应用程序中启动外部程序的方法。通过QProcess&#xff0c;你可以启动一个进程&#xff0c;与它通信&#xff08;发送输入和读取输出&#xff09;&#xff0c;检查它的状态&#xff0c;以及等待它完成。这个类在执行系统命令、运行其他程序或脚本时…

Leetcode 394. 字符串解码

心路历程&#xff1a; 这道题看到括号直接想到栈&#xff0c;五分钟新题直接秒了&#xff0c;一开始以为需要两个栈分别存储数字和非数字&#xff0c;后来发现一个栈就够了&#xff0c;思路如图&#xff1a; 这道题考察的应该是队栈这两种数据结构的转换&#xff0c;因为每次…

LangChain - 文档加载

文章目录 一、关于 检索二、文档加载器入门指南 三、CSV1、使用每个文档一行的 CSV 数据加载 CSVLoader2、自定义 csv 解析和加载 &#xff08;csv_args3、指定用于 标识文档来源的 列&#xff08;source_column 四、文件目录 file_directory1、加载文件目录数据&#xff08;Di…

缺少vcruntime140_1.dll

windows安装mysql的时候错误提示&#xff1a; 64位下载安装&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1u_ALo0JMc-Y2an22l1Y1EA 提取码&#xff1a;ve10 32位下载安装&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/16XTt642Tj-Oc-WvbgQK-Ww 提取码…

学校4-11天梯赛选拔赛

目录 L1-5 6翻了 题目 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 思路 AC代码 L1-1 嫑废话上代码 题目 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; AC代码 L1-8 刮刮彩…

MySQL_00001_00000

数据准备 员工表&#xff1a;emp Oracle: create table emp ( empno number(4) not null, ename varchar2(10), job varchar2(9), mgr number(4), hiredate date, sal number(7, 2), comm number(7, 2), deptno number(2) ); insert into em…