V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
uti6770werty
V2EX  ›  Python

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

  •  
  •   uti6770werty · 2021-03-08 10:50:54 +08:00 · 2486 次点击
    这是一个创建于 1360 天前的主题,其中的信息可能已经有所发展或是发生改变。

    经过各位高手前几天指点,
    可以确认 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 才对呀
    望各位高手指出问题所在,谢谢解答!

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

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

    还是想在做 BeautifulSoup 之前,正确地把字符编码转好
    还是根本没办法,必须要对这些\xa0,特殊字符做手动替换吗?
    wevsty
        10
    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
        11
    uti6770werty  
    OP
       2021-03-08 12:32:25 +08:00
    @wevsty 明白您的意思,Python 3.66 的 str 已经没有 decode()这个方法了,虽然知道是要转成 gbk,一直都没能找到 utf-8-SIG 转 gbk 的正确方式....
    wevsty
        12
    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
        13
    shyrock  
       2021-03-08 14:06:10 +08:00
    python3 还有字符串处理和显示问题?这问题真挺恶心的,日志窗口能显示中文,调试窗口就是乱码
    imn1
        14
    imn1  
       2021-03-08 14:26:07 +08:00
    如果你是 windows 平台,cmd 环境也要设成 utf8,windows 对应是 codepage 65001
    Sylv
        15
    Sylv  
       2021-03-08 14:39:41 +08:00 via iPhone
    你这个是中文 Windows 下终端编码导致的 print 问题,print str(unicode) 类型字符串时 Python 要把字符串用终端编码 encode 成 bytes 后才能输出显示,Windows 中文终端默认编码是 gbk,而你的字符串里有 gbk 编码不了的字符,于是就报错了,解决方法是把终端编码改成 utf-8 。
    dier
        16
    dier  
       2021-03-08 14:51:46 +08:00
    我之前也遇到过类似的问题,用的是下面的方法,你参考一下

    r = requests.get(url)
    r.encoding = "gbk"
    html = r.text
    Rhilip
        17
    Rhilip  
       2021-03-08 15:59:29 +08:00
    中文 Windows 下终端编码问题,因为出错在 print 上
    lusi1990
        18
    lusi1990  
       2021-03-08 16:02:03 +08:00
    打印 r.content 看看
    .decode('utf-8',errors='ignore') 添加参数忽略错误
    geebos
        19
    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)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1154 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 23:01 · PVG 07:01 · LAX 15:01 · JFK 18:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.