使用正确的字符编码进行抓取(python 请求 + beautifulsoup) [英] scrape with correct character encoding (python requests + beautifulsoup)

查看:21
本文介绍了使用正确的字符编码进行抓取(python 请求 + beautifulsoup)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在解析此网站时遇到问题:

正如您在上面的屏幕截图中看到的那样,我的 chrome 浏览器正确显示了变音符号.但是在其他页面上(例如:

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

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

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

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

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

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

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

Der Wildlöwenpfleger

应该是

Der Wildlöwenpfleger

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

解决方案

一般来说,不要使用 r.content 接收的字节串,而是使用 r.text> 这是使用 requests 确定的编码解码的内容.

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

导入请求r = requests.get('http://fm4-archiv.at/files.php?cat=106')>>>type(r.content) # 原始内容<类'字节'>>>>type(r.text) # 解码为 un​​icode<类'str'>>>>r.headers['内容类型']'文本/html;字符集=UTF-8'>>>编码'UTF-8'>>>汤 = BeautifulSoup(r.text, 'lxml')

这将解决Wildlöwenpfleger"问题,但是,页面的其他部分随后开始损坏,例如:

<预><代码>>>>汤 = BeautifulSoup(r.text, 'lxml') # 使用解码的字符串...应该可以工作>>>汤.find_all('a')[39]<a href="details.php?file=1882">Der Wildlöwenpfleger</a>>>>汤.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 undh rt mit euch quer. In der heutige">Salon Hermes (6 档)

显示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 eucherheutige">沙龙爱马仕(6 个文件)\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 Themenund h rt mit euch quer. In der heutige">Salon Hermes(6 个文件)\r\n</a>'

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

I have an issue parsing this website: http://fm4-archiv.at/files.php?cat=106

It contains special characters such as umlauts. See here:

My chrome browser displays the umlauts properly as you can see in the screenshot above. However on other pages (e.g.: http://fm4-archiv.at/files.php?cat=105) the umlauts are not displayed properly, as can be seen in the screenshot below:

The meta HTML tag defines the following charset on the pages:

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

I use the python requests package to get the HTML and then use Beautifulsoup to scrape the desired data. My code is as follows:

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

If I print the encoding (print(r.encoding) the result is UTF-8. If I manually change the encoding to ISO-8859-1 or cp1252 by calling r.encoding = ISO-8859-1 nothing changes when I output the data on the console. This is also my main issue.

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

still results in the following string shown on the console output in my python IDE:

Der Wildlöwenpfleger

instead it should be

Der Wildlöwenpfleger

How can I change my code to parse the umlauts properly?

解决方案

In general, instead of using r.content which is the byte string received, use r.text which is the decoded content using the encoding determined by requests.

In this case requests will use UTF-8 to decode the incoming byte string because this is the encoding reported by the server in the Content-Type header:

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')

That will fix the "Wildlöwenpfleger" problem, however, other parts of the page then begin to break, for example:

>>> 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)

shows that "Wildlöwenpfleger" is fixed but now "übergeben" and others in the second link are broken.

It appears that multiple encodings are used in the one HTML document. The first link uses UTF-8 encoding:

>>> 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>'

but the second link uses ISO-8859-1 encoding:

>>> 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>'

Obviously it is incorrect to use multiple encodings in the same HTML document. Other than contacting the document's author and asking for a correction, there is not much that you can easily do to handle the mixed encoding. Perhaps you can run chardet.detect() over the data as you process it, but it's not going to be pleasant.

这篇关于使用正确的字符编码进行抓取(python 请求 + beautifulsoup)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