还是 Python requests 的字符编码问题,明明已经正确析出真 html 文本内容, str 对象依然含有 gbk 环境不能处理的特殊字符...

2021-03-08 10:50:54 +08:00
 uti6770werty

经过各位高手前几天指点,
可以确认 http 服务器的通信过程没有指明编码, 网页内容里虽然指定了 content="text/html; charset=utf-8",但这个不能影响到 requests 判断。。 被 requests 认为是"ISO-8859-1"了

r = requests.get(link)
print(r..encoding)  # <- ISO-8859-1
print(r.apparent_encoding) # <- UTF-8-SIG

r.encoding = 'UTF-8-SIG'
print(r.text) # <- 不再报编码错误,能正确输出

retrun r.text # 从函数里把 html 文本送出去

# 函数外
htmlString = reguestGeturl(urllink)
for i in BeautifulSoup(htmlString ,'lxml').findAll('td'):
        print(i)

这时候,又有编码错误了。。。
print(i)
UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 282: illegal multibyte sequence

为什么还会有\xa0 呢,处理出来的 string,已经没有\xa0 才对呀
望各位高手指出问题所在,谢谢解答!

2339 次点击
所在节点    Python
19 条回复
zpfhbyx
2021-03-08 11:17:00 +08:00
#coding=utf8
uti6770werty
2021-03-08 11:19:22 +08:00
@zpfhbyx 做了 htmlString = "#coding=utf8\n" + htmlString
还是老样子,这个应该不行?
ClutchBear
2021-03-08 11:21:07 +08:00
@uti6770werty 意思应该是在 python 代码的第一行加上这个. 不是 html 源码中加..
uti6770werty
2021-03-08 11:21:27 +08:00
如果是用 replace 的方式,替换完\xa0,还有\xae,\xa***之类的东西,有些担心会替换了很多有用的字符。。。
uti6770werty
2021-03-08 11:22:56 +08:00
@ClutchBear 每个.py 文件,都加了的。。。。
renmu123
2021-03-08 11:29:17 +08:00
utf-8 和 urf-8-sig 可不是一个编码,还有可能是网页头文件是瞎标的,压根不是 utf-8 编码
uti6770werty
2021-03-08 11:32:48 +08:00
@renmu123 明白,可是我 print(htmlString),已经能看到中文了
str 对象携带的内容编码是 UTF-8-SIG
搜了网络,似乎从来没有人做过对 str 对象本身要转编码这种事情。。。。
wevsty
2021-03-08 11:34:02 +08:00
BeautifulSoup(htmlString, 'lxml', from_encoding="utf-8")

大概这样就可以了。
uti6770werty
2021-03-08 11:44:28 +08:00
@wevsty 内容带了一堆\xa0,\r\n 的特殊字符,

还是想在做 BeautifulSoup 之前,正确地把字符编码转好
还是根本没办法,必须要对这些\xa0,特殊字符做手动替换吗?
wevsty
2021-03-08 12:07:09 +08:00
@uti6770werty
只是要做编码转换的话自己用 decode 和 encode 转就行了。
GBK->UTF-8
"string".decode('gbk').encode('utf-8')

UTF-8->GBK
"string".decode('utf-8').encode('gbk')
uti6770werty
2021-03-08 12:32:25 +08:00
@wevsty 明白您的意思,Python 3.66 的 str 已经没有 decode()这个方法了,虽然知道是要转成 gbk,一直都没能找到 utf-8-SIG 转 gbk 的正确方式....
wevsty
2021-03-08 12:47:25 +08:00
@uti6770werty

更正一下,写错了.
string 是没有 decode 方法的,只有 bytes 才有 decode 。

GBK->UTF-8
b"GBK string".decode('gbk').encode('utf-8')

UTF-8->GBK
"string".encode('gbk')
shyrock
2021-03-08 14:06:10 +08:00
python3 还有字符串处理和显示问题?这问题真挺恶心的,日志窗口能显示中文,调试窗口就是乱码
imn1
2021-03-08 14:26:07 +08:00
如果你是 windows 平台,cmd 环境也要设成 utf8,windows 对应是 codepage 65001
Sylv
2021-03-08 14:39:41 +08:00
你这个是中文 Windows 下终端编码导致的 print 问题,print str(unicode) 类型字符串时 Python 要把字符串用终端编码 encode 成 bytes 后才能输出显示,Windows 中文终端默认编码是 gbk,而你的字符串里有 gbk 编码不了的字符,于是就报错了,解决方法是把终端编码改成 utf-8 。
dier
2021-03-08 14:51:46 +08:00
我之前也遇到过类似的问题,用的是下面的方法,你参考一下

r = requests.get(url)
r.encoding = "gbk"
html = r.text
Rhilip
2021-03-08 15:59:29 +08:00
中文 Windows 下终端编码问题,因为出错在 print 上
lusi1990
2021-03-08 16:02:03 +08:00
打印 r.content 看看
.decode('utf-8',errors='ignore') 添加参数忽略错误
geebos
2021-03-10 02:47:03 +08:00
这个问题应该是 windows 的控制台默认编码是 gbk 的问题,改一下控制台编码就行。

实际你的结果已经没有问题了,只是包含有不能转成 gbk 编码的字符,所以在用 print 输出的时候会报错,保存到文件在看就是正常的了。

如果实在觉得膈应的话,可以用下面的代码把 gbk 不支持的字符全部过滤掉。

def encoding_transform(text:'str', target_encoding:'str')->str:
"""
将字符串转换成目标编码,不能被目标编码编码的字符全部舍弃
"""
if not isinstance(text, str):
return text

text_list = []
while True:
try:
text = text.encode(target_encoding).decode(target_encoding)
text_list.append(text)
break
except UnicodeEncodeError as e:
position = int(re.findall(r'position (\d+):', str(e))[0])
text_list.append(text[:position])
text = text[position+1:]
return ''.join(text_list)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/759499

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX