【问题标题】:scrape with correct character encoding (python requests + beautifulsoup)使用正确的字符编码进行抓取(python 请求 + beautifulsoup)
【发布时间】:2017-09-16 11:16:44
【问题描述】:

我在解析此网站时遇到问题:http://fm4-archiv.at/files.php?cat=106

它包含特殊字符,例如变音符号。看这里:

如您在上面的屏幕截图中所见,我的 chrome 浏览器可以正确显示变音符号。但是在其他页面(例如:http://fm4-archiv.at/files.php?cat=105)上,变音符号无法正确显示,如下面的屏幕截图所示:

元 HTML 标记在页面上定义以下字符集:

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>

我使用 python requests 包获取 HTML,然后使用 Beautifulsoup 抓取所需的数据。我的代码如下:

r = requests.get(URL)
soup = BeautifulSoup(r.content,"lxml")

如果我打印编码 (print(r.encoding),结果是 UTF-8。如果我通过调用r.encoding = ISO-8859-1 手动将编码更改为ISO-8859-1cp1252,则当我在控制台上输出数据时没有任何变化。这也是我的主要问题。

r = requests.get(URL)
r.encoding = 'ISO-8859-1'
soup = BeautifulSoup(r.content,"lxml")

仍然会在我的 python IDE 的控制台输出中显示以下字符串:

Der Wildlöwenpfleger

应该是

Der Wildlöwenpfleger

如何更改我的代码以正确解析变音符号?

【问题讨论】:

    标签: python encoding utf-8 python-requests


    【解决方案1】:

    我刚刚找到了两个解决方案。你能确认一下吗?

    Soup = BeautifulSoup(r.content.decode('utf-8','ignore'),"lxml")
    

    Soup = BeautifulSoup(r.content,"lxml", fromEncoding='utf-8')
    

    这两个结果都产生以下示例输出:

    Der Wildlöwenpfleger
    

    编辑: 我只是想知道为什么这些工作,因为r.encoding 无论如何都会导致UTF-8。这告诉我,请求无论如何将数据处理为UTF-8 数据。因此,我想知道为什么 .decode('utf-8','ignore')fromEncoding='utf-8' 会产生所需的输出?

    编辑 2: 好吧,我想我现在明白了。 .decode('utf-8','ignore')fromEncoding='utf-8' 意味着实际数据被编码为UTF-8,Beautifulsoup 应该将其解析为UTF-8 编码数据,实际上就是这种情况。

    我假设requests 正确地将其处理为UTF-8,但BeautifulSoup 没有。因此,我必须做这个额外的解码。

    【讨论】:

    • soup = BeautifulSoup(response.content, 'html.parser'),它对我有用
    • @giasuddin 对我来说它也有效,但是一些 utf-8 网站被破坏了,所以我使用了条件,如果响应是 utf-8 使用 .text else .content
    【解决方案2】:

    一般情况下,不要使用r.content(接收到的字节串),而是使用r.text,它是使用requests确定的编码解码的内容。

    在这种情况下,requests 将使用 UTF-8 解码传入的字节字符串,因为这是服务器在 Content-Type 标头中报告的编码:

    import requests
    
    r = requests.get('http://fm4-archiv.at/files.php?cat=106')
    
    >>> type(r.content)    # raw content
    <class 'bytes'>
    >>> type(r.text)       # decoded to unicode
    <class 'str'>    
    >>> r.headers['Content-Type']
    'text/html; charset=UTF-8'
    >>> r.encoding
    'UTF-8'
    
    >>> soup = BeautifulSoup(r.text, 'lxml')
    

    这将解决“Wildlöwenpfleger”问题,但是页面的其他部分随后会开始中断,例如:

    >>> soup = BeautifulSoup(r.text, 'lxml')     # using decoded string... should work
    >>> soup.find_all('a')[39]
    <a href="details.php?file=1882">Der Wildlöwenpfleger</a>
    >>> soup.find_all('a')[10]
    <a href="files.php?cat=87" title="Stermann und Grissemann sind auf Sommerfrische und haben Hermes ihren Salon �bergeben. Auf Streifz�gen durch die Popliteratur st��t Hermes auf deren gro�e Themen und h�rt mit euch quer. In der heutige">Salon Hermes (6 files)
    

    显示“Wildlöwenpfleger”已修复,但现在“übergeben”和第二个链接中的其他内容已损坏。

    似乎在一个 HTML 文档中使用了多种编码。第一个链接使用UTF-8编码:

    >>> r.content[8013:8070].decode('iso-8859-1')
    '<a href="details.php?file=1882">Der Wildlöwenpfleger</a>'
    
    >>> r.content[8013:8070].decode('utf8')
    '<a href="details.php?file=1882">Der Wildlöwenpfleger</a>'
    

    但第二个链接使用 ISO-8859-1 编码:

    >>> r.content[2868:3132].decode('iso-8859-1')
    '<a href="files.php?cat=87" title="Stermann und Grissemann sind auf Sommerfrische und haben Hermes ihren Salon übergeben. Auf Streifzügen durch die Popliteratur stößt Hermes auf deren große Themen und hört mit euch quer. In der heutige">Salon Hermes (6 files)\r\n</a>'
    
    >>> r.content[2868:3132].decode('utf8', 'replace')
    '<a href="files.php?cat=87" title="Stermann und Grissemann sind auf Sommerfrische und haben Hermes ihren Salon �bergeben. Auf Streifz�gen durch die Popliteratur st��t Hermes auf deren gro�e Themen und h�rt mit euch quer. In der heutige">Salon Hermes (6 files)\r\n</a>'
    

    显然在同一个 HTML 文档中使用多种编码是不正确的。除了联系文档的作者并要求更正之外,您可以轻松地处理混合编码。也许您可以在处理数据时对数据运行chardet.detect(),但这并不令人愉快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-21
      • 2023-03-23
      • 1970-01-01
      • 2020-07-24
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      相关资源
      最近更新 更多