Python:如何将Markdown格式的文本转换为文本

54

我需要将Markdown文本转换为纯文本格式,以在我的网站上显示摘要。我希望使用Python编写代码。


2
不是Python,但你可以将它传递给Pandoc:pandoc --to=plain会保留一些格式(标题下划线),但不会太多。 - naught101
7个回答

66
尽管这是一个非常古老的问题,但我想提供一个最近想出的解决方案。该方案既不使用BeautifulSoup,也没有将内容转换为html然后再转回来的开销。
Markdown模块的核心类Markdown拥有一个名为output_formats的属性,它不可配置,但几乎像Python中的任何其他东西一样可以被局部修补。默认情况下,它有两个输出格式:“html”和“xhtml”,对应地。借助一些帮助,它可能具有易于编写的纯文本呈现函数:
from markdown import Markdown
from io import StringIO


def unmark_element(element, stream=None):
    if stream is None:
        stream = StringIO()
    if element.text:
        stream.write(element.text)
    for sub in element:
        unmark_element(sub, stream)
    if element.tail:
        stream.write(element.tail)
    return stream.getvalue()


# patching Markdown
Markdown.output_formats["plain"] = unmark_element
__md = Markdown(output_format="plain")
__md.stripTopLevelTags = False


def unmark(text):
    return __md.convert(text)

unmark函数以Markdown文本作为输入,并返回去除所有Markdown字符的文本。


4
看起来很棒,非常感谢您抽出时间回答这个问题,即使它已经很老了。非常感激! - Frerich Raabe
非常感谢您提供这个精彩的答案。我原本打算自己实现它,但是这段代码片段为我节省了很多时间。 - Leonardo Maffei
1
这绝对比被接受的答案更可取!谢谢。 - Hans Z
1
这里有一个非官方的 Python-Markdown 扩展 kostyachum/python-markdown-plain-text,基本上可以做到与 monkey-patching 相同的事情,但不需要进行额外的修改。 - Ross Patterson

54

Markdownbeautifulsoup4模块可以帮助您完成所描述的操作。

将Markdown转换为HTML后,您可以使用HTML解析器来剥离纯文本。

您的代码可能类似于以下内容:

from bs4 import BeautifulSoup
from markdown import markdown

html = markdown(some_html_string)
text = ''.join(BeautifulSoup(html).findAll(text=True))

1
似乎需要将其转换为HTML格式。我需要将其转换为纯文本格式。就像StackOverflow在主页的问题摘要中一样,它会删除格式。 - Krish
1
谢谢 coonj.. 很高兴了解到 Beautiful Soup。 - Krish
2
来回转换Markdown和HTML太麻烦了,下面有一个很好的替代方案,只使用Markdown。 - Renato Byrro
好答案 - 当将原始文本和md / html版本保存到数据库时,这是一个很好的解决方案。虽然我没有测试过它,但只要不剥夺原始文本的换行符号,就应该没问题。 - Hills
现在已经测试过了,但它从原始文本中删除了换行符。您知道如何防止这种情况发生吗? - Hills

6

这与Jason的回答类似,但可以正确处理评论。

import markdown # pip install markdown
from bs4 import BeautifulSoup # pip install beautifulsoup4

def md_to_text(md):
    html = markdown.markdown(md)
    soup = BeautifulSoup(html, features='html.parser')
    return soup.get_text()

def example():
    md = '**A** [B](http://example.com) <!-- C -->'
    text = md_to_text(md)
    print(text)
    # Output: A B

你可以使用pypandoc代替BeautifulSoup。如果在Jupyter中找不到该模块,请从ipython中运行。 - S.Doe_Dude

2

我删除了评论,因为我终于认为我看到了问题的关键:将你的Markdown文本转换为HTML并从文本中删除HTML可能更容易。 我不知道有什么有效地从文本中删除Markdown的方法,但有许多HTML转纯文本的解决方案。


Markdown 被称为“基本上是纯文本”,但这么难去除格式,还不如用 Word。 - gargoylebident
Markdown可以在99.99%的计算机上运行。 - panchicore

0
正如Neil所建议的那样,nltk的解析器是基于markdown-itmdit-plain的。直接使用它们非常简单(无需使用BeautifulSoup!)。
pip install markdown-it-py mdit_plain

from markdown_it import MarkdownIt
from mdit_plain.renderer import RendererPlain

parser = MarkdownIt(renderer_cls=RendererPlain)

md_data = "# some markdown"
txt_data = parser.render(md_data)

0

根据我的有限经验,这不一定是一个非常快速的解决方案,但您可以尝试使用NLTK中的MarkdownCorpusReader。它需要一个包含Markdown文件的目录和一个用于有效文件ID的正则表达式。

from nltk.corpus.reader.markdown import MarkdownCorpusReader
from nltk.tokenize.treebank import TreebankWordDetokenizer
# You might also need a punkt detokenizer for the English language.

filepath = './some/path/here' 
reader = MarkdownCorpusReader(filepath, r'[w\]*\.md')

def get_text(reader: MarkdownCorpusReader, fileid: str) -> str:
    tokens = reader.words(fileids=fileid)
    # You might also need a punkt detokenizer for the English language.
    return TreebankWordDetokenizer().detokenize(tokens)

不幸的是,Markdown 有各种变种,所以具体要看它来自哪里,一些格式元素可能仍然存在。我无法完全测试,因为没有示例数据可供使用。对于英文,您可能还需要一个 punkt detokenizer。对于这里使用的默认标记化方式,我并不熟悉,但我推测它是使用 nltk.tokenize.word_tokenize,该方法结合了 treebank tokenizer 和英语 punkt tokenizer。

我还要补充一点,nlkt 的 Markdown 解析器是基于 markdown-it-py 和 mdit-plain 构建的,所以这些模块内部应该也有工具可用于处理此类问题。


-3

我在搜索通过API调用执行s.c. GitLab发布的方法时来到这里。我希望这符合原问题提出者的用例。

我将Markdown解码为纯文本(包括以\n等形式的空格),方法如下:

    with open("release_note.md", 'r') as file:
        release_note = file.read()
        description = bytes(release_note, 'utf-8')
    return description.decode("utf-8")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接