python爬虫的一个问题,python2 json.loadss()不式转化字符串为dict类型吗?

没有更多推荐了,
不良信息举报
举报内容:
python json loads遇到中文的情况分析。
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!博客分类:
Python处理JSON
(如果阅读效果不佳,可戳)
序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON、XML等。反序列化就是从存储区域(JSON,XML)读取反序列化对象的状态,重新创建该对象。
JSON(JavaScript Object Notation):一种轻量级数据交换格式,相对于XML而言更简单,也易于阅读和编写,机器也方便解析和生成,Json是JavaScript中的一个子集。
Python2.6开始加入了JSON模块,无需另外下载,Python的Json模块序列化与反序列化的过程分别是 encoding和 decoding
encoding:把一个Python对象编码转换成Json字符串decoding:把Json格式字符串解码转换成Python对象对于简单数据类型(string、unicode、int、float、list、tuple、dict),可以直接处理。
json.dumps方法对简单数据类型encoding:
import json
data = [{'a':"A",'b':(2,4),'c':3.0}]
print "DATA:",repr(data)
data_string = json.dumps(data)
print "JSON:",data_string
DATA: [{'a':'A','c':3.0,'b':(2,4)}] #python的dict类型的数据是没有顺序存储的
JSON: [{"a":"A","c":3.0,"b":[2,4]}]
JSON的输出结果与DATA很相似,除了一些微妙的变化,如python的元组类型变成了Json的数组,Python到Json的编码转换规则是:
json.loads方法处理简单数据类型的decoding(解码)转换
import json
data = [{'a':"A",'b':(2,4),'c':3.0}]
data_string = json.dumps(data)
print "ENCODED:",data_string
decoded = json.loads(data_string)
print "DECODED:",decoded
print "ORIGINAL:",type(data[0]['b'])
print "DECODED:",type(decoded[0]['b'])
ENCODED: [{"a": "A", "c": 3.0, "b": [2, 4]}]
DECODED: [{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]
ORIGINAL: &type 'tuple'&
DECODED: &type 'list'&
解码过程中,json的数组最终转换成了python的list,而不是最初的tuple类型,Json到Python的解码规则是:
json的人文关怀
编码后的json格式字符串紧凑的输出,而且也没有顺序,因此dumps方法提供了一些可选的参数,让输出的格式提高可读性,如sort_keys是告诉编码器按照字典排序(a到z)输出。
import json
data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
print 'DATA:', repr(data)
unsorted = json.dumps(data)
print 'JSON:', json.dumps(data)
print 'SORT:', json.dumps(data, sort_keys=True)
DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]
SORT: [{"a": "A", "b": [2, 4], "c": 3.0}
indent参数根据数据格式缩进显示,读起来更加清晰:
import json
data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
print 'DATA:', repr(data)
print 'NORMAL:', json.dumps(data, sort_keys=True)
print 'INDENT:', json.dumps(data, sort_keys=True, indent=2)
DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
NORMAL: [{"a": "A", "b": [2, 4], "c": 3.0}]
separators参数的作用是去掉,,:后面的空格,从上面的输出结果都能看到", :"后面都有个空格,这都是为了美化输出结果的作用,但是在我们传输数据的过程中,越精简越好,冗余的东西全部去掉,因此就可以加上separators参数:
import json
data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
print 'DATA:', repr(data)
print 'repr(data)
:', len(repr(data))
print 'dumps(data)
:', len(json.dumps(data))
print 'dumps(data, indent=2)
:', len(json.dumps(data, indent=2))
print 'dumps(data, separators):', len(json.dumps(data, separators=(',',':')))
DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
repr(data)
dumps(data)
dumps(data, indent=2)
dumps(data, separators): 29
skipkeys参数,在encoding过程中,dict对象的key只可以是string对象,如果是其他类型,那么在编码过程中就会抛出ValueError的异常。skipkeys可以跳过那些非string对象当作key的处理.
import json
data= [ { 'a':'A', 'b':(2, 4), 'c':3.0, ('d',):'D tuple' } ]
print json.dumps(data)
except (TypeError, ValueError) as err:
print 'ERROR:', err
print json.dumps(data, skipkeys=True)
ERROR: keys must be a string
[{"a": "A", "c": 3.0, "b": [2, 4]}]
让json支持自定义数据类型
以上例子都是基于python的built-in类型的,对于自定义类型的数据结构,json模块默认是没法处理的,会抛出异常:TypeError xx is not JSON serializable,此时你需要自定义一个转换函数:
import json
class MyObj(object):
def __init__(self, s):
self.s = s
def __repr__(self):
return '&MyObj(%s)&' % self.s
obj = .MyObj('helloworld')
print json.dumps(obj)
except TypeError, err:
print 'ERROR:', err
def convert_to_builtin_type(obj):
print 'default(', repr(obj), ')'
# 把MyObj对象转换成dict类型的对象
d = { '__class__':obj.__class__.__name__,
'__module__':obj.__module__,
d.update(obj.__dict__)
print json.dumps(obj, default=convert_to_builtin_type)
ERROR: &MyObj(helloworld)& is not JSON serializable
default( &MyObj(helloworld)& )
{"s": "hellworld", "__module__": "MyObj", "__class__": "__main__"}
#注意:这里的class和module根据你代码的所在文件位置不同而不同
相反,如果要把json decode 成python对象,同样也需要自定转换函数,传递给json.loads方法的object_hook参数:
#jsontest.py
import json
class MyObj(object):
def __init__(self,s):
self.s = s
def __repr__(self):
return "&MyObj(%s)&" % self.s
def dict_to_object(d):
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
print "MODULE:",module
class_ = getattr(module,class_name)
print "CLASS",class_
args = dict((key.encode('ascii'),value) for key,value in d.items())
print 'INSTANCE ARGS:',args
inst = class_(**args)
return inst
encoded_object = '[{"s":"helloworld","__module__":"jsontest","__class__":"MyObj"}]'
myobj_instance = json.loads(encoded_object,object_hook=dict_to_object)
print myobj_instance
MODULE: &module 'jsontest' from 'E:\Users\liuzhijun\workspace\python\jsontest.py'&
CLASS &class 'jsontest.MyObj'&
INSTANCE ARGS: {'s': u'helloworld'}
[&MyObj(helloworld)&]
MODULE: &module 'jsontest' from 'E:\Users\liuzhijun\workspace\python\jsontest.py'&
CLASS &class 'jsontest.MyObj'&
INSTANCE ARGS: {'s': u'helloworld'}
[&MyObj(helloworld)&]
使用Encoder与Decoder类实现json编码的转换
JSONEncoder有一个迭代接口iterencode(data),返回一系列编码的数据,他的好处是可以方便的把逐个数据写到文件或网络流中,而不需要一次性就把数据读入内存.
import json
encoder = json.JSONEncoder()
data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
for part in encoder.iterencode(data):
print 'PART:', part
encode方法等价于''.join(encoder.iterencode(),而且预先会做些错误检查(比如非字符串作为dict的key),对于自定义的对象,我们只需从些JSONEncoder的default()方法,其实现方式与上面提及的函数convet_to_builtin_type()是类似的。
import json
import json_myobj
class MyObj(object):
def __init__(self,s):
self.s = s
def __repr__(self):
return "&MyObj(%s)&" % self.s
class MyEncoder(json.JSONEncoder):
def default(self, obj):
print 'default(', repr(obj), ')'
# Convert objects to a dictionary of their representation
d = { '__class__':obj.__class__.__name__,
'__module__':obj.__module__,
d.update(obj.__dict__)
obj = json_myobj.MyObj('helloworld')
print MyEncoder().encode(obj)
&MyObj(internal data)&
default( &MyObj(internal data)& )
{"s": "helloworld", "__module__": "Myobj", "__class__": "MyObj"}
从json对Python对象的转换:
class MyDecoder(json.JSONDecoder):
def __init__(self):
json.JSONDecoder.__init__(self, object_hook=self.dict_to_object)
def dict_to_object(self, d):
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
print 'MODULE:', module
class_ = getattr(module, class_name)
print 'CLASS:', class_
args = dict( (key.encode('ascii'), value) for key, value in d.items())
print 'INSTANCE ARGS:', args
inst = class_(**args)
return inst
encoded_object = '[{"s": "helloworld", "__module__": "jsontest", "__class__": "MyObj"}]'
myobj_instance = MyDecoder().decode(encoded_object)
print myobj_instance
MODULE: &module 'jsontest' from 'E:\Users\liuzhijun\workspace\python\jsontest.py'&
CLASS: &class 'jsontest.MyObj'&
INSTANCE ARGS: {'s': u'helloworld'}
[&MyObj(helloworld)&]
json格式字符串写入到文件流中
上面的例子都是在内存中操作的,如果对于大数据,把他编码到一个类文件(file-like)中更合适,load()和dump()方法就可以实现这样的功能。
import json
import tempfile
data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
f = tempfile.NamedTemporaryFile(mode='w+')
json.dump(data, f)
print open(f.name, 'r').read()
[{"a": "A", "c": 3.0, "b": [2, 4]}]
import json
import tempfile
f = tempfile.NamedTemporaryFile(mode='w+')
f.write('[{"a": "A", "c": 3.0, "b": [2, 4]}]')
print json.load(f)
[{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]
浏览 272788
lantian_123
浏览: 1070433 次
来自: 广州
学会了recording,感谢~~
看完了才发现这篇文章果然是你写的
看完了,才发现时部长写的,真爱啊
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'没有更多推荐了,
不良信息举报
举报内容:
【python】str与json类型转换
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
python爬虫问题总结
摘要:从接触爬虫到现在也整整一年了,谈不上什么精通,只是摸爬滚打、吃一堑长一智,就算在泥潭里,多少也了解点怎样滚,才能少沾点泥巴。这一年里维护改进着日规模高峰达80w、均度50w的垂直爬虫系统,写过一些一次性抓取的小脚本,参与过破解接口、本地执行js进而获取抓取数据,调研过伪登录、利用cookie进行抓取,写过简单的价格图片识别脚本,维护着基于模板截图的c++ocr图片识别服务,开发了用上redis的基于特征统计判重服务,进行过局部的死链检测优化……其实回过头来看,一年的时间我还是
从接触爬虫到现在也整整一年了,谈不上什么精通,只是摸爬滚打、吃一堑长一智,就算在泥潭里,多少也了解点怎样滚,才能少沾点泥巴。这一年里维护改进着日规模高峰达80w、均度50w的垂直爬虫系统,写过一些一次性抓取的小脚本,参与过破解接口、本地执行js进而获取抓取数据,调研过伪登录、利用cookie进行抓取,写过简单的价格图片识别脚本,维护着基于模板截图的c++ocr图片识别服务,开发了用上redis的基于特征统计判重服务,进行过局部的死链检测优化……其实回过头来看,一年的时间我还是浪费了很多。这些东西或多或少跟抓取、搜索都有一些关系。临近年关,没那么忙的话,就理一理吧。
1、最基本的代码 import urllib2 content = urllib2.urlopen('http://XXXX').read()
2、最基本的结构和流程 调度、下载、抽取、入库
3、可能遇到的问题 两个原则:1)下回来了没?没有的话想尽千方百计搞到本地2)下回来了,就要相信一定能提取出来,只是麻烦与否的问题
1)被封禁 A、adsl代理 import urllib2 proxy_support =urllib2.ProxyHandler({'http':'http://XX.XX.XX.XX:XXXX'}) opener = urllib2.build_opener(proxy_support,urllib2.HTTPHandler) urllib2.install_opener(opener) content = urllib2.urlopen('http://XXXX').read() 其实以上几行代码是我从网上别处搞过来的,我一般小脚本那种一次性的抓取,用不上代理,而维护的垂直爬虫系统,下载那块主要借助的是pyqt4库,代理代码有一定耦合,就不在这里细说了,主要不是我自己写的,担心说不明白,那就不大好了,感兴趣的童鞋可以自己去研究pyqt4库,都是有很好支持的
B、控制对同一站点的访问频率(要是让它sleep、要么让它抓别的站点)
4、爬虫的自我伪装 对于需要登录的一般有以下几种处理方法: 1)直接模拟登录后的动作,利用cookie、携带用户信息等方式发起请求,绕过登录动作 2)机器人自动登录 3)直接使用webkit和js去操作登录
这里主要说一下前两种,不是因为对它们多熟,而是第三种我暂时压根没用过,⊙﹏⊙b汗 工具:firefox+httpfox 机器人自动登录: 这个东东其实原理很简单,就是程序post_data真实用户信息发起请求,至于最后能否成功登录获取登录后的信息,个人经验觉得跟对方校验严格程度有关,有些网站post_data有一些乱七八糟的数据值,你无法分析清楚,尽管携带真实用户信息请求,也总是返回用户名和密码不一致。而有的简单就容易攻破。
我实际工作中用的是直接模拟登录后访问的方法。大体代码如下: import urllib,urllib2,cookielib mycookie =urllib2.HTTPCookieProcessor(cookielib.CookieJar()) openner = urllib2.build_opener(mycookie) request = urllib2.Request('http:/*&) request.add_header(&Accept-Language&,&zh-cn,q=0.8,en-q=0.5,q=0.3&) request.add_header(&Connection&, &keep-alive&) request.add_header(&Accept-Encoding&, &gzip, deflate&) request.add_header(&X-Requested-With&, &XMLHttpRequest&) request.add_header(&Referer&, &http://****&) cookie_str = &***& request.add_header(&Cookie&, cookie_str) html_src = openner.open(request).read()
到这里基本已经完事,但你偶尔还会遇到一个问题:乱码 解决方法: import gzip from gzip import * import os, io import StringIO
html_data = GzipFile(fileobj=StringIO(html_src),mode=&r&).read()
5、多线程加速 其实这一块本身跟爬虫没多大关系了,对我这种菜鸟来讲,需要注意一点就是仔细理解线程,别把线程和函数调用混淆。建议使用线程池,至于具体代码,这个东东网上多去了,就不啰嗦了。
6、一些琐碎的东东 pyqt4本地模拟浏览器执行js from PyQt4.QtWebKit import QWebPage, QWebElement from PyQt4.QtCore import QCoreApplication, QThread, QUrl,SIGNAL, QTimer app = QApplication(sys.argv) downloader = QWebPage() with open('***.js') as f: &
js = f.read() js = js.replace('{{address}}', encoded_lat_lng) js_res_str =unicode(downloader.mainFrame().evaluateJavaScript(js).toString()
抽取失败怎么查? 1)检查下载回本地内容 是否下载完全?下载是否正确(即是否是自己想要的内容)?是否包含所要抽的内容? 有时由于网络原因,它会下载不全;有时由于封禁等会导致下载非所要内容,甚至会被通知“机器人检查”;有时由于js加载等浏览器本地处理,导致你在页面能看到,并不代表你就已经下载回所看到的内容了。其实web是这样的,网页文本是一部分,会随着当次请求返回,而其余的类似css/js/图片等等,第一次获取到的只是url等信息,也就是说我们从浏览器看到的一次请求实际上是包含了n次请求的,或前或后最后统一由浏览器加载呈现。
2)检查xpath是否正确 当然也可以是其他的定位方法,这里拿xpath举例。xpath是否准确定位到所需信息?
3)检查提取方法是否正确 可以用正则,也可以用python自带的字符串处理函数,这个看你喜欢,但貌似正则看起来更美观些。期间我遇到情况有:信息藏在利用工具获取的xpath节点的父节点、信息做了简单防抓取截断甚至js等处理……这些情况可以仔细分析网页源码加以针对解决,再唠叨一句,记住——只要到了本地,那就是你的天下,有就一定能抽出来。
4)图片抽取失败呢? 首先看是否进行了全局抽取,有的为了防止抓到广告图片,限定了抽取范围,而一旦对方变了模板,此时的图片抽取会失效。其次就是程序逻辑了,是否进行了次数限制,比如前边弄了5张,就不去扫描下面的内容了。
除了封禁,对方还会采取哪些常见的信息保护措施? 1)信息图片化 这样即使你抓到该图片,要想获取信息,也得费一番劲了。常见的比如价格图片、电话图片、验证码等等。而作为抓取方,这就得依赖后端服务了,比如图片识别ocr,这个就不在这里说了。 2)有意信息截断分开存储 拿电话图片举例,我遇到过前三位存一个地方,后八位显示星号,用户通过点击button获取完整的电话号码,其实这纯粹是个防傻瓜机器人的trick,你要想复杂的做可以模拟js点击,再获取。但更简单的方法是分析其网页源码,找到分散的部分,直接正则分别提取,再拼接即可。 3)对非登录用户不展示 这个的话,其实我现在没有什么太好的办法。临时抓取可以利用上面的破解登录的方法,但长期来看的话,别人想kill掉你是很容易的,因为你短时间内同一账号大规模的访问这个是极其容易被发现的,除非对方弱智或者压根不想管你。不然就是你有成千上万个马甲,你要搞到这种程度,我也只能拜服了。应个景,12306要想封插件个人觉得技术肯定不是问题,很简单啊,你一个账号10、20分钟五秒钟刷一次,避免误判,我忍了,可你连续几小时这样,我立马就给你封了。O(∩_∩)O哈哈~,其实他是不想真那么干罢了。
…… 本篇的话感觉主要关注一些比较细节方面的东西即可,至于爬虫系统的方面东东再起一篇吧 系统架构(从种子到模板到入库到死链检查整个一套机制如何运转) 调度、如何让其平稳长时间运行(包括出去了回不来、出不去、新比例)站点如何做到平衡 downloader主要是多进程、异步转同步、pyqt webkit渲染 抽取的模板机制,如何保证关系不混乱、列表页、详情页、抽取field 入库就没什么太多可讲的了 引擎是怎么统领全局的 ……
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
为您提供0门槛上云实践机会
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
python爬虫问题总结相关信息,包括
的信息,所有python爬虫问题总结相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International

我要回帖

更多关于 python的json.loads 的文章

 

随机推荐