0

我已经读过 BeautifulSoup 存在与符号 (&) 的问题,这些符号在 HTML 中并不严格正确,但大多数浏览器仍能正确解释。然而奇怪的是,我在 Mac 系统和 Ubuntu 系统上得到了不同的行为,两者都使用 bs4 版本 4.3.2:

html='<td>S&P500</td>'
s=bs4.BeautifulSoup(html)

在 Ubuntu 系统上 s 等于:

<td>S&amp;P500;</td>

注意最后添加的分号,这是一个真正的问题

在 mac 系统上:

<html><head></head><body>S&amp;P500</body></html>

没关系 html/head/body 标签,我可以处理它,但请注意这次 S&P 500 被正确解释,没有添加“;”。

知道发生了什么吗?如何在不使用丑陋的 hack 的情况下制作跨平台代码?非常感谢,

4

1 回答 1

1

首先,我无法使用 python2.7.1 和 beautifulsoup4.3.2 重现 mac 结果,也就是说,我在所有系统上都得到了额外的分号。

简单的解决方法是 a) 使用严格有效的 HTML,或 b) 在 & 符号后添加一个空格。您可能无法更改源代码,如果您可以在 python 中解析并替换它们,您将不需要 BeautifulSoup ;)

所以问题是 BeautifulSoupHTMLParser 首先转换S&P500S&P500;因为它假定P500是字符名称而您只是忘记了分号。

然后它重新解析字符串并找到&P500;. 现在它不能识别P500为有效名称并将其转换&&amp;而不触及其余部分。

这是一个愚蠢的猴子补丁,只是为了证明我的观点。我不太了解 BeautifulSoup 的内部工作原理,无法提出适当的解决方案。

from bs4 import BeautifulSoup
from bs4.builder._htmlparser import BeautifulSoupHTMLParser
from bsp.dammit import EntitySubstitution

def handle_entityref(self, name):
    character = EntitySubstitution.HTML_ENTITY_TO_CHARACTER.get(name)
    if character is not None:
        data = character
    else:
        # Previously was
        # data = "&%s;" % name
        data = "&%s" % name
    self.handle_data(data)

html = '<td>S&P500</td>'

# Pre monkeypatching
# <td>S&amp;P500;</td>
print(BeautifulSoup(html))

BeautifulSoupHTMLParser.handle_entityref = handle_entityref

# Post monkeypatching    
# <td>S&amp;P500</td>
print(BeautifulSoup(html))

希望更精通bs4的人能给你一个合适的解决方案,祝你好运。

于 2013-10-08T02:59:57.770 回答