【问题标题】:How to eliminate html tags?如何消除html标签?
【发布时间】:2011-10-15 04:46:02
【问题描述】:

我正在从页面中获取第一段并尝试提取适合作为标签或关键字的单词。在某些段落中有链接,我想删除标签:

例如,如果文本是

A <b>hex triplet</b> is a six-digit, three-<a href="/wiki/Byte"
enter code heretitle="Byte">byte</a> ...

我要删除

<b></b><a href="/wiki/Byte" title="Byte"></a>

到此结束

A hex triplet is a six-digit, three-byte ...

这样的正则表达式不起作用:

>>> text = """A <b>hex triplet</b> is a six-digit, three-<a href="/wiki/Byte"
    enter code heretitle="Byte">byte</a> ..."""
>>> f = re.findall(r'<.+>', text)
>>> f
['<b>hex triplet</b>', '</a>']
>>>

最好的方法是什么?

我发现了几个类似的问题,但我认为没有一个可以解决这个特定问题。

使用 BeautifulSoup 提取示例进行更新(提取删除包含其文本的标签,并且必须为每个标签单独运行:

>>> soup = BeautifulSoup(text)
>>> [s.extract() for s in soup('b')]
[<b>hex triplet</b>]
>>> soup
A  is a six-digit, three-<a href="/wiki/Byte" enter code heretitle="Byte">byte</a> ...
>>> [s.extract() for s in soup('a')]
[<a href="/wiki/Byte" enter code heretitle="Byte">byte</a>]
>>> soup
A  is a six-digit, three- ...
>>> 

更新

对于有同样问题的人:正如 Brendan Long 所说,this answer 使用 HtmlParser 效果最好。

【问题讨论】:

标签: python regex


【解决方案1】:

Beautiful Soup 是您问题的答案!试试看,非常棒!

一旦你使用它,HTML解析将变得如此简单。

>>> text = """A <b>hex triplet</b> is a six-digit, three-<a href="/wiki/Byte"
... enter code heretitle="Byte">byte</a> ..."""
>>> soup = BeautifulSoup(text)
>>> ''.join(soup.findAll(text=True))
u'A hex triplet is a six-digit, three-byte ...'

如果您将要提取的所有文本都包含在一些外部标签中,例如&lt;body&gt; ... &lt;/body&gt; 或一些&lt;div id="X"&gt; .... &lt;/div&gt;,那么您可以执行以下操作(此插图假设您要提取的所有文本都包含在&lt;body&gt; 标签)。现在您可以选择性地仅从一些需要的标签中提取文本。

(查看文档和示例,您会发现许多解析 DOM 的方法)

>>> text = """<body>A <b>hex triplet</b> is a six-digit, 
... three-<a href="/wiki/Byte"
... enter code heretitle="Byte">byte</a>
... </body>"""
>>> soup = BeautifulSoup(text)
>>> ''.join(soup.body.findAll(text=True))
u'A hex triplet is a six-digit, three-byte'

【讨论】:

  • 我使用 extract 添加了一个 Beautiful Soup 示例。但是提取会删除包含其文本内容的标签,而且我还需要为 html 中的每个标签运行extract。有没有更好的方法来用 Beautiful Soup 做到这一点?
  • @Zeynel 解决方案有帮助吗?
  • 是的,这很有帮助,但在这种情况下,我决定在这里使用答案stackoverflow.com/questions/753052/…。再次感谢。
  • 我回来尝试这个解决方案,但在我的情况下,文本没有包含在 标签或
    标签中。我正在使用这样的 js 获得页面的第一段:var p = document.getElementsByTagName("p")[0]; 当文本不是 DOM 的一部分时,有没有办法让你的答案起作用?谢谢
【解决方案2】:

+ 量词是贪婪的,这意味着它会找到最长的匹配项。添加? 以强制它找到最短可能的匹配项:

>>> re.findall(r'<.+?>', text)
['<b>', '</b>', '</a>']

另一种编写正则表达式的方法是在标记内显式排除直角括号,使用[^&gt;] 而不是.

>>> re.findall(r'<[^>]+>', text)
['<b>', '</b>', '<a href="/wiki/Byte"\n    enter code heretitle="Byte">', '</a>']

这种方法的一个优点是它还可以匹配换行符 (\n)。如果添加 re.DOTALL 标志,您可以使用 . 获得相同的行为。

>>> re.findall(r'<.+?>', text, re.DOTALL)
['<b>', '</b>', '<a href="/wiki/Byte"\n    enter code heretitle="Byte">', '</a>']

要去除标签,请使用re.sub:

>>> re.sub(r'<.+?>', '', text, flags=re.DOTALL)
'A hex triplet is a six-digit, three-byte ...'

【讨论】:

  • 好的,谢谢,您的编辑现在有效。如何从字符串中删除匹配项?我在文档中没有看到这种方法。
  • 字符串是不可变的;你可以重新分配它。
【解决方案3】:

这只是去除标签的基本元素。包括缺失的元素,
下面的 \w 代表带有前缀和正文的合格 unicode 标记名称,
需要一个 join() 语句来形成子表达式。解析的优点
带有正则表达式的 html/xml 不会在第一个格式错误的实例上失败,
使它非常适合修复它!缺点是它的速度很慢,尤其是
与 Unicode。

不幸的是,剥离标签会破坏内容,因为根据定义,标记 格式 内容。

在大网页上试试这个。这应该可以翻译成python。

$rx_expanded = '
<
(?:
    (?:
       (?:
           (?:script|style) \s*
         | (?:script|style) \s+ (?:".*?"|\'.*?\'|[^>]*?)+\s*
       )> .*? </(?:script|style)\s*
    )
  |
    (?:
        /?\w+\s*/?
      | \w+\s+ (?:".*?"|\'.*?\'|[^>]*?)+\s*/?
      | !(?:DOCTYPE.*?|--.*?--)
    )
)
>
';

$html =~ s/$rx_expanded/[was]/xsg;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 2012-10-19
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多