当前位置:   article > 正文

Python实现Word转为Markdown:CSDN新手发文窘境——段落篇_python把word文档转为md格式

python把word文档转为md格式

前言

  本来想把自己的一些笔记整理好放到CSDN的博客中,然而却被CSDN编辑器搞头大了。无论是科研还是工作中都很少用到Markdown“编辑器”(本文简称md法,它主张专注于打字,但不太符合我记笔记的习惯,换个颜色啥的;虽然它支持html语言实现各种“符合习惯的”的样式,但又丧失了专注于打字的功能。
  CSDN也支持富文本编辑器(本文简称rt法),但是从word中转移到富文本内图片上传的速度不敢苟同,且丧失了很多可以实现的效果,更气人的是,两个编辑器不能协同编辑。部分博主介绍了一种将WritagePandoc联动的方法(本文简称wp法)把docx格式转为md格式。个人试了一下,有几个方面的错误:1.公式通配符;2.图片添加不了;3.表格颜色单调;4.文字格式与word中不匹配。
  为了一次性解决众多问题,尝试使用一个Python脚本(doc2md)完成从word转换到CSDN能够支持的Markdown“编辑器”格式。

  本系列主要包括如下几个方面:1.文字篇;2.段落篇;3.表格篇;4.公式篇;5.图片篇
  各位小伙伴还有哪些想要的功能可以在评论区留言!
  

  段落篇我们主要需要修改以及可修改的内容包括:
  
  标题转换、首行缩进

  这一部分能修改的不多,我还尝试了段落间距、对齐方式,可似乎没什么效果
  测试所用数据(text.docx)挂这儿了,先对比看下效果
  
在这里插入图片描述
在这里插入图片描述

1 标题转换

  利用paragraph.style.name返回Heading+标题等级”这一特性搜索到标题,分割字符串得到标题等级,docx中最高支持9级标题,但Markdown最高只支持6级标题,所以我们把一级标题的文字大小设置为6.

    # 读取段落标题 docx中最高支持9级标题,但Markdown最高只支持6级标题
    # paragraph.style.name 返回值“Heading 标题等级数字”
    if 'Heading' in paragraph.style.name:  # 判断段落是否为标题
        level = eval(paragraph.style.name[-1])
        for run in paragraph.runs:
            i = run.text.index('size=') + 5  # 查询标题中设置标题字号的文本位置
            run.text = run.text[:i] + '{}'.format(7 - level) + run.text[i + 1:]  # 1级标题文字大小为6
        paragraph.text = '#' * level + ' ' + paragraph.text
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2 首行缩进

  我们在读取docx信息时,首行缩进的单位支持PtCmMmInches等,五号字体为例 = 10.5pt = 3.70mm = 14px = 0.146inch,默认设置返回None。也就是说,paragraph.paragraph_format.first_line_indent的返回值时不固定的,那么我们认为只要满足返回值非空就进行首行缩进。
  Markdown中首行缩进可用的方法比较多,这里选用添加两个 的方式。

    # 首行缩进
    # 首行缩进的单位支持Pt、Cm、Mm、Inches等,如果想要缩进几个字符,需要自己进行转换,因为不同字号字符占用的磅数是不同的
    #(五号字体 = 10.5pt = 3.70mm = 14px = 0.146inch)
    if paragraph.paragraph_format.first_line_indent != None:  # 判断段落是否使用首行缩进
        paragraph.text = ' ' * 2 + paragraph.text
  • 1
  • 2
  • 3
  • 4
  • 5

3 完整代码

import pydoc
import docx                                                 #导入python-docx库

# 判断是否添加</font>,这里如果添加多个会导致TOC目录显示异常eg:1</font>.1 </font>标题</font>2</font>
def exist_font(run):
    if '</font>' in run.text:
        pass
    else:
        run.text = run.text + '</font>'

''' 
    Get_run_format(run):     修改节段的格式信息
    input:                    实例化节段对象
'''
def Get_run_format(run):
    # TODO: 自定义添加你需要的节段格式转换
    # 判断文本是否加粗
    if run.font.bold == None:
        pass
    else:
        run.text = '<b>' + run.text + '</b>'

    # 判断文本是否为斜体
    if run.font.italic == None:
        pass
    else:
        run.text = '<i>' + run.text + '</i>'

    # 判断文本是否有下划线
    if run.font.underline == None:
        pass
    else:
        run.text = '<u>' + run.text + '</u>'

    # 判断文本是否添加删除线
    if run.font.strike == None:
        pass
    else:
        run.text = '<s>' + run.text + '</s>'

    # 设置文字颜色
    if run.font.color.rgb == None:
        pass
    else:
        exist_font(run)
        run.text = '<font color=#{}>'.format(run.font.color.rgb) + run.text

    # 判断字体是否高亮显示:
    if run.font.highlight_color == None:
        pass
    else:
        '''
        这里我尝试过了下面的语句,根据https://blog.csdn.net/ningmengshuxiawo/article/details/109112540介绍是可以更换成红色的
        <mark style="background:red" >这里是输入的文本</mark>
        但是我自己尝试的时候发现背景色并不能更换,这里就直接用黄色高亮标记
        '''
        run.text = '<mark>' + run.text + '</mark>'

    # 设置字体,默认为楷体
    if run.font.name == None:
        Is_Chi=False                               #判断run.text中是否有中文
        for i in range(len(run.text)):
            if '\u4e00' <= run.text[i] <= '\u9fff':# 中文字符串unicode范围\u4e001-\u9fff,设置为楷体
                Is_Chi = True
                break
            else:
                continue
        if Is_Chi == True:
            exist_font(run)
            run.text = '<font face="楷体">' + run.text
        else:  # 数字&英文设置为Times New Roman
            exist_font(run)
            run.text = '<font face="Times New Roman">' + run.text
    else:
        exist_font(run)
        run.text = '<font face={}>'.format(run.font.name) + run.text

    # 设置文字大小,默认为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
    exist_font(run)
    run.text = '<font size={}>'.format(font_size) + run.text

'''
    Get_paragraph_format(paragraph):     修改段落的格式信息
    input:                                实例化段落对象
'''
def Get_paragraph_format(paragraph):
    # TODO: 自定义添加你需要的段落格式转换

    # #行间距=行高-字体大小
    # if paragraph.paragraph_format.line_spacing!=None:
    #     for run in paragraph.runs:
    #         exist_font(run)
    #         run.text = '<font style="line-height:{};">'.format(paragraph.paragraph_format.line_spacing) + run.text
    # else:
    #     for run in paragraph.runs:
    #         exist_font(run)
    #         run.text = '<font style="line-height:1.0;">' + run.text

    # #段前间距
    # if paragraph.paragraph_format.space_before!=None:
    #     pass
    # else:
    #     pass

    # 读取段落标题 docx中最高支持9级标题,但Markdown最高只支持6级标题
    # paragraph.style.name 返回值“Heading 标题等级数字”
    if 'Heading' in paragraph.style.name:  # 判断段落是否为标题
        level = eval(paragraph.style.name[-1])
        for run in paragraph.runs:
            i = run.text.index('size=') + 5  # 查询标题中设置标题字号的文本位置
            run.text = run.text[:i] + '{}'.format(7 - level) + run.text[i + 1:]  # 1级标题文字大小为6
        paragraph.text = '#' * level + ' ' + paragraph.text

    # 首行缩进
    # 首行缩进的单位支持Pt、Cm、Mm、Inches等,如果想要缩进几个字符,需要自己进行转换,因为不同字号字符占用的磅数是不同的(五号字体 = 10.5pt = 3.70mm = 14px = 0.146inch)
    if paragraph.paragraph_format.first_line_indent != None:  # 判断段落是否使用首行缩进
        paragraph.text = '&#8195;' * 2 + paragraph.text



if __name__ == '__main__':
    doc = docx.Document(r'text.docx')  # 打开.docx文件
    for paragraph in doc.paragraphs:                         # 实例化文档中一个段落
        for run in paragraph.runs:                           # 实例化段落中一个节段
            Get_run_format(run)                              # 修改文字格式
        Get_paragraph_format(paragraph)                      # 修改段落格式
        print(paragraph.text)                                # 打印段落中的文本
  • 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
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143

  接下来我们需要对常用组件“表格”进行转换啦,欢迎翻看我的下一篇《Python实现Word转为Markdown:CSDN新手发文窘境——表格篇》。

               赶紧点赞、收藏起来吧!不然下次就找不到了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/159137
推荐阅读
相关标签