【问题标题】:Python BeautifulSoup Ampersand issue Mac vs. Linux UbuntuPython BeautifulSoup Ampersand 问题 Mac vs. Linux Ubuntu
【发布时间】:2013-10-07 21:12:16
【问题描述】:

我读到 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 的情况下制作跨平台代码?非常感谢,

【问题讨论】:

  • 我刚刚在 Debian 和 Mac OS X 上损坏了 &lt;td&gt;S&amp;amp;P500;&lt;/td&gt;,版本 4.3.2 由 pip 安装。看起来像一个错误。

标签: python html linux macos beautifulsoup


【解决方案1】:

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

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

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

然后它重新解析字符串并找到&amp;P500;。现在它不会将P500 识别为有效名称,并将&amp;amp; 转换为&amp;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的人能给你一个合适的解决方案,祝你好运。

【讨论】:

  • 谢谢,很有用 - 似乎确实存在不同的黑白系统行为,请参阅:link
  • 很有可能,但该链接尤其似乎是编码问题。 & 符号在 ascii 集中,所以这些问题不应该影响这个例子。
  • 我猜蛮力将创建一个 ascii 字符及其数字代码/快捷方式代码的字典 - 然后搜索所有 & 字符,如果它们后面没有构成代码的字符,用 & 替换 &
  • 这就是它的作用,python 的 HTMLParser 匹配 &amp;[^\s]+ 之类的东西作为 entityref 并将其传递给 handle_entityref 函数。然后我们使用 HTML_ENTITY_TO_CHARACTER.get(name) 检查它是否在字典中,如果我们在字典中没有找到它,则忽略它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-02
  • 1970-01-01
  • 1970-01-01
  • 2020-05-08
相关资源
最近更新 更多