用于从字符串中删除HTML标记的Python代码

Bru*_*uno 112 html python xml string parsing

我有这样的文字:

text = """<div>
<h1>Title</h1>
<p>A long text........ </p>
<a href=""> a link </a>
</div>"""
Run Code Online (Sandbox Code Playgroud)

使用纯Python,没有外部模块我想要这个:

>>> print remove_tags(text)
Title A long text..... a link
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用lxml.html.fromstring(text).text_content()来实现它,但我需要在纯Python中使用内置或std库实现相同的2.6+

我怎样才能做到这一点?

c24*_*24b 202

使用正则表达式

使用正则表达式,你可以清理里面的一切<>:

import re

def cleanhtml(raw_html):
  cleanr = re.compile('<.*?>')
  cleantext = re.sub(cleanr, '', raw_html)
  return cleantext
Run Code Online (Sandbox Code Playgroud)

使用BeautifulSoup

您还可以使用&nsbm其他包来查找所有原始文本

你需要在调用BeautifulSoup时显式设置解析器我推荐"lxml",如替代答案中所提到的(比默认答案更强大(即没有额外安装时可用)'html.parser'

cleanr = re.compile('<.*?>|&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});')
Run Code Online (Sandbox Code Playgroud)

但它并不妨碍您使用外部库,因此我建议使用第一个解决方案.

  • 如果你想编译regexp,最好的方法是编译外部函数.在你的例子中,每次调用`cleanhtml`都必须再次编译regexp (9认同)
  • 当标记很重时,BeautifulSoup很好,否则尽量避免它,因为它很慢. (3认同)
  • 很好的答案.您可能希望使用`cleantext = BeautifulSoup(raw_html,"html.parser")在BeautifulSoup中显式设置解析器. (2认同)

lvc*_*lvc 37

Python内置了几个XML模块.对于你已经拥有完整HTML的字符串的情况,最简单的一个是xml.etree,它与你提到的lxml示例类似地工作(有些):

def remove_tags(text):
    return ''.join(xml.etree.ElementTree.fromstring(text).itertext())
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用,但要小心自动关闭类型的 html 标签。示例: &lt;/br&gt; 我收到“ParseError:不匹配的标记:第 1 行,第 9 列”,因为此标记已关闭而之前未打开。这对于所有自动关闭的 html 标签都是一样的。 (3认同)

Amb*_*ber 27

请注意,这并不完美,因为如果你有类似的东西,比如说<a title=">">它会破裂.但是,如果没有非常复杂的函数,它就是你在非库Python中最接近的:

import re

TAG_RE = re.compile(r'<[^>]+>')

def remove_tags(text):
    return TAG_RE.sub('', text)
Run Code Online (Sandbox Code Playgroud)

但是,由于xml.etreePython标准库中提供了lvc提及,因此您可能只需将其调整为与现有lxml版本一样:

def remove_tags(text):
    return ''.join(xml.etree.ElementTree.fromstring(text).itertext())
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢你的正则表达式方法,如果性能是一个重要因素,也许会更好。 (2认同)
  • 值得注意的是,如果您的文档中有文本 `&lt;`,这将会中断。 (2认同)

Med*_*ros 5

在任何类C语言中都有一种简单的方法.风格不是Pythonic,但适用于纯Python:

def remove_html_markup(s):
    tag = False
    quote = False
    out = ""

    for c in s:
            if c == '<' and not quote:
                tag = True
            elif c == '>' and not quote:
                tag = False
            elif (c == '"' or c == "'") and tag:
                quote = not quote
            elif not tag:
                out = out + c

    return out
Run Code Online (Sandbox Code Playgroud)

这个想法基于一个简单的有限状态机,详细解释如下:http://youtu.be/2tu9LTDujbw

你可以在这里看到它:http://youtu.be/HPkNPcYed9M?t = 35s

PS - 如果你对这个课程感兴趣(关于使用python进行智能调试),我会给你一个链接:http://www.udacity.com/overview/Course/cs259/CourseRev/1.免费!

  • 这将在不匹配的引号上中断,并且由于逐个字符地添加输出字符而非常慢.但它足够令人难以理解,编写一个原始的逐字符解析器并不是什么大问题. (6认同)