博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用python批量替换MD文件中的图片地址
阅读量:7126 次
发布时间:2019-06-28

本文共 5014 字,大约阅读时间需要 16 分钟。

背景

在用Markdown格式记录我的技术笔记过程中,我习惯把所有的图片先保存在本地,而不是直接上传到图床上去。这样的好处是,一方面我可以有本地备份,不用担心图床哪一天挂掉了;另一方面,如果我想把某一篇笔记发布到博客,我可以随时把图片上传,然后更新图片地址。

Mac平台下的Typora + iPic的组合,虽然很强大,但是不能满足我奇葩的需求。所以就写了一个简单的python脚本来处理。因为会配合KM一起使用,所以这个脚本的任务就只需要处理单一文件即可。

KM脚本参见

需求

  1. 通过指定入参处理单一文件,更新图片URL;
  2. 能把MD文件中的图片拷贝到本地其他目录(方便备份);
  3. 能把MD文件中的图片从本地上传到图床(方便发布);
  4. 能把博客上文章内嵌的图片抓到本地;

源代码

整体逻辑如下:

  1. 判断入参是一个合法的MD文件;
  2. 正则表达式查找所有图片地址的列表;
  3. 根据不同的操作模式
    1. 本地模式,把图片拷贝到指定目录下,生成新url
    2. 图床模式,把本地图片上传到阿里云OSS,生成新url
    3. 下拉模式,暂未实现。。。
  4. 用新url替换原来的url

replace_md_url.py

#!/usr/bin/env -S -P${HOME}/anaconda/bin python# -*- coding:utf-8 -*-import re, os, shutil, time, sys, argparsefrom itertools import chainimport oss2# 需要替换url的MD文件md_file = ''# 操作类型, L2L (默认本地到本地), L2W(本地到图床), W2L(图床到本地)action = 'L2L'# 保存图片文件的根目录dir_base = '/*******/_MD_Media'# Markdown中图片语法 ![](url) 或者 img_patten = r'!\[.*?\]\((.*?)\)|
'def get_img_local_path(md_file, path): """ 获取MD文件中嵌入图片的本地文件绝对地址 :param md_file: MD文件 :param path: 图片URL :return: 图片的本地文件绝对地址 """ result = None # /a/b/c if path.startswith('/'): result = path # ./a/b/c elif path.startswith('.'): result = '{0}/{1}'.format(os.path.dirname(md_file), path) # file:///a/b/c elif path.startswith('file:///'): result = path[8:] result = result.replace('%20',' ') else: result = '{0}/{1}'.format(os.path.dirname(md_file), path) return resultdef local_2_local(md_file, dir_ts, match): """ 把MD中的本地图片移动到指定目录下,并返回URL。 这里并没有进行URL的替换 :param md_file: :param dir_ts: :param match: :return: new_url,新本地文件地址。如果不需要替换,就返回空 """ dir_tgt = '{0}/{1}'.format(dir_base, dir_ts) new_url = None # 判断是不是已经是一个图片的网址,或者已经在指定目录下 if not (re.match('((http(s?))|(ftp))://.*', match) or re.match('{}/.*'.format(dir_base), match)): # 如果图片url是本地文件,就替换到指定目录 img_file = get_img_local_path(md_file, match) if os.path.isfile(img_file): new_url = '{0}/{1}'.format(dir_tgt, os.path.basename(match)) os.makedirs(dir_tgt, exist_ok=True) # 移动物理文件 shutil.move(img_file, dir_tgt) return new_urldef local_2_web(md_file, dir_ts, match): """ 把MD中的本地图片上传到OSS下,并返回URL。 这里并没有进行URL的替换 :param md_file: :param dir_ts: :param match: :return: new_url,新本地文件地址。如果不需要替换,就返回空 """ # 阿里云OSS信息 bucket_name = "b******ce" endpoint = "http://oss-cn-beijing.aliyuncs.com" access_key_id = "******" access_key_secret = "******" web_img_prfix = 'https://******.oss-cn-beijing.aliyuncs.com' # 创建Bucket对象,所有Object相关的接口都可以通过Bucket对象来进行 bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name) new_url = None # 判断是不是已经是一个图片的网址 if not (re.match('((http(s?))|(ftp))://.*', match) ): # 如果图片url是本地文件,就上传 img_file = get_img_local_path(md_file, match) if os.path.isfile(img_file): key_url = '{0}/{1}'.format(dir_ts, os.path.basename(match)) bucket.put_object_from_file(key_url, img_file) new_url = '{}/{}'.format(web_img_prfix, key_url) return new_urldef replace_md_url(md_file): """ 把指定MD文件中引用的图片移动到指定地点(本地或者图床),并替换URL :param md_file: MD文件 :return: """ if os.path.splitext(md_file)[1] != '.md': print('{}不是Markdown文件,不做处理。'.format(md_file)) return cnt_replace = 0 # 本次操作时间戳 dir_ts = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime()) with open(md_file, 'r',encoding='utf-8') as f: #使用utf-8 编码打开 post = f.read() matches = re.compile(img_patten).findall(post) if matches and len(matches)>0 : # 多个group整合成一个列表 for match in list(chain(*matches)) : if match and len(match)>0 : new_url = None # 进行不同类型的URL转换操作 if action == 'L2L': new_url = local_2_local(md_file, dir_ts, match) elif action == 'L2W': new_url = local_2_web(md_file, dir_ts, match) # 更新MD中的URL if new_url : post = post.replace(match, new_url) cnt_replace = cnt_replace + 1 # 如果有内容的话,就直接覆盖写入当前的markdown文件 if post and cnt_replace > 0: open(md_file, 'w', encoding='utf-8').write(post) print('{0}的{1}个URL被替换到<{2}>/{3}'.format(os.path.basename(md_file), cnt_replace, action, dir_ts)) elif cnt_replace == 0: print('{}中没有需要替换的URL'.format(os.path.basename(md_file)))if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-f', '--file', help='文件Full file name ofMarkdown file.') parser.add_argument('-a', '--action', help='操作类型: L2L, L2W, W2L .') parser.add_argument('-d', '--dir', help='Base directory to store MD images.') args = parser.parse_args() if args.action: action = args.action if args.dir: dir_base = args.dir if args.file: replace_md_url(args.file)复制代码

转载于:https://juejin.im/post/5af2ad0c6fb9a07ac363758b

你可能感兴趣的文章
Cocos2d-x Touch事件处理机制(better)
查看>>
那些年借“云”出海的日子
查看>>
Lync Server 2010的部署系列(四) outlook无法加入联机会议
查看>>
网易星球手机挖矿,仿公信宝不要太明显!伪区块链搜集用户隐私?
查看>>
第一次获得Microsoft MVP应该做的事
查看>>
java:Eclipse:Juno:设置workspace路径
查看>>
MySQL5.6更人性化修改redo log事务日志文件大小
查看>>
Office 365系列之十三:Office 365管理员角色
查看>>
Kubernetes数据持久化方案
查看>>
mysql高可用方案之MaxScale-HA-with-Corosync-Pacemaker
查看>>
SHELL网络爬虫实例剖析
查看>>
拇指接龙游戏从WIN32向Android移植过程问题记录(2)
查看>>
[zz]mesos 底层基础库
查看>>
线性 计算公式
查看>>
java.io.NotSerializableException错误解决方法
查看>>
[工具库]JFileDownloader工具类——多线程下载网络文件,并保存在本地
查看>>
updateprogress 不显示
查看>>
分享:如何使用 epoll? 一个 C 语言实例
查看>>
[转]谈谈.Net技术面试
查看>>
每天一个linux命令(56):netstat命令
查看>>