Python: Dlaczego `requests` niepoprawnie dekoduje tekst zamiast użyć UTF-8
Czasami requests niepoprawnie dekoduje tekst w response.text
- używa ISO-8859-1
(Latin-1
) zamiast UTF-8
nawet jeśli w HTML jest <meta charset="uft-8">
lub <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
.
Można to zobaczyć w response.headers['content-type']
oraz response.encoding
Problem jest ponieważ on nie używa <meta>
ale nagłówka Content-Type
, który zwykle ma wartość text/html; charset=UTF-8
(HTML5)
ale czasami jakiś server wysyła tylko text/html
a domyślne kodowanie dla takiej wartości jest ISO-8859-1
(HTML4)
Na szczęście on także używa chardet aby rozpoznać kodowanie w tekście i zapisuje to w response.apparent_encoding
więc można zrobić:
print(response.content.decode(response.apparent_encoding))
lub
response.encoding = response.apparent_encoding
print(response.text)
Przykładowy kod
import requests
import lxml.html
import chardet
r = requests.get('https://travel.rakuten.co.jp/')
print('content-type:', r.headers['content-type'])
print('encoding:', r.encoding)
print('apparent:', r.apparent_encoding)
print('chardet :', chardet.detect(r.content) )
# wrong result
html = r.text
tree = lxml.html.fromstring(html)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
print('1:', result.text)
# correct result
detected_encoding = chardet.detect(r.content)['encoding']
html = r.content.decode(detected_encoding)
tree = lxml.html.fromstring(html)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
print('2:', result.text)
# correct result
html = r.content.decode(r.apparent_encoding)
tree = lxml.html.fromstring(html)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
print('3:', result.text)
# correct result
r.encoding = r.apparent_encoding
html = r.text
tree = lxml.html.fromstring(html)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
print('4:', result.text)
Result:
encoding: ISO-8859-1
apparent: utf-8
chardet : {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
1: å½å
æ
è¡
2: 国内旅行
3: 国内旅行
4: 国内旅行
If you like it
Buy a Coffee
