Python使用Mistune对markdown自定义规则解析

Mistune——更快的markdown解析器

在Python中有很多markdown解析器,以前我一直使用的是Python-markdown,一个纯Python实现的markdown解析器,别的不说,慢的要死倒是真的。每次点击保存后,都要响应很久,我开始一直以为是我的vps在国外导致的,后来还用了Mistune才知道,不是网速的问题,是解析器的速度问题。

没有对比就没有伤害,Mistune是所有纯Python实现中最快的一个。在纯Python环境中,几乎比Python- markdown快4倍,在Cython的帮助下,几乎快5倍。现在我使用了CPython,几乎是点击完保存的一瞬间,就解析完了,可以说感觉是很明显的。

基础用法

一个简单的栗子:

import mistune

mistune.markdown('I am using **mistune markdown parser**')
# output: <p>I am using <strong>mistune markdown parser</strong></p>

如果关心性能,官方推荐使用对象实例化后在进行调用

import mistune

markdown = mistune.Markdown()
markdown('I am using **mistune markdown parser**')

选择项

在使用mistune.Renderer的时候会有一些选择项提供修改

renderer = mistune.Renderer(escape=True, hard_wrap=True)
# use this renderer instance
markdown = mistune.Markdown(renderer=renderer)
markdown(text)
  • escape: 如果设置为False,则不会转义所有原始html标记。
  • hard_wrap: 如果设置为True,它将具有GFM换行功能。所有新行都将替换为<br>标记。GFM跟标准MD一样,行尾不允许直接回车换行,必须是\n\n或者空格空格\n
  • use_xhtml: 如果设置为True,则所有标记都将使用xhtml,例如:<hr />
  • parse_block_html:只解析block级别的。
  • parse_inline_html: 只解析inline级别的。

Renderer(渲染器)

官方提供了渲染器,当然你也可以继承官方的Renderer然后自己重写或者添加一些方法,这里给了一个官网给出的栗子,是一个给所有代码块添加highlighting标签的栗子。

import mistune
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import html

class HighlightRenderer(mistune.Renderer):
    def block_code(self, code, lang):
        if not lang:
            return '\n<pre><code>%s</code></pre>\n' %                 mistune.escape(code)
        lexer = get_lexer_by_name(lang, stripall=True)
        formatter = html.HtmlFormatter()
        return highlight(code, lexer, formatter)

renderer = HighlightRenderer()
markdown = mistune.Markdown(renderer=renderer)
print(markdown('```python\nassert 1 == 1\n```'))

下面是关于解析内容的很关键的定义,一个是块级解析(Block Level),一个是小跨度级解析(Span Level),也就是每句话中间出现的那种markdown解析,加粗什么的,还有一个是脚注(Footnotes)

Block Level

块级的API如下:

block_code(code, language=None) #代码块
block_quote(text) #引用块
block_html(html) #原生html?
header(text, level, raw=None) # 不知道是啥
hrule() # 不知道是啥
list(body, ordered=True) # 不知道是啥
list_item(text) # 不知道是啥
paragraph(text) # 段落
table(header, body) # 表格
table_row(content) # 表格行
table_cell(content, **flags) # 表格单元

Span Level

块级的API如下:

autolink(link, is_email=False) #引用链接
codespan(text) #行级code
double_emphasis(text) #加粗
emphasis(text) #斜体
image(src, title, alt_text) #图片
linebreak() #不知道
newline() #新的一行?
link(link, title, content) #引用链接
strikethrough(text) #不知道
text(text) #普通文字
inline_html(text) #内嵌HTML

Footnotes

脚注的API如下:

footnote_ref(key, index)
footnote_item(key, text)
footnotes(text)

自定义规则

下面就是自定义规则了,我们大概了解了每个API,官方源码里面主要分了以下几个类

  • BlockGrammar:关于块级的语法正则定义
  • BlockLexer:块级词法分析器
  • InlineGrammar:关于行级的语法正则定义
  • InlineLexer:行级词法分析器
  • Markdown:Markdown解析
  • Renderer:解析器

在这里,我举一个真实的栗子来讲解,首先抛出问题

问题:我在使用mathtype的时候,书写公式,例如这个公式||x||_1= \sum_{i=0}^{n}|x_i|,这是L1范数的公式,现在解析肯定没有问题了,我已经修复了,但如果是以前,会由于||x||后面的字符_sum后面的字符_,匹配到markdown中就是斜体的定义,那么我的公式就会变为

||x|| @1= \[email protected] {i=0}^{n}|x_i|?

这个样子。所以为了解决这个问题,我要重写有关于下划线_和乘号*的markdown语法。

解决办法:

首先定位一下,主要引起这个的有两个,一个是加粗,一个是斜体,所以我重写他们。

  1. 定义自己的InlineLexer,继承InlineLexer
  2. 找到规则double_emphasisemphasis,我将加粗改写为了只允许**框住,斜体改写为了@框住;
  3. 加入到default_rules这个list里面;
  4. 重写输出函数output_double_emphasisoutput_emphasis
class MyInlineLexer(InlineLexer):
    def enable_delete_em(self):
        self.rules.double_emphasis = re.compile(
            r'\*{2}([\s\S]+?)\*{2}(?!\*)'  # **word**
        )
        self.rules.emphasis = re.compile(
            r'\@((?:\*\*|[^\*])+?)\@(?!\*)'  # @[email protected]
        )
        self.default_rules.insert(3, 'double_emphasis')
        self.default_rules.insert(3, 'emphasis')

    def output_double_emphasis(self, m):
        text = m.group(1)
        return self.renderer.double_emphasis(text)

    def output_emphasis(self, m):
        text = m.group(1)
        return self.renderer.emphasis(text)

