从字符串中删除HTML图像标签以及标签之间的所有内容

10

我看到许多关于从字符串中删除HTML标签的问题,但我还是有些不清楚如何处理我的特定情况。

我看到许多帖子建议不要使用正则表达式来处理HTML,但我怀疑我的情况可能需要审慎规避这个规则。

我正在尝试解析PDF文件,我已成功将样本PDF文件的每个页面转换为UTF-32文本字符串。当出现图像时,会插入一个类似HTML的标记,其中包含图像的名称和位置(保存在其他地方)。

在我的应用程序的另一个部分,我需要摆脱这些图像标记。因为我们仅涉及图像标记,所以我认为使用正则表达式可能是合适的。

我的问题有两个:

  1. 我应该使用正则表达式来删除这些标记,还是仍然使用像BeautifulSoup这样的HTML解析模块?
  2. 我应该使用哪种正则表达式或BeautifulSoup构造?换句话说,我应该如何编写代码?

为了清晰起见,标记的结构如下:<img src="/path/to/file"/>

谢谢!


这个文件里还有其他的HTML吗?还是只有纯文本和<img>标签? - senderle
@senderle 不,除了 <img> 标签之外没有 HTML,因此我不太愿意使用完整的 HTML 库。格式始终如上所述。 - Louis Thibault
我刚刚发布了一个答案,但是我想知道,每个图像的结束符号>后面实际上是否有撇号,还是那只是一个笔误? - joshcartme
@joshcartme 很好的发现!那确实是个打字错误! - Louis Thibault
好的,很酷,我打算更新我下面发布的答案来处理撇号 =) - joshcartme
3个回答

15

我认为在你的情况下使用正则表达式是可以接受的。以下这个正则表达式应该可以满足你的需求:

def remove_html_tags(data):
    p = re.compile(r'<.*?>')
    return p.sub('', data)
我在这里找到了代码片段(http://love-python.blogspot.com/2008/07/strip-html-tags-using-python.html)。
编辑:只会删除形如<img .... />的内容。
def remove_img_tags(data):
    p = re.compile(r'<img.*?/>')
    return p.sub('', data)

我之前也看过那个页面,但是对于所提到的正则表达式有点困惑(请注意我对正则表达式的使用一无所知)。为什么要用 .*? 这个字符串?难道不应该写成类似 <img src*> 的形式吗? - Louis Thibault
1
我之前发布的第一个版本是通过删除 < 和 > 之间的任何内容来实现的。如果你在纯文本中有其他 < 或 > 的实例(而不是作为 HTML 标签),它会删除不应该删除的内容。我刚刚发布了另一个更加精确的版本。 - joshcartme
又有一个快速问题。我应该提到,我试图从UTF-32字节串中释放的字符串是带有<img>标签的。为了使其工作,我需要做些特殊的事情吗?我似乎没有检测到任何<img>标签... - Louis Thibault
在 '*' 后面添加 '?' 可以使其变得非贪婪。 - Ray
嗯,我对UTF-32字节串不太确定。所以它根本就不起作用了? - joshcartme

3

由于这段文字只包含图像标签,因此使用正则表达式可能是可以的。但对于其他任何内容,最好使用真正的HTML解析器。幸运的是,Python提供了一个!这很基本--要完全功能,这将不得不处理更多的边角情况。(最值得注意的是,XHTML样式的空标签(以斜杠结尾的<... />)在这里没有正确处理。)

>>> from HTMLParser import HTMLParser
>>> 
>>> class TagDropper(HTMLParser):
...     def __init__(self, tags_to_drop, *args, **kwargs):
...         HTMLParser.__init__(self, *args, **kwargs)
...     self._text = []
...         self._tags_to_drop = set(tags_to_drop)
...     def clear_text(self):
...         self._text = []
...     def get_text(self):
...         return ''.join(self._text)
...     def handle_starttag(self, tag, attrs):
...         if tag not in self._tags_to_drop:
...             self._text.append(self.get_starttag_text())
...     def handle_endtag(self, tag):
...         self._text.append('</{0}>'.format(tag))
...     def handle_data(self, data):
...         self._text.append(data)
... 
>>> td = TagDropper([])
>>> td.feed('A line of text\nA line of text with an <img url="foo"> tag\nAnother line of text with a <br> tag\n')
>>> print td.get_text()
A line of text
A line of text with an <img url="foo"> tag
Another line of text with a <br> tag

并且要删除 img 标签...

>>> td = TagDropper(['img'])
>>> td.feed('A line of text\nA line of text with an <img url="foo"> tag\nAnother line of text with a <br> tag\n')
>>> print td.get_text()
A line of text
A line of text with an  tag
Another line of text with a <br> tag

1
太棒了,谢谢!我现在认为我会使用正则表达式,因为它似乎涉及的代码较少(简化,简化!)。 - Louis Thibault

0

我的解决方案是:

def remove_HTML_tag(tag, string):
    string = re.sub(r"<\b(" + tag + r")\b[^>]*>", r"", string)
    return re.sub(r"<\/\b(" + tag + r")\b[^>]*>", r"", string)

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