【问题标题】:Python BeautifulSoup output unusual spacing and charactersPython BeautifulSoup 输出异常的间距和字符
【发布时间】:2025-12-29 03:50:06
【问题描述】:

我是 python 新手。

我正在尝试使用 BeautifulSoup 解析来自网站的数据,我之前已经成功使用过 BeautifulSoup。然而,对于这个特定的网站,返回的数据在每个字符之间都有空格,并且还有很多“&gt”字符。

奇怪的是,如果复制页面源并将其添加到我的本地 apache 实例并向我的本地副本发出请求,那么输出是完美的。我应该提到我的本地和网站之间的区别:

  1. 我的本地不使用 https
  2. 我的本地不需要身份验证,但是网站确实需要 Active Directory 身份验证,而我使用 requests_ntlm

import requests
from requests_ntlm import HttpNtlmAuth
from bs4 import BeautifulSoup

r = requests.get("http://WEBSITE/CONTEXT/",auth=HttpNtlmAuth('DOMAIN\USER','PASS'))
content = r.text
soup = BeautifulSoup(content, 'lxml')
print(soup)

【问题讨论】:

    标签: python beautifulsoup


    【解决方案1】:

    看起来本地服务器返回使用 UTF-8 编码的内容,而主网站使用 UTF-16。这表明主网站配置不正确。但是,可以使用代码解决此问题。

    Python 将请求默认编码为 UTF-8。 (我相信)这是基于响应头的。该请求有一个名为apparent_encoding 的方法,它读取流并使用chardet 检测正确的编码。但是,除非指定,否则不会消耗明显的编码。

    因此,通过设置 r.encoding = r.apparent_encoding,请求应该在两个环境中正确下载文本。

    代码应该类似于:

    r = requests.get("http://WEBSITE/CONTEXT/",auth=HttpNtlmAuth('DOMAIN\USER','PASS'))
    r.encoding = r.apparent_encoding # Override the default encoding
    content = r.text
    r.raise_for_status() # Always check for server errors before consuming the data.
    soup = BeautifulSoup(content, 'lxml') 
    print(soup.prettify()) # Should match print(content) (minus indentation)
    

    【讨论】:

    • 嗨@Greg 似乎 request.get 内容是问题所在。这就是我所看到的,如果我打印出 request.get 返回内容,它看起来很好,但是如果我将它通过管道传输到一个文件,它看起来很奇怪,每个第二个字符串都有一个 @ 字符 ��<^@!^@D^@O^@C^@T^@Y^@P^@E^@ ^@h^@t^@m^@l^@ 我已经尝试过 .encoding = 'utf-8' 但是输出还是一样的
    • 下一步将检查响应标头。在 requests.get() 之后添加 print(r.headers)。这应该给我们一个关于服务器返回什么的线索。另外,我相信您说过该 URL 在网络浏览器中有效。如果您检查查看源代码,它是否具有带有属性字符集的元 html 标记?
    • 是的网络浏览器工作,当我查看源代码时它看起来正确,没有其他字符 这是标题输出 {'Content-Type': 'text/html', 'Last-Modified' :'2020 年 6 月 10 日星期三 13:38:13 GMT','Accept-Ranges':'bytes','ETag':'"9d5abb632c3fd61:0"','Server':'Microsoft-IIS/8.5',' Persistent-Auth':'true','X-Powered-By':'ASP.NET','Date':'Wed,2020 年 6 月 10 日 14:08:18 GMT','Content-Length':'5557948' }
    • 有趣的是,Web 浏览器会发出相同的请求并以某种方式知道要显示内容。标头本身并没有提供任何关于什么编码类型(默认值除外)的线索。我们可以检查的下一件事是检查(在 3 行上) print(f"encoding: {r.encoding}") print(f" visible_encoding: {r.apparent_encoding}") print(f"content: {r.content}") # 是否包含html?
    • 您的本地版本工作正常,因为它将内容类型返回为 'text/html;字符集=UTF-8'。其他服务器没有的地方。它的编码为 UTF-8,但它看起来像它的 UTF-16。您可以尝试的一件事是 r.encoding = r.apparent_encoding,然后打印出 r.text 和 r.content。您可以尝试的另一件事是通过邮递员运行 api。