然后在解析markdown的时候

renderer = Renderer()
inline = MyInlineLexer(renderer)
inline.enable_delete_em()
markdown = mistune.Markdown(renderer=renderer, inline=inline)
  1. 实例化Renderer;
  2. 实例化自己的词法分析器;
  3. 调用enable_delete_em()重写对应的地方;
  4. 最后,实例化markdown,传入对应的renderer与inline即可。

Reference

Mistune文档

Markdown Parsers in Python

原文地址:https://www.cnblogs.com/harrylyx/p/12395259.html

时间: 2024-10-10 02:49:49

Python使用Mistune对markdown自定义规则解析的相关文章

解析prototxt文件的python库 prototxt-parser(使用parsy自定义文件格式解析)

解析prototxt文件的python库 prototxt-parser https://github.com/yogin16/prototxt_parser https://test.pypi.org/project/prototxt-parser1.yield让函数执行支持分段,让函数支持了记忆和状态,能够让一个函数变成状态机,这样一个状态机的执行流程可能直接表达在一个函数中,让整个处理流程更加顺畅.2.parsy的optional,Returns a parser that expects

转 markdown编写规则、语法

http://www.jianshu.com/p/1e402922ee32/ Markdown——入门指南 字数2231 阅读307754 评论115 喜欢1350 转载请注明原作者,如果你觉得这篇文章对你有帮助或启发,也可以来请我喝咖啡. 导语: Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的语法十分简单.常用的标记符号也不超过十个,这种相对于更为复杂的 HTML 标记语言

如何使用PMD自定义规则

准备工作 首先在PMD官网下载最新版本的文件,目前最新版本是5.4.1. 下载pmd-bin-5.4.1.zip和pmd-src-5.4.1.zip之后解压备用. pmd-src-5.4.1是PMD源码包,是无法直接执行的. pmd-bin-5.4.1是PMD的可执行包 目录简介 pmd-src-5.4.1中除了pmd-core是PMD的核心执行调度模块,其他文件夹都是各种语言检查规则的模块. 其中pmd-bin-5.4.1\lib目录中是执行所依赖的jar包. pmd-bin-5.4.1\bi

详解 Python 中的下划线命名规则

在 python 中,下划线命名规则往往令初学者相当 疑惑:单下划线.双下划线.双下划线还分前后……那它们的作用与使用场景 到底有何区别呢?今天 就来聊聊这个话题. 1.单下划线(_) 通常情况下,单下划线(_)会在以下3种场景中使用: 1.1 在解释器中: 在这种情况下,“_”代表交互式解释器会话中上一条执行的语句的结果.这种用法首先被标准CPython解释器采用,然后其他类型的解释器也先后采用. >>> _ Traceback (most recent call last): Fil

Python:使用基于事件驱动的SAX解析XML

SAX的特点: 是基于事件的 API 在一个比 DOM 低的级别上操作 为您提供比 DOM 更多的控制 几乎总是比 DOM 更有效率 但不幸的是,需要比 DOM 更多的工作 基于对象和基于事件的接口 您可能已经知道语法分析器有两类接口 - 基于对象的(如:DOM)和基于事件(如:SAX)的接口. DOM是基于对象的语法分析器的标准 API. 作为基于对象的接口,DOM 通过在内存中显示地构建对象树来与应用程序通信.对象树是 XML 文件中元素树的精确映射. DOM 易于学习和使用,因为它与基本

StyleCop学习笔记——自定义规则

本文将简单的一步一步的指导这可能有助于学习如何创建自己的规则 1.创建一个项目. Visual Studio创建一个新的类库项目.NET3.5 2.引用两个DLL,StyleCop.dll和StyleCop.Csharp.dll. 3.添加自定义的规则. MyCustomAnalyzer.cs代码如下: using StyleCop; using StyleCop.CSharp; namespace MyCustomRules { /// <summary> /// Custom analyz

速卖通 排序规则解析

排序规则解析 一.搜索排序的原则 AliExpress搜索的整体目标是帮助我们的买家快速找到想要的商品并且能够有比较好的采购交易体验,而搜索的排名的目标就是要将最好的商品.服务能力最好的卖家优先推荐给我们的买家,谁能带给买家最好的采购体验,谁的商品就会排序靠前. 在排序过程中,我们将始终坚持公平的原则,对于所有的卖家采取相同的标准,给予表现好的卖家更多的曝光机会,降低表现差的卖家曝光机会甚至没有曝光机会.我们提倡卖家间公平竞争,优胜劣汰,能够提供最好的采购体验给我们的买家,让更多的买家满意愿意来

python中的if __name__==&#39;__main__&#39;: main()解析

python中我们会看到一段代码是这样的: 1 if __name__=='__main__': 2 main() 这段代码的什么意思,我们可以知道代码的意思是如果__name__=='__main__'为Ture,则调用main()函数 有句话经典的概括了这段代码的意义: “Make a script both importable and executable” 意思就是说让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行. __name__的值是什么?模块是对象,并且所有的模

1. PMD 使用,编译和自定义规则

一 PMD简介 PMD是一款代码静态检查工具,可以检查出很多代码中潜在的bug以及让人感到疑惑的代码,具体大家可以百度下. 二 PMD源代码下载 下载地址: https://github.com/pmd/pmd/tree/pmd/5.5.x 需要注意的是注意选择branch,一般选择最新的branch:然后可以用git clone下来,或者直接下载zip压缩包. 如下: 从上图也可以看到,pmd支持的语言有很多,java的检测那就是在pmd-java里面. 三 maven下载和环境变量配置 参考