使用BeautifulSoup解析文档但不解析<code>标签内容
我正在用Django写一个博客应用。我想让评论者可以使用一些标签(比如 <strong>
、a
等等),但要禁用其他所有标签。
另外,我还想让他们可以在 <code>
标签中放代码,并让pygments来解析这些代码。
比如,有人可能会写这样的评论:
I like this article, but the third code example <em>could have been simpler</em>:
<code lang="c">
#include <stdbool.h>
#include <stdio.h>
int main()
{
printf("Hello World\n");
}
</code>
问题是,当我用BeautifulSoup来解析评论,去掉不允许的HTML标签时,它也会解析 <code>
块里的内容,把 <stdbool.h>
和 <stdio.h>
当成HTML标签来处理。
我该怎么告诉BeautifulSoup不要解析 <code>
块呢?也许还有其他更适合这个工作的HTML解析器?
5 个回答
0
很遗憾,BeautifulSoup无法阻止解析代码块。
要实现你想要的效果,有一个解决方案是:
1) 移除代码块
soup = BeautifulSoup(unicode(content))
code_blocks = soup.findAll(u'code')
for block in code_blocks:
block.replaceWith(u'<code class="removed"></code>')
2) 进行常规解析,去掉不允许的标签。
3) 重新插入代码块,并重新生成HTML。
stripped_code = stripped_soup.findAll(u"code", u"removed")
# re-insert pygment formatted code
我本来可以给你一些代码示例,但我最近看到一个博客,里面优雅地解决了这个问题。
1
来自 Python wiki
>>>import cgi
>>>cgi.escape("<string.h>")
>>>'<string.h>'
>>>BeautifulSoup('<string.h>',
... convertEntities=BeautifulSoup.HTML_ENTITIES)
1
问题在于,<code>
标签是按照普通的 HTML 规则来处理的,标签里面的内容依然被当作 HTML。其实这些标签主要是为了让 CSS 样式能够正常工作,并不是为了改变解析规则。
你想做的事情是创建一种与 HTML 非常相似但又不完全相同的标记语言。一个简单的解决办法是设定一些规则,比如说,“<code>
和 </code>
必须单独占一行”,然后自己进行一些预处理。
- 一种非常简单但不完全可靠的方法是把
^<code>$
替换成<code><![CDATA[
,把^</code>$
替换成]]></code>
。这个方法不太可靠,因为如果代码块里面包含]]>
,就会出问题。 - 一个更安全的选择是把代码块里面的危险字符(比如
<
、>
和&
)替换成它们对应的字符实体引用(比如<
、>
和&
)。你可以通过把每个识别出来的代码块传给cgi.escape(code_block)
来实现。
完成预处理后,像往常一样把结果提交给 BeautifulSoup。