跳转到内容

搜索

本地图片上传工具

Python 脚本
造物 更新于:

批量上传 Obsidian Vault 中的本地图片,并自动替换为远程 URL。

Obsidian Image Uploader

一个用于批量处理 Obsidian Vault 中本地图片引用的脚本工具。

它会遍历指定 Obsidian Vault 中的 Markdown 文件,查找本地图片引用,通过 PicGo Server 上传图片,并将本地图片链接替换为远程 URL。

脚本会处理整个 Markdown 文件内容,包括正文和 frontmatter。

功能

  • 遍历 Obsidian Vault 中的所有 Markdown 文件。
  • 处理整个 Markdown 文件,包括 frontmatter。
  • 支持 Obsidian 嵌入图片语法:
    • ![[image.png]]
    • ![[image.png|440]]
    • ![[image.png|440x300]]
    • ![[image.png|说明文字]]
    • ![[image.png|说明文字|440]]
  • 支持 Obsidian 普通文件链接语法:
    • [[image.png]]
    • [[image.png|别名]]
  • 支持标准 Markdown 本地图片语法:
    • ![](image.png)
    • ![alt](image.png)
  • 自动通过 PicGo Server 上传本地图片。
  • 自动将本地图片引用替换为远程 URL。
  • 支持上传前自动转换为 WebP 格式,减小图片体积。
  • 同一个实际图片文件只上传一次,后续引用复用同一个 URL。
  • 不同路径下的同名图片会被视为不同图片。
  • 支持 5 分钟配额限制自动重试(带随机抖动)。
  • 支持通过启动参数指定 Obsidian Vault 路径。
  • 支持交互式输入 Obsidian Vault 路径。

前置条件

PicGo

需要安装并配置 PicGo。

同时需要开启 PicGo Server。

默认接口地址为:

http://127.0.0.1:36677/upload

脚本中的默认配置:

PICGO_API = "http://127.0.0.1:36677/upload"

如果你的 PicGo Server 地址不同,需要修改 upload_obsidian_images.py 中的 PICGO_API

使用方式

安装 uv 后,直接运行:

uv run upload_obsidian_images.py

或运行时手动输入 obsidian 仓库路径

uv run upload_obsidian_images.py <vault path>

[!important] 重要 脚本会直接修改 Markdown 文件内容。

首次运行前,建议先使用 Git 或其他方式备份 Vault。

常见问题

PicGo Server 没有开启怎么办?

如果 PicGo Server 未开启,脚本会提示:

上传失败:无法连接 PicGo Server,请确认 PicGo Server 已开启。

请先打开 PicGo,并确认 PicGo Server 功能已开启。

如何关闭 [[file.png]] 的转换?

使用:

python upload_obsidian_images.py ~/Temp/Test --no-convert-file-links

如何处理多个同名图片更安全?

将脚本中的:

SKIP_AMBIGUOUS_WIKI_IMAGE = False

改为:

SKIP_AMBIGUOUS_WIKI_IMAGE = True

这样脚本遇到多个同名图片时会跳过,不会默认使用第一个匹配项。

如何关闭 WebP 转换?

python upload_obsidian_images.py ~/Temp/Test --no-convert-webp

上传图片时提示配额限制怎么办?

脚本内置了自动重试机制,遇到配额限制时会自动等待约 5 分钟后重试,无需手动干预。

如果希望在更短时间内上传大量图片,可以每次只处理少量 Markdown 文件,分批次运行。

配额限制与自动重试策略是怎样的?

PicGo 使用的图床通常有 5 分钟上传配额限制。脚本针对此问题内置了自动重试机制:

  • 遇到 429 / 500 / quota / rate limit 等响应时,自动等待约 5 分钟 + 随机抖动(0-30 秒),然后重试。
  • 最多重试 10 次,保证在大批量上传时能自动续传。
  • 随机抖动用于避免多个请求恰好撞在配额窗口边界。

抖动和重试次数可在脚本顶部的 MAX_UPLOAD_RETRIESRATE_LIMIT_RETRY_DELAY_SECONDSRATE_LIMIT_JITTER_SECONDS 变量中调整。

为什么带尺寸的图片会转换成 HTML?

标准 Markdown 图片语法是:

![alt](url)

其中 alt 是替代文本,不是图片宽度。

例如:

![440](url)

含义是:

<img src="url" alt="440">

而不是:

<img src="url" width="440">

因此,为了保留 Obsidian 中 ![[file.png|440]] 的渲染大小,脚本会将其转换为 HTML:

<img src="url" width="440">

Frontmatter 是否会处理?

脚本会处理整个 Markdown 文件,包括 frontmatter。

例如:

---
cover: "![[cover.png]]"
attachment: "[[file.png]]"
---

也会被转换。

示例转换结果:

---
cover: "![](https://example.com/cover.png)"
attachment: "[file.png](https://example.com/file.png)"
---

注意:frontmatter 是结构化元数据。如果某些发布系统、Dataview 查询或插件依赖原始 Obsidian 链接格式,转换前建议先确认兼容性。

同一张图片被多次引用是否导致重复上传?

脚本会缓存已经上传过的图片。

缓存 key 使用图片文件的 resolved absolute path,也就是解析后的绝对路径。

因此:

/Users/lu/Vault/assets/demo.png

如果被多个 Markdown 文件引用,只会上传一次。

后续引用会复用第一次上传得到的远程 URL。

如何处理同名图片与重复引用?

对于 Obsidian Wiki 图片引用,例如:

![[demo.png]]

脚本会在整个 Vault 中查找 demo.png

如果同一个图片文件被多个 Markdown 文件引用,脚本只会上传一次,并复用第一次上传得到的远程 URL 替换所有引用位置。

如果 Vault 中存在多个同名图片文件,例如:

assets/demo.png
notes/project-a/demo.png
notes/project-b/demo.png

脚本不会把它们简单视为同一张图片。

因为多个同名文件可能是不同图片,所以脚本的上传缓存基于"实际文件路径",而不是单纯基于文件名。

也就是说:

  • 同一路径的图片文件:只上传一次。
  • 不同路径的同名图片文件:视为不同图片。
  • 无法唯一确定的 Wiki 图片引用:会输出警告。

当前默认策略是:如果发现多个同名图片,脚本会输出警告,并默认使用第一个匹配结果。

如果你希望更安全,可以在脚本中将:

SKIP_AMBIGUOUS_WIKI_IMAGE = False

改为:

SKIP_AMBIGUOUS_WIKI_IMAGE = True

这样遇到多个同名图片时,脚本会跳过该引用,不上传、不替换,避免误替换。

已经是远程图片的引用会不会处理?

例如:

![](https://example.com/demo.png)

不会被重复上传或替换。

目前普通 Markdown 图片链接中,http://https:// 开头的 URL 都会被跳过。