BeautifulSoup解析器将分号附加到裸露的&符号,修改URL?

c0l*_*row 7 python beautifulsoup

我试图解析python中的一些网站,其中链接到其他网站,但在纯文本,而不是"a"标签.使用BeautifulSoup我得到了错误的答案.考虑以下代码:

import BeautifulSoup

html = """<html>
            <head>
              <title>Test html</title>
            </head>
            <body>
              <div>
                example.com/a.php?b=2&c=15
              </div>
            </body>
          </html>"""

parsed = BeautifulSoup.BeautifulSoup(html)
print parsed
Run Code Online (Sandbox Code Playgroud)

当我运行上面的代码时,我得到以下输出:

<html>
  <head>
    <title>Test html</title>
  </head>
  <body>
    <div>
      example.com/a.php?b=2&c;=15
    </div>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

注意"div"中的链接和b = 2&c; = 15的部分.它与原始HTML不同.为什么BeautifulSoup会以这种方式搞乱链接.它是否试图自动创建HTML entites?怎么预防这个?

smc*_*mci 7

显然BS有一个解析URL内的&符号的未记录问题,我只是在他们的讨论论坛搜索'分号'.根据2009年的讨论,裸体&是严格无效的,必须替换为&amp;虽然浏览器接受这一点,所以它看起来很迂腐.

我同意这种解析行为是假的,你应该联系他们的列表,要求他们至少将这更好地记录为已知问题,并在将来修复它.

解决方法:无论如何,您的解决方法很可能是re.sub(...)捕获和扩展&- > &amp;仅在URL内部.可能你需要一个反向函数来在输出中压缩它们.您需要一个更高级的正则表达式才能捕获URL中的仅&符号,但无论如何:

# Minimal string to tickle this
#html = "<html>example.com/a.php?b=2&c=15&d=42</html>"
html = "<html>example.com/a.php?b=2&c=15&amp;d=29&e=42</html>"

html = re.sub(r'&(?!amp;)', r'&amp;', html)

parsed = BeautifulSoup.BeautifulSoup(html)
>>> print parsed.text.encode('utf-8')
'example.com/a.php?b=2&amp;c=15'

>>> re.sub(r'&amp;', r'&', parsed.text.encode('utf-8'))
'example.com/a.php?b=2&c=15'
Run Code Online (Sandbox Code Playgroud)

可能还有其他更多的BS-thonic方法.您可能想帮助测试4.0 beta.