推荐学习书目
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 · Mar 8, 2021 · 3240 views
    This topic created in 1916 days ago, the information mentioned may be changed or developed.

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

    大概这样就可以了。
    uti6770werty
        9
    uti6770werty  
    OP
       Mar 8, 2021
    @wevsty 内容带了一堆\xa0,\r\n 的特殊字符,

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

    r = requests.get(url)
    r.encoding = "gbk"
    html = r.text
    Rhilip
        17
    Rhilip  
       Mar 8, 2021
    中文 Windows 下终端编码问题,因为出错在 print 上
    lusi1990
        18
    lusi1990  
       Mar 8, 2021
    打印 r.content 看看
    .decode('utf-8',errors='ignore') 添加参数忽略错误
    geebos
        19
    geebos  
    PRO
       Mar 10, 2021
    这个问题应该是 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)
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2737 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 49ms · UTC 12:33 · PVG 20:33 · LAX 05:33 · JFK 08:33
    ♥ Do have faith in what you're doing.