Python'latin-1'编解码器无法编码字符-如何忽略字符?

时间:2019-02-15 16:30:21

标签: python web-scraping beautifulsoup html-parsing

这是我代码的要点。它正在尝试从旧网站获取一些文本。不是我的,所以我无法更改来源。

from bs4 import BeautifulSoup
import requests

response = requests.get("https://mattgemmell.com/network-link-conditioner-in-lion/")
data = response.text
soup = BeautifulSoup(data, 'lxml')
article = soup.find_all('article')[0]
text = article.find_all('p')[1].text 
print(text)

为此:

'如果您是使用网络的Mac或iOS应用程序的开发人员,则Mac OS X 10.7开发人员工具中的新功能x80 \ x99 xx80 \x9cLionâ€x80 \ x9d(请阅读我对《卫报》的评论),这对您很有用。这篇简短的文章介绍了它的工作原理。'

我可以用它来转换â\ x80 \ x99之类的部分:

converted_text = bytes(text, 'latin-1').decode('utf-8')

实际上可行。

但是如果您得到文本的不同部分:

text = article.find_all('p')[8].text 

给我:

'\ n←在Lion上的文本中查找模式\ n在OS X Lion上使用空格→\ n'

使用bytes(text, 'latin-1')给我:

'latin-1'编解码器无法在位置1编码字符'\ u2190':序数不在范围(256)中

我认为是箭头?如何做到这一点,以便所有非拉丁字符都将被自动忽略并丢弃。

任何想法都会最有帮助!

2 个答案:

答案 0 :(得分:1)

使用bytes的第三个参数来告诉它如何处理错误:

converted_text = bytes(text, 'latin-1', 'ignore')
                                         ^^^^^^

您会丢失箭头,但其他一切都保持不变:

>>> text = '\n← Find Patterns in text on Lion\nUsing Spaces on OS X Lion →\n'
>>> converted_text = bytes(text, 'latin-1', 'ignore')
>>> converted_text
'\n Find Patterns in text on Lion\nUsing Spaces on OS X Lion \n'

有关文档中参数的更多信息-https://docs.python.org/3.3/howto/unicode.html

  

errors参数指定当无法根据编码规则转换输入字符串时的响应。此参数的合法值为'strict'(引发UnicodeDecodeError异常),'replace'(使用U + FFFD,REPLACEMENT CHARACTER)或'ignore'(只需将字符排除在Unicode结果之外)。

答案 1 :(得分:1)

您不想忽略这些字符。它们的症状是您接收到的数据已使用错误的字符编码进行了解码。在您的情况下,requests错误地猜测编码为latin-1。实际编码为utf-8,并在HTML响应的<meta>标签中指定。 requests是用于处理HTTP的库,它不了解HTML。由于Content-Type标头未指定编码,requests只能猜测编码。 BeautifulSoup是用于HTML的库,它非常擅长检测编码。因此,您希望从响应中获取原始字节,并将其传递给BeautifulSoup。即。

from bs4 import BeautifulSoup
import requests

response = requests.get("https://mattgemmell.com/network-link-conditioner-in-lion/")
data = response.content # we now get `content` rather than `text`
assert type(data) is bytes
soup = BeautifulSoup(data, 'lxml')
article = soup.find_all('article')[0]
text = article.find_all('p')[1].text 
print(text)

assert type(text) is str
assert 'Mac OS X 10.7 “Lion”' in text