前面的废话
做12306爬虫的时候,回传的数据是json格式,但是用r.json()解析之后我不知道怎么用。然后尝试用正则去解析,刚开始还是挺顺利的,直到我需要检测火车票的时候,才发现对于一种火车票,有三种可能性:数字、‘--’或者‘无’。其他还好,‘无’这个中文就让人感觉闹心了,折腾半天没有办法,正好遇到张吉嘎,学习了一下json。
JSON:全名javascript object notation,也就是javascript用来描述对象的格式
requests这个库还是很好的,对于获取到的内容,直接用r.json()就可以获取文本文件json化的数据,然后我们可以用json解析器观察一下它的结构,之后用
<span style="font-size:18px;">rj = r.json()["data"]["datas"]
print type(rj)
for x in rj:
print " %s %s\n" % (x["station_train_code"],x["yz_num"])</span>
就可以方便地使用我们的内容啦
(json的[]就相当于C或者java的成员运算符,关于是调用哪个成员,就需要你自己用json解析器仔细研究它的结构了)
关于pickle
python内部其实带了一个pickle模块用于序列化/反序列化一个对象,但是根据牛人测试json的速度在pickle的十倍以上,所以还是推荐使用json。
用于序列化的两个模块
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
Json模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load
pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load (不仅可以序列化字典,列表...还可以把一个程序,一个类给序列化掉)
(这里也可以看出它们功能还是很相似的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
'''
Pickle序列化
python的pickle模块实现了基本的数据序列和反序列化。通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储;通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。
'''
'''
基本接口:
pickle.dump(obj, file, [,protocol])
注解:将对象obj保存到文件file中去。
protocol为序列化使用的协议版本,0:ASCII协议,所序列化的对象使用可打印的ASCII码表示;
1:老式的二进制协议;2:2.3版本引入的新二进制协议,较以前的更高效。其中协议0和1兼容老版本的python。
protocol默认值为0。
file:对象保存到的类文件对象。file必须有write()接口, file可以是一个以'w'方式打开的文件或者一个
StringIO对象或者其他任何实现write()接口的对象。如果protocol>=1,文件对象需要是二进制模式打开的。
pickle.load(file)
注解:从file中读取一个字符串,并将它重构为原来的python对象。
file:类文件对象,有read()和readline()接口。
'''
#dump
import
pickle
name_list
=
{
'L'
:[
1
,
2
,
3
,
4
],
'D'
:{
'name'
:
'biggerl'
,
'age'
:
27
},
'S'
:
'biggerl'
}
f
=
open
(r
'c:\Users\admin\Desktop\user.pkl'
,
'wb'
)
pickle.dump(name_list,f)
#### encoded_pickle = pickle.dumps(l)
f.close()
#load
import
pickle
f
=
open
(r
'c:\Users\admin\Desktop\user.pkl'
,
'rb'
)
D
=
pickle.load(f)
####decode_pickle = pickle.loads(encoded_pickle)
D
{
'L'
: [
1
,
2
,
3
,
4
],
'D'
: {
'age'
:
27
,
'name'
:
'biggerl'
},
'S'
:
'biggerl'
}
|
关于python 的 json的详细介绍
JSON建构于两种结构:
“名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。
这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能
对简单数据类型的encoding 和 decoding:
使用简单的json.dumps方法对简单数据类型进行编码,例如:
1
2
3
4
5
6
|
import
json
obj
=
[[
1
,
2
,
3
],
123
,
123.123
,
'abc'
,{
'key1'
:(
1
,
2
,
3
),
'key2'
:(
4
,
5
,
6
)}]
encodedjson
=
json.dumps(obj)
print
repr
(obj)
print
encodedjson
|
输出:
[[1, 2, 3], 123, 123.123, 'abc', {'key2': (4, 5, 6), 'key1': (1, 2, 3)}]
[[1, 2, 3], 123, 123.123, "abc", {"key2": [4, 5, 6], "key1": [1, 2, 3]}]
通过输出的结果可以看出,简单类型通过encode之后跟其原始的repr()输出结果非常相似,但是有些数据类型进行了改变,例如上例中的元组则转换为了列表。在json的编码过程中,会存在从python原始类型向json类型的转化过程,具体的转化对照如下:
json.dumps()方法返回了一个str对象encodedjson,我们接下来在对encodedjson进行decode,得到原始数据,需要使用的json.loads()函数:
1
2
3
4
|
decodejson
=
json.loads(encodedjson)
print
type
(decodejson)
print
decodejson[
4
][
'key1'
]
print
decodejson
|
输出:
<type 'list'>
[1, 2, 3]
[[1, 2, 3], 123, 123.123, u'abc', {u'key2': [4, 5, 6], u'key1': [1, 2, 3]}]
loads方法返回了原始的对象,但是仍然发生了一些数据类型的转化。比如,上例中‘abc’转化为了unicode类型。从json到python的类型转化对照如下:
(可以观察到这个过程还是有一些信息的损失的)处理自己的数据类型
json模块不仅可以处理普通的python内置类型,也可以处理我们自定义的数据类型,而往往处理自定义的对象是很常用的。
首先,我们定义一个类Person。
1
2
3
4
5
6
7
8
9
|
class
Person(
object
):
def
__init__(
self
,name,age):
self
.name
=
name
self
.age
=
age
def
__repr__(
self
):
return
'Person Object name : %s , age : %d'
%
(
self
.name,
self
.age)
if
__name__
=
=
'__main__'
:
p
=
Person(
'Peter'
,
22
)
print
p
|
如果直接通过json.dumps方法对Person的实例进行处理的话,会报错,因为json无法支持这样的自动转化。通过上面所提到的json和python的类型转化对照表,可以发现,object类型是和dict相关联的,所以我们需要把我们自定义的类型转化为dict,然后再进行处理。这里,有两种方法可以使用。一种是自己写转化函数,另一种是利用demjson模块的encode和decode函数(可以用pip install demjson安装)
关于自己写转化函数
语法?
1
|
dict .update(dict2)
|
- dict2 -- 这是被添加dict到的词典
- update()方法添加键 - 值对到字典dict2。此函数不返回任何值。
下面的例子显示了update()方法的使用
当我们运行程序:
dict1={'name':'xiaoming','age':'18'}
dict2={'name':'xiaohong','age':'20','school':'zhejiang'}
dict1.update(dict2)
print dict1 #output:{'age': '20', 'name': 'xiaohong', 'school': 'zhejiang'}
可以看到update会改变dict1,同时会更新已经存在的键,会自动添加不存在的键 encode
Python encode() 函数用于将 Python 对象编码成 JSON 字符串。
语法
demjson.encode(self, obj, nest_level=0)
实例
以下实例将数组编码为 JSON 格式数据:
#!/usr/bin/python import demjson data = [ { 'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 } ] json = demjson.encode(data) print json
以上代码执行结果为:
[{"a":1,"b":2,"c":3,"d":4,"e":5}]
decode
Python 可以使用 demjson.decode() 函数解码 JSON 数据。该函数返回 Python 字段的数据类型。
语法
demjson.decode(self, txt)
实例
以下实例展示了Python 如何解码 JSON 对象:
#!/usr/bin/python import demjson json = '{"a":1,"b":2,"c":3,"d":4,"e":5}'; text = demjson.decode(json) print text
以上代码执行结果为:
{u'a': 1, u'c': 3, u'b': 2, u'e': 5, u'd': 4}