python lxml 在某些情况下无法解析日语
python lxml can't parse japanese in some case
我正在使用 lxml 4.5.0 从网站抓取数据。
在下面的例子中效果很好
chrome_ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 " \
"(KHTML, like Gecko) Chrome/77.0.3864.0 Safari/537.36"
with requests.Session() as s:
s.headers.update({'User-Agent': chrome_ua})
resp = s.get('https://www.yahoo.co.jp')
parser = etree.HTMLParser()
tree = etree.parse(StringIO(resp.text), parser)
result = tree.xpath('//*[@id="tabTopics1"]/a')[0]
result.text
作为 result.text
给我正确的文本 'ニュース'
但是当我尝试另一面时,它没能正确地表达日语。
chrome_ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 " \
"(KHTML, like Gecko) Chrome/77.0.3864.0 Safari/537.36"
with requests.Session() as s:
s.headers.update({'User-Agent': chrome_ua})
resp = s.get('https://travel.rakuten.co.jp/')
parser = etree.HTMLParser()
tree = etree.parse(StringIO(resp.text), parser)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
result.text
那个result.text
给我'å\x9b½å\x86\x85æ\x97\x85è¡\x8c'
,应该是'国内旅行'
我试过parser = etree.HTMLParser(encoding='utf-8')
,但还是不行。
在这种情况下,如何使 lxml 正确解析日语?
使用
print(resp.encoding)
你可以看到它使用 ISO-8859-1
将 resp.content
转换为 resp.text
但是你可以直接得到resp.content
然后用不同的编码解码
StringIO( resp.content.decode('utf-8') )
使用模块 chardet 你可以尝试检测你应该使用什么编码
print( chardet.detect(resp.content) )
结果
{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
import requests
from lxml import etree
from io import StringIO
import chardet
chrome_ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 " \
"(KHTML, like Gecko) Chrome/77.0.3864.0 Safari/537.36"
with requests.Session() as s:
s.headers.update({'User-Agent': chrome_ua})
resp = s.get('https://travel.rakuten.co.jp/')
print(resp.encoding)
print( chardet.detect(resp.content) )
detected_encoding = chardet.detect(resp.content)['encoding']
parser = etree.HTMLParser()
#tree = etree.parse(StringIO(resp.content.decode('utf-8')), parser)
tree = etree.parse(StringIO(resp.content.decode(detected_encoding)), parser)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
result.text
编辑: @usr2564301 在答案
中找到
可以用
解决
resp.encoding = resp.apparent_encoding
使用chardet
识别编码。
我正在使用 lxml 4.5.0 从网站抓取数据。
在下面的例子中效果很好
chrome_ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 " \
"(KHTML, like Gecko) Chrome/77.0.3864.0 Safari/537.36"
with requests.Session() as s:
s.headers.update({'User-Agent': chrome_ua})
resp = s.get('https://www.yahoo.co.jp')
parser = etree.HTMLParser()
tree = etree.parse(StringIO(resp.text), parser)
result = tree.xpath('//*[@id="tabTopics1"]/a')[0]
result.text
作为 result.text
给我正确的文本 'ニュース'
但是当我尝试另一面时,它没能正确地表达日语。
chrome_ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 " \
"(KHTML, like Gecko) Chrome/77.0.3864.0 Safari/537.36"
with requests.Session() as s:
s.headers.update({'User-Agent': chrome_ua})
resp = s.get('https://travel.rakuten.co.jp/')
parser = etree.HTMLParser()
tree = etree.parse(StringIO(resp.text), parser)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
result.text
那个result.text
给我'å\x9b½å\x86\x85æ\x97\x85è¡\x8c'
,应该是'国内旅行'
我试过parser = etree.HTMLParser(encoding='utf-8')
,但还是不行。
在这种情况下,如何使 lxml 正确解析日语?
使用
print(resp.encoding)
你可以看到它使用 ISO-8859-1
将 resp.content
转换为 resp.text
但是你可以直接得到resp.content
然后用不同的编码解码
StringIO( resp.content.decode('utf-8') )
使用模块 chardet 你可以尝试检测你应该使用什么编码
print( chardet.detect(resp.content) )
结果
{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
import requests
from lxml import etree
from io import StringIO
import chardet
chrome_ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 " \
"(KHTML, like Gecko) Chrome/77.0.3864.0 Safari/537.36"
with requests.Session() as s:
s.headers.update({'User-Agent': chrome_ua})
resp = s.get('https://travel.rakuten.co.jp/')
print(resp.encoding)
print( chardet.detect(resp.content) )
detected_encoding = chardet.detect(resp.content)['encoding']
parser = etree.HTMLParser()
#tree = etree.parse(StringIO(resp.content.decode('utf-8')), parser)
tree = etree.parse(StringIO(resp.content.decode(detected_encoding)), parser)
result = tree.xpath('//*[@id="rt-nav-box"]/li[1]/a')[0]
result.text
编辑: @usr2564301 在答案
中找到可以用
解决 resp.encoding = resp.apparent_encoding
使用chardet
识别编码。