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
eggshell
V2EX  ›  Python

Python 子线程里创建 BeautifulSoup 对象会在终端打印 encoding error,主线程就没问题,求解惑

  •  
  •   eggshell ·
    gaoliang · 2018-03-26 18:50:21 +08:00 · 5450 次点击
    这是一个创建于 2433 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Python 子线程里创建 BeautifulSoup 对象会在终端打印encoding error : input conversion failed due to input error, 主线程里面一切正常。

    感觉应该是 lxml 的问题,但是没找到怎么解决,求解惑

    就几个特定的网页会出现这个问题,比如 http://zhuanlan.sina.com.cn/

    下面这个代码可以用来复现

    import requests
    from bs4 import BeautifulSoup
    from threading import Thread
    def test():
        r = requests.get('http://zhuanlan.sina.com.cn/')
        soup = BeautifulSoup(r.content,'lxml')
    
    print('在主线程中执行 test')
    test()
    
    print('在子线程中执行 test')
    t = Thread(target=test)
    t.start()
    t.join()
    

    输出如下

    在主线程中执行 test
    在子线程中执行 test
    encoding error : input conversion failed due to input error, bytes 0x95 0x50 0x22 0x20
    encoding error : input conversion failed due to input error, bytes 0x95 0x50 0x22 0x20
    encoding error : input conversion failed due to input error, bytes 0x95 0x50 0x22 0x20
    
    11 条回复    2018-03-27 13:42:17 +08:00
    seanzhao
        1
    seanzhao  
       2018-03-26 19:03:05 +08:00
    把你的解析那段替换成以下代码,不是线程问题,是编码问题。
    soup = BeautifulSoup(r.content.decode('ISO-8859-1'),'lxml')
    eggshell
        2
    eggshell  
    OP
       2018-03-26 19:47:01 +08:00
    @seanzhao 谢谢啦,不过应该不是编码的问题,试了下子线程里面还是会打印 encoding error, 主线程还是正常的
    ![截图]( )
    kenzh
        3
    kenzh  
       2018-03-26 20:24:38 +08:00
    试下 r.content.decode('gb2312', 'ignore').encode('gb2312')
    seanzhao
        4
    seanzhao  
       2018-03-26 20:30:18 +08:00
    @eggshell 好吧,给你的那段代码,我已经在本机测试通过的,不知道你那边是什么个情况。
    eggshell
        5
    eggshell  
    OP
       2018-03-26 20:42:00 +08:00
    @kenzh 这样就可以了。。 但是之前为什么主线程里面跑就正常,子线程里就不行呢, 好迷啊= =
    holajamc
        6
    holajamc  
       2018-03-26 21:42:40 +08:00
    import requests
    from bs4 import BeautifulSoup
    from threading import Thread


    def test():
    r = requests.get('http://zhuanlan.sina.com.cn/')
    print(r.encoding)
    soup = BeautifulSoup(r.content.decode('utf-8', 'ignore'), 'lxml')


    print('在主线程中执行 test')
    test()

    print('在子线程中执行 test')
    t = Thread(target=test)
    t.start()
    t.join()

    注意看加的那一行的输出呦~
    eggshell
        8
    eggshell  
    OP
       2018-03-27 00:15:47 +08:00
    @holajamc 加的那一行的输出是 ISO-8859-1,应该是 response header 里没有编码信息,然后 requests 按照标准默认用错误的 ISO-8859-1 解码了,但是还是没搞懂他这个多线程是怎么回事。。
    holajamc
        9
    holajamc  
       2018-03-27 09:39:17 +08:00
    @eggshell 看起来是 lxml 的问题了 我试过用 html.parser 和 html5lib 都没有问题诶
    TimePPT
        10
    TimePPT  
       2018-03-27 10:52:55 +08:00
    soup = BeautifulSoup(r.content, 'lxml', from_encoding=r.encoding)
    TimePPT
        11
    TimePPT  
       2018-03-27 13:42:17 +08:00
    @TimePPT 囧,试了下不行,soup 的编码还是有问题 orz
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2490 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 01:31 · PVG 09:31 · LAX 17:31 · JFK 20:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.