目录
前言
本来想把自己的一些笔记整理好放到CSDN的博客中,然而却被CSDN编辑器搞头大了。无论是科研还是工作中都很少用到Markdown“编辑器”(本文简称md法),它主张专注于打字,但不太符合我记笔记的习惯,换个颜色啥的;虽然它支持html语言实现各种“符合习惯的”的样式,但又丧失了专注于打字的功能。
CSDN也支持富文本编辑器(本文简称rt法),但是从word中转移到富文本内图片上传的速度不敢苟同,且丧失了很多可以实现的效果,更气人的是,两个编辑器不能协同编辑。部分博主介绍了一种将Writage和Pandoc联动的方法(本文简称wp法)把docx格式转为md格式。个人试了一下,有几个方面的错误:1.公式通配符;2.图片添加不了;3.表格颜色单调;4.文字格式与word中不匹配。
为了一次性解决众多问题,尝试使用一个Python脚本(doc2md)完成从word转换到CSDN能够支持的Markdown“编辑器”格式。本系列主要包括如下几个方面:1.文字篇;2.段落篇;3.表格篇;4.公式篇;5.图片篇
各位小伙伴还有哪些想要的功能可以在评论区留言!
文字篇我们主要需要修改以及可修改的内容包括:
文字字体、文字大小、文字加粗、文字倾斜、文字颜色、文字高亮、添加下划线、添加删除线
测试所用数据(text.docx)挂这儿了,先对比看下效果
需要系统理解实现过程的可以看前两部分,需要帮忙测试转换正确率的UU可以直接跳到最后一步
1️⃣ 读取Word文件
工欲善其事必先利其器,这一部分我们会优先介绍word中的几个基本概念,主要用到的是docx库,用该库可以实现word的大部分功能,这里主要用于读取。
1.1 Word文件的几个基本概念
Document:一个Word文档对象List<Paragraph>
,不同于 VBA 中 Worksheet 的概念,Document 是独立的,打开不同的 Word 文档,就会有不同的 Document 对象,相互之间没有影响;
Paragraph:一个段落对象List<Run>
,一个 Word 文档由多个段落组成,当在文档中输入一个回车键,就会成为新的段落,输入 shift + 回车,不会分段这个地方我一开始就没理解好,正常输入一段文字,到页边距末尾的时候相当于自动输入一个回车键,这样就相当于一个新的段落
;
Run :一个节段对象,每个段落由多个节段组成,一个段落中具有相同样式的连续文本,组成一个节段,所以一个段落对象有个Run 列表.
1.2 安装python-docx库
能看到这篇博文,应该python和编辑器安装都已经没问题了;我也不知道为什么那么多库安装和导入包的名字不一样,反正就是天天踩坑。
基本动作Win+R,输入“cmd”,点击Enter
pip install python-docx
安装完成以后,可以在python-docx官方文档查看相关用法,我在撰写本文的时候同时参考了【2.5万字】详解 Python-docx 自动生成word图文报告一文,当然就解决发文烦恼也可以只参考本文。
1.3 读取.doxc文件
按照好python-docx后,我们通过如下命令导入该库
import docx
实例化Document对象
doc=docx.Document(r'filepath') #filepath应为需要转换的word文件目录
for paragraph in doc.paragraphs: # 遍历每一个段落
print(paragraph.text) # 打印段落中的文本
2️⃣ 将文字格式(docx格式)转为CSDN可识别格式(md格式)
2.1 基本思路
这里我们要弄清楚两种命令格式的区别
(1)关于python-docx中读写文字格式信息的一些基本命令
#关于python-docx中去写文字格式信息的一些基本命令
runs=docx.Document.paragraphs
#实例化一个r在runs列表内
r.font.name #文字字体
r.font.size #文字大小
r.font.bold #文字加粗
r.font.italic #文字倾斜
r.font.color.rgb #文字颜色
r.font.highlight_color #文字高亮
r.font.underline #下划线
r.font.strike #删除线
(2)关于md格式中可识别的文字格式信息的一些基本命令
#关于md格式中可识别的文字格式信息的一些基本命令
#假设我们要显示的字符串变量名为:char
<font face='字体'> char</font> #文字字体
<font size='字号'> char</font> #文字大小
<b> char</b> #文字加粗
<i> char</i> #文字倾斜
<font color=#'16进制RGB颜色标识'> char</font> #文字颜色
<mark> char</mark> #文字高亮
<u> char</u> #下划线
<s> char</s> #删除线
仔细对比两种格式不难发现,我们的思路可以是:1.获取word中文字格式信息;2.将节段对象的文本(run.text)按照对应格式修改。
2.2 代码实现
格式转换函数
我们首先定义一个Get_run_format函数:用于读取word文字格式信息并将其转换为html格式,后续节段格式转换代码可以直接加到TODO部分
。
'''
Get_run_format(run): 修改节段的格式信息函数
input: 实例化节段对象
output: 修改为html格式的文字字符串
'''
def Get_run_format(run):
r_text = run.text #文本默认存储节段文本字符
#TODO: 自定义添加你需要的节段格式转换
return r_text #返回修改后的节段文本字符
main函数
我们在主函数中打开文件,调用Get_run_format(run)函数完成打印输出,这一部分的代码可以不做修改。
if __name__ == '__main__':
doc = docx.Document(r'text.docx') # 打开.docx文件
for paragraph in doc.paragraphs: # 实例化文档中一个段落
for run in paragraph.runs: # 实例化段落中一个节段
run.text = Get_run_format(run)
print(paragraph.text) # 打印段落中的文本
2.2.1 文字加粗
run.font.bold只会返回两种结果:None-没加粗,True-加粗
# 判断文本是否加粗
if run.font.bold == None:
pass
else:
r_text = '<b>' + r_text + '</b>'
2.2.2 文字倾斜
run.font.italic只会返回两种结果:None-没倾斜,True-倾斜
# 判断文本是否为斜体
if run.font.italic == None:
pass
else:
r_text = '<i>' + r_text + '</i>'
2.2.3 添加下划线
run.font.underline只会返回两种结果:None-没添加下划线,True-添加下划线
# 判断文本是否有下划线
if run.font.underline == None:
pass
else:
r_text = '<u>' + r_text + '</u>'
2.2.4 添加删除线
run.font.strike只会返回两种结果:None-没添加删除线,True-添加删除线
# 判断文本是否添加删除线
if run.font.strike == None:
pass
else:
r_text = '<s>' + r_text + '</s>'
2.2.5 文字颜色
run.font.color.rgb返回的是16进制的RGB颜色值,这里是读取到word什么颜色,就修改成什么颜色,当然你也可以根据颜色对照表修改自己喜欢的自定义颜色
# 设置文字颜色
if run.font.color.rgb == None:
pass
else:
r_text = '<font color=#{}>'.format(run.font.color.rgb) + r_text + '</font>'
2.2.6 文字高亮
这里我尝试过了下面的语句
<mark style="background:red" >这里是输入的文本</mark>
根据此生辽阔博主的介绍是可以更换成红色的, 但是我自己尝试的时候发现背景色并不能更换,只有黄色高亮标记能起作用
# 判断字体是否高亮显示:
if run.font.highlight_color == None:
pass
else:
r_text = '<mark>' + r_text + '</mark>'
2.2.7 文字字体
run.font.name返回的是字体名称或“None”(“None”代表的是当前字体为docx文档的默认字体),节段的特性就是会将段落中格式发生变化的文字截断,所以每个节段内的格式应该是一致的,这里我们就只用节段的第一个字符串char[0]进行判断:
首先,如果是默认字体,那么假设char[0]满足unicode字符中[‘\u4e00’,‘\u9fff’]的范围,则这部分节段应该是中文字符,默认设置为"楷体";否则就将默认设置为"Times New Roman"字体。如果不是默认字体就读取docx的字体为节段的字体格式。
# 设置字体,默认为楷体
if run.font.name == None:
if '\u4e00' <= run.text[0] <= '\u9fff': # 中文字符串unicode范围,设置为楷体\u9fff
r_text = '<font face="楷体">' + r_text + '</font>'
else: # 数字&英文设置为Times New Roman
#这里可以将"Times New Roman"替换为"Times"
r_text = '<font face="Times New Roman">' + r_text + '</font>'
else:
r_text = '<font face={}>'.format(run.font.name) + r_text + '</font>'
2.2.8 文字大小
这里经过简单的测试:markdown语法中,可以供选的大小从1~7,1最小,7最大,默认文字大小为3,根据run.font.size返回的结果
run.font.size输出结果对照表 | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
初号 | 小初 | 一号 | 1号 | 二号 | 2号 | 三号 | 3号 | 四号 | 4号 | 五号 | 5号 | 六号 | 6号 |
533400 | 457200 | 330200 | 304800 | 279400 | 228600 | 203200 | 190500 | 177800 | 152400 | 133350 | 114300 | 95250 | 82550 |
# 设置文字大小,默认为3
if run.font.size == None or run.font.size == 152400:
font_size = 3 #默认字体/4号字设置为3
elif run.font.size < 152400:
if run.font.size < 95250:
font_size = 1 #比六号字小的设置为1
else:
font_size = 2 #介于六号字到4号字之间的设置为2
else:
if run.font.size == 177800:
font_size = 4 #四号字置为4
elif run.font.size < 203200:
font_size = 5 #介于四号字到三号字之间的设置为5
elif run.font.size < 279400:
font_size = 6 #介于三号字到二号字之间的设置为6
else:
font_size = 7 #大于二号字之间的设置为7
r_text = '<font size={}>'.format(font_size) + r_text + '</font>'
3️⃣ 全部代码(欢迎UU们帮忙测试转换正确率💕)
各位小伙伴还有哪些想要的功能可以在评论区留言!
import docx #导入python-docx库
'''
Get_run_format(run): 修改节段的格式信息
input: 实例化节段对象
output: 修改为html格式的文字字符串
'''
def Get_run_format(run):
#TODO: 自定义添加你需要的节段格式转换
r_text = run.text #文本默认存储节段文本字符
# 判断文本是否加粗
if run.font.bold == None:
pass
else:
r_text = '<b>' + r_text + '</b>'
# 判断文本是否为斜体
if run.font.italic == None:
pass
else:
r_text = '<i>' + r_text + '</i>'
# 判断文本是否有下划线
if run.font.underline == None:
pass
else:
r_text = '<u>' + r_text + '</u>'
# 判断文本是否添加删除线
if run.font.strike == None:
pass
else:
r_text = '<s>' + r_text + '</s>'
# 设置文字颜色
if run.font.color.rgb == None:
pass
else:
r_text = '<font color=#{}>'.format(run.font.color.rgb) + r_text + '</font>'
# 判断字体是否高亮显示:
if run.font.highlight_color == None:
pass
else:
r_text = '<mark>' + r_text + '</mark>'
# 设置字体,默认为楷体
if run.font.name == None:
if '\u4e00' <= run.text[0] <= '\u9fff': # 中文字符串unicode范围,设置为楷体\u9fff
r_text = '<font face="楷体">' + r_text + '</font>'
else: # 数字&英文设置为Times New Roman
r_text = '<font face="Times New Roman">' + r_text + '</font>'
else:
r_text = '<font face={}>'.format(run.font.name) + r_text + '</font>'
# 设置文字大小,默认为3
if run.font.size == None or run.font.size == 152400:
font_size = 3
elif run.font.size < 152400:
if run.font.size < 95250:
font_size = 1
else:
font_size = 2
else:
if run.font.size == 177800:
font_size = 4
elif run.font.size < 203200:
font_size = 5
elif run.font.size < 279400:
font_size = 6
else:
font_size = 7
r_text = '<font size={}>'.format(font_size) + r_text + '</font>'
return r_text
if __name__ == '__main__':
doc = docx.Document(r'text.docx') # 打开.docx文件
for paragraph in doc.paragraphs: # 实例化文档中一个段落
for run in paragraph.runs: # 实例化段落中一个节段
run.text = Get_run_format(run)
print(paragraph.text) # 打印段落中的文本
细心的小伙伴可能发现了,我们的结果还是不能满足首行缩进、标题识别等功能,这部分我们放到下一篇《Python实现Word转为Markdown:CSDN新手发文窘境——段落篇》展开解释。
赶紧点赞、收藏起来吧!不然下次就找不到了💕