我读到 BeautifulSoup 存在与符号 (&) 的问题,这在 HTML 中并不严格正确,但仍能被大多数浏览器正确解释。然而奇怪的是,我在 Mac 系统和 Ubuntu 系统上得到不同的行为,两者都使用 bs4 版本 4.3.2:
html='<td>S&P500</td>'
s=bs4.BeautifulSoup(html)
在Ubuntu系统上s等于:
<td>S&P500;</td>
注意最后添加的分号,这是一个真正的问题
在mac系统上:
<html><head></head><body>S&P500</body></html>
不用管 html/head/body 标签,我可以处理它,但请注意这次正确解释了标准普尔 500 指数,没有添加“;”。
知道发生了什么事吗?如何在不诉诸丑陋黑客的情况下制作跨平台代码?非常感谢,
最佳答案
首先,我无法使用 python2.7.1 和 beautifulsoup4.3.2 重现 mac 结果,也就是说我在所有系统上都得到了额外的分号。
简单的解决方法是 a) 使用严格有效的 HTML,或 b) 在 & 符号后添加一个空格。您可能无法更改源代码,如果您可以在 python 中解析并替换它们,您就不需要 BeautifulSoup ;)
所以问题是 BeautifulSoupHTMLParser 首先将 S&P500
转换为 S&P500;
因为它假定 P500
是角色名称而你只是忘记了分号。
然后它重新解析字符串并找到 &P500;
。现在它不会将 P500
识别为有效名称并将 &
转换为 &
而不触及其余部分。
这是一个愚蠢的 monkeypatch 只是为了证明我的观点。我不太了解 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&P500;</td>
print(BeautifulSoup(html))
BeautifulSoupHTMLParser.handle_entityref = handle_entityref
# Post monkeypatching
# <td>S&P500</td>
print(BeautifulSoup(html))
希望更精通bs4的人能给你一个合适的解决方案,祝你好运。
关于Python BeautifulSoup & 问题 Mac 与 Linux Ubuntu,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19234880/