自动化 Markdown 图片上传到 GitHub
1. 代码介绍
本代码用于自动扫描指定目录下的 Markdown 文章,提取其中的本地图片,并上传到 GitHub 仓库,最后替换文章中的图片路径,实现图片的托管和访问加速。
2. 主要功能
- 读取本地配置文件,加载 GitHub Token
- 扫描 Markdown 文章,查找本地图片
- 判断图片是否已处理,避免重复上传
- 将图片上传到 GitHub 指定仓库和分支
- 更新 Markdown 文章中的图片链接
- 记录处理过的文件哈希值,避免重复处理
3. 代码解析
3.1 配置文件管理
代码首先定义了 CONFIG_FILE 路径 (~\.image_upload_config.json),用于存储 GitHub Token。然后 load_github_token() 函数用于读取该文件,并获取 GITHUB_TOKEN。
1 2 3 4 5 6 7 8 9 10 11 12 13
| CONFIG_FILE = Path.home() \ ".image_upload_config.json"
def load_github_token(): try: with open(CONFIG_FILE, 'r') as f: config = json.load(f) token = config.get("GITHUB_TOKEN") if not token: raise ValueError("配置文件中缺少GITHUB_TOKEN字段") return token except FileNotFoundError: print(f"错误:配置文件 {CONFIG_FILE} 不存在。请创建该文件并包含GITHUB_TOKEN字段。") exit(1)
|
3.2 全局配置项
定义了 CONFIG 字典,包含 GitHub 仓库信息、文章目录、允许的图片格式等。
1 2 3 4 5 6 7 8 9
| CONFIG = { "GITHUB_TOKEN": load_github_token(), "REPO": "qingyun201908\qingyun201908.github.io", "BRANCH": "images", "POSTS_DIR": Path(r"D:\\2025Blog\\my-blog\\source\\_posts"), "ALLOWED_EXTENSIONS": {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'}, "HASH_STORE": Path.home() \ ".image_upload_processed", "LOCAL_IMAGES_DIR": None, }
|
3.3 文件处理管理
3.3.1 FileProcessor 类
- 负责初始化 GitHub 连接
- 读取和存储已处理的文件哈希值
- 遍历 Markdown 目录,逐个处理文章
1 2 3 4 5
| class FileProcessor: def __init__(self): self.processed = self.load_processed() self.repo = self.init_github() print(f"成功连接仓库: {self.repo.full_name}\n")
|
3.3.2 计算文件哈希值
用于检查文章是否修改过,避免重复处理。
1 2 3 4 5 6
| def calculate_hash(self, filepath): hasher = hashlib.sha256() with open(filepath, 'rb') as f: while chunk := f.read(8192): hasher.update(chunk) return hasher.hexdigest()
|
3.4 文章处理
3.4.1 ArticleProcessor 类
- 解析 Markdown 文件,查找图片链接
- 处理本地图片(检查路径、上传到 GitHub)
- 替换 Markdown 文章中的本地图片路径
1 2 3 4 5
| def process_images(self): matches = re.findall("!\[.*?\]\((.*?)\)", self.content) print(f"发现 {len(matches)} 个图片引用") for local_path in matches: self.process_single_image(local_path)
|
3.4.2 上传图片到 GitHub
- 先检查 GitHub 仓库中是否已存在相同文件
- 如果文件已存在且内容一致,则直接复用 URL
- 否则更新或创建新的图片文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| def upload_image(self, image_path): image_name = image_path.name remote_path = f"images\{self.article_folder}\{image_name}" with open(image_path, 'rb') as f: content = f.read() try: existing = self.manager.repo.get_contents(remote_path, CONFIG["BRANCH"]) if existing.decoded_content == content: print(f"图片已存在,跳过上传: {remote_path}") return f"{CONFIG['BASE_URL']}{remote_path}" self.manager.repo.update_file( path=remote_path, message=f"Update image: {remote_path}", content=content, sha=existing.sha, branch=CONFIG["BRANCH"] ) except Exception: self.manager.repo.create_file( path=remote_path, message=f"Add image: {remote_path}", content=content, branch=CONFIG["BRANCH"] ) return f"{CONFIG['BASE_URL']}{remote_path}"
|
3.5 运行主程序
1 2 3 4 5 6 7
| if __name__ == "__main__": CONFIG["POSTS_DIR"] = Path(CONFIG["POSTS_DIR"]) CONFIG["LOCAL_IMAGES_DIR"] = CONFIG["POSTS_DIR"].parent \ "images" CONFIG["BASE_URL"] = f"https:\\raw.githubusercontent.com\{CONFIG['REPO']}\{CONFIG['BRANCH']}\" processor = FileProcessor() processor.process_directory()
|
4. 运行方式
- 在
~\.image_upload_config.json 中配置 GitHub Token: 1 2 3
| { "GITHUB_TOKEN": "your_github_personal_access_token" }
|
- 修改
CONFIG 变量,指定 GitHub 仓库和本地 Markdown 目录。
- 运行 Python 脚本:
5. 总结
本代码通过解析 Markdown 文件,自动上传本地图片到 GitHub,并更新文章内容,使得图片可以通过 GitHub 进行托管,适用于 Hexo 或 Jekyll 博客的自动化部署。
