python pyquery 采集淘宝的编码问题

2013-09-13 13:32:29 +08:00
 54dev
代码在这里:http://pastebin.com/mdizARWA

采集到的数据是gbk的,插入数据库的时候要转成utf8的,试过decode encode各种模式,都无法解决乱码的问题,文件的编码是utf-8 无bom的。
7838 次点击
所在节点    问与答
16 条回复
54dev
2013-09-13 14:24:21 +08:00
现在的问题是:插入到数据库的全是乱码,实在是不知道怎么转换了。
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
2013-09-13 14:41:00 +08:00
decode('gbk').encode('utf-8')试下
54dev
2013-09-13 15:05:58 +08:00
先去给同事修个电脑,回来继续test
54dev
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
2013-09-13 15:19:23 +08:00
54dev
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
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
2013-09-13 16:13:22 +08:00
@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
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
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
2013-09-13 17:12:59 +08:00
你用gb18030试试
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
2013-09-13 17:28:57 +08:00
@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
2013-09-14 17:32:07 +08:00
@swulling 嗯,对这些库不太熟,所以会走些弯路 :)
54dev
2013-09-14 17:32:41 +08:00
@Ziya 对的,已经使用requests处理了,谢谢

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

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

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

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

© 2021 V2EX