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

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

时间 版本 修改人 描述
2024年4月3日11:13:50 V0.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实现,基本功能是将标题

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

修改成

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

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

python 复制代码
# -*- 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 查询出每年的今天所撰写的笔记。

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

相关推荐
汇能感知3 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun3 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao4 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾4 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT4 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
ST.J5 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin5 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全
小憩-6 小时前
【机器学习】吴恩达机器学习笔记
人工智能·笔记·机器学习
UQI-LIUWJ6 小时前
unsloth笔记:运行&微调 gemma
人工智能·笔记·深度学习
googleccsdn6 小时前
ESNP LAB 笔记:配置MPLS(Part4)
网络·笔记·网络协议