V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
54dev
V2EX  ›  问与答

python pyquery 采集淘宝的编码问题

  •  
  •   54dev · 2013-09-13 13:32:29 +08:00 · 7827 次点击
    这是一个创建于 3879 天前的主题,其中的信息可能已经有所发展或是发生改变。
    代码在这里:http://pastebin.com/mdizARWA

    采集到的数据是gbk的,插入数据库的时候要转成utf8的,试过decode encode各种模式,都无法解决乱码的问题,文件的编码是utf-8 无bom的。
    16 条回复    1970-01-01 08:00:00 +08:00
    54dev
        1
    54dev  
    OP
       2013-09-13 14:24:21 +08:00
    现在的问题是:插入到数据库的全是乱码,实在是不知道怎么转换了。
    swulling
        2
    swulling  
       2013-09-13 14:37:22 +08:00
    1. MySQL建表时有没有指定UTF8?,这个很容易遗漏
    2. 不要用sys.setdefaultencoding('utf-8'),这是一种ugly的,无用,错误的设置
    3. pyquery处理前,先讲网页内容从gbk转换为unicode,注意是unicode
    用 decode("gbk")
    4. 插入MySQL的时候,直接插Unicode就行了,会自动转换成UTF-8的。没必须手工转换
    pigletfly
        3
    pigletfly  
       2013-09-13 14:41:00 +08:00
    decode('gbk').encode('utf-8')试下
    54dev
        4
    54dev  
    OP
       2013-09-13 15:05:58 +08:00
    先去给同事修个电脑,回来继续test
    54dev
        5
    54dev  
    OP
       2013-09-13 15:17:56 +08:00
    @swulling 谢谢你的解答,好多pyquery的编码都有你的身影,也根据你在别的贴子里的回复做过调试
    1,mysql表的整理选项是utf8_general_ci
    2,这个我再试一下不要setdefaultencoding('utf-8')的情况下decode('gbk'),我终端是utf8编码 的
    3,是,我也注意到这个问题,但我我拿到采集后,连unicode都打印不出来
    54dev
        6
    54dev  
    OP
       2013-09-13 15:19:23 +08:00
    54dev
        7
    54dev  
    OP
       2013-09-13 15:20:24 +08:00
    @swulling
    print price.decode('gbk')
    会报错
    print price.decode('gbk')
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
    54dev
        8
    54dev  
    OP
       2013-09-13 15:20:42 +08:00
    @pigletfly

    print price.decode('gbk')
    会报错
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
    swulling
        9
    swulling  
       2013-09-13 16:13:22 +08:00   ❤️ 1
    @54dev 是这样的,你这是用了PyQuery直接来获取Url,这样面对非utf-8的页面就会解析错误

    比如将你的price显示出来是这样:
    In [9]: price
    Out[9]: u'\xa3\xa4196.20 \xa3\xa4185.01 \xa3

    完全乱了,虽然也可以用一些方法处理为正常,不过就ugly了


    所以我建议你用一个库去抓网页,比如requests甚至简单点用urlib,然后 decode('gbk') 转换为Unicode交给PyQuery,而不是直接用pq去抓

    话说我刚刚尝试了下requests去抓,不知道是不是新版本的特性,可以自动识别页面编码了。抓回来就是unicode,直接扔给pq就是

    ret=requests.get(url="http://s.taobao.com/search?q=%BB%A7%CD%E2%B0%FC",headers={'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36'})

    p=pq(ret.text)


    In [19]: print p(".row-focus .price").text()
    ¥196.20 ¥185.01 ¥268.00 ¥166.00 ¥26.90 ¥185.00 ¥49.00 ¥168.00 ¥58.00 ¥110.00 ¥55.00 ¥87.50 ¥135.00 ¥22.00 ¥45.00 ¥58.00 ¥118.00 ¥20.00 ¥157.50 ¥68.00 ¥188.00 ¥55.00 ¥109.45 ¥88.00 ¥88.00 ¥368.00 ¥99.00 ¥66.00 ¥18.00 ¥55.00 ¥106.20 ¥55.00 ¥256.80 ¥330.00 ¥45.00 ¥562.00 ¥52.20 ¥98.00 ¥218.00 ¥38.90 ¥208.00 ¥138.00 ¥129.00 ¥108.00
    swulling
        10
    swulling  
       2013-09-13 16:15:02 +08:00
    In [18]: p(".row-focus .price").text()
    Out[18]: u'\uffe5196.20 \uffe5185.01 \uffe5268.00 \uffe5166.00 \uffe526.90 \uffe5185.00 \uffe549.00 \uffe5168.00 \uffe558.00 \uffe5110.00 \uffe555.00 \uffe587.50 \uffe5135.00 \uffe522.00 \uffe545.00 \uffe558.00 \uffe5118.00 \uffe520.00 \uffe5157.50 \uffe568.00 \uffe5188.00 \uffe555.00 \uffe5109.45 \uffe588.00 \uffe588.00 \uffe5368.00 \uffe599.00 \uffe566.00 \uffe518.00 \uffe555.00 \uffe5106.20 \uffe555.00 \uffe5256.80 \uffe5330.00 \uffe545.00 \uffe5562.00 \uffe552.20 \uffe598.00 \uffe5218.00 \uffe538.90 \uffe5208.00 \uffe5138.00 \uffe5129.00 \uffe5108.00'


    看来没有,unicode的字符串开头有小u,然后内容也是很容易看出来的\u开头的字符,python里面直接print unicode的字符串会自动转换为终端编码,比较方便
    54dev
        11
    54dev  
    OP
       2013-09-13 16:47:03 +08:00
    @swulling 谢谢,最终还是用你的request方法解决了,在回贴之前我看到有人说淘宝的编码可能是gb18030的,我试着用BeautifulSoup先把内容抓下来再去用pq处理,
    像这样的方法
    page = urllib2.urlopen('http://s.taobao.com/search?q=%BB%A7%CD%E2%B0%FC');
    soup = BeautifulSoup(page,fromEncoding="gb18030")
    d = pq(soup. prettify())
    但还是会出现乱码。。。我觉得还是因为没有正常识别所采集网页编码 的问题

    从写这个脚本开始,我只知道pquery和beautifulsoup是采集的库,其他的还不太了解,而且刚接触这个语言就遇到编码 的问题,的确很头痛,不过谢谢你啦。
    holmesabc
        12
    holmesabc  
       2013-09-13 17:12:59 +08:00
    你用gb18030试试
    swulling
        13
    swulling  
       2013-09-13 17:19:02 +08:00
    @54dev 我用urllib试了下,没问题啊,为啥要加beautifulsoup?

    import urllib
    page = urllib.urlopen('http://s.taobao.com/search?q=%BB%A7%CD%E2%B0%FC').read()
    d=pq(page.decode('gbk'))
    In [11]: print d(".row-focus .price").text()
    ¥196.20 ¥185.01 ¥268.00 ¥166.00 ¥26.90
    Ziya
        14
    Ziya  
       2013-09-13 17:28:57 +08:00   ❤️ 1
    @54dev

    requests 现在会根据header判断字符集,一般情况下直接获取的结果,就是转换后的unicode了
    就算没能自动识别也可以用指定编码的形式,所以用requests,基本可以保证「采集回来的就是Unicode」
    之后进行下一步处理就可以了,不用再考虑抓回来的是 GBK 怎么办,是GB18030怎么办……

    In [1]: import requests

    In [2]: url = 'http://s.taobao.com/search?q=%BB%A7%CD%E2%B0%FC'

    In [3]: r = requests.get(url)

    In [4]: type(r.text)
    Out[4]: unicode

    In [5]: print r.text[900:1000]
    ;
    window.givenByFE = {
    currentPage: "mainsrp",
    //有些模块出现在首屏但是却是在特殊情况才
    54dev
        15
    54dev  
    OP
       2013-09-14 17:32:07 +08:00
    @swulling 嗯,对这些库不太熟,所以会走些弯路 :)
    54dev
        16
    54dev  
    OP
       2013-09-14 17:32:41 +08:00
    @Ziya 对的,已经使用requests处理了,谢谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1478 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:58 · PVG 00:58 · LAX 09:58 · JFK 12:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.