JSON文件解析
最近使用百度文字识别功能来抓取图片内的文字和位置,
百度把识别结果以JSON的形式返了回来,内容如下:
{‘words_result‘: [{‘words‘: ‘勤道天‘, ‘location‘: {‘top‘: 190, ‘left‘: 135, ‘width‘: 499, ‘height‘: 136}, ‘chars‘: [{‘char‘: ‘勤‘, ‘location‘: {‘top‘: 190, ‘left‘: 135, ‘width‘: 81, ‘height‘: 136}}, {‘char‘: ‘道‘, ‘location‘: {‘top‘: 190, ‘left‘: 385, ‘width‘: 125, ‘height‘: 136}}, {‘char‘: ‘天‘, ‘location‘: {‘top‘: 190, ‘left‘: 509, ‘width‘: 82, ‘height‘: 136}}]}, {‘words‘: ‘刚欲平川智海‘, ‘location‘: {‘top‘: 337, ‘left‘: 161, ‘width‘: 471, ‘height‘: 113}, ‘chars‘: [{‘char‘: ‘刚‘, ‘location‘: {‘top‘: 337, ‘left‘: 230, ‘width‘: 51, ‘height‘: 63}}, {‘char‘: ‘欲‘, ‘location‘: {‘top‘: 337, ‘left‘: 265, ‘width‘: 56, ‘height‘: 62}}, {‘char‘: ‘平‘, ‘location‘: {‘top‘: 347, ‘left‘: 335, ‘width‘: 67, ‘height‘: 76}}, {‘char‘: ‘川‘, ‘location‘: {‘top‘: 384, ‘left‘: 501, ‘width‘: 41, ‘height‘: 66}}, {‘char‘: ‘智‘, ‘location‘: {‘top‘: 381, ‘left‘: 541, ‘width‘: 39, ‘height‘: 68}}, {‘char‘: ‘海‘, ‘location‘: {‘top‘: 378, ‘left‘: 579, ‘width‘: 39, ‘height‘: 68}}]}, {‘words‘: ‘政治家‘, ‘location‘: {‘top‘: 348, ‘left‘: 186, ‘width‘: 16, ‘height‘: 70}, ‘chars‘: [{‘char‘: ‘政‘, ‘location‘: {‘top‘: 374, ‘left‘: 186, ‘width‘: 16, ‘height‘: 10}}, {‘char‘: ‘治‘, ‘location‘: {‘top‘: 388, ‘left‘: 186, ‘width‘: 16, ‘height‘: 10}}, {‘char‘: ‘家‘, ‘location‘: {‘top‘: 402, ‘left‘: 186, ‘width‘: 16, ‘height‘: 10}}]}, {‘words‘: ‘任意2套省20%‘, ‘location‘: {‘top‘: 704, ‘left‘: 287, ‘width‘: 468, ‘height‘: 76}, ‘chars‘: [{‘char‘: ‘任‘, ‘location‘: {‘top‘: 704, ‘left‘: 287, ‘width‘: 51, ‘height‘: 76}}, {‘char‘: ‘意‘, ‘location‘: {‘top‘: 704, ‘left‘: 363, ‘width‘: 51, ‘height‘: 76}}, {‘char‘: ‘2‘, ‘location‘: {‘top‘: 704, ‘left‘: 433, ‘width‘: 42, ‘height‘: 76}}, {‘char‘: ‘套‘, ‘location‘: {‘top‘: 704, ‘left‘: 466, ‘width‘: 51, ‘height‘: 76}}, {‘char‘: ‘省‘, ‘location‘: {‘top‘: 704, ‘left‘: 545, ‘width‘: 50, ‘height‘: 76}}, {‘char‘: ‘2‘, ‘location‘: {‘top‘: 704, ‘left‘: 614, ‘width‘: 42, ‘height‘: 76}}, {‘char‘: ‘0‘, ‘location‘: {‘top‘: 704, ‘left‘: 639, ‘width‘: 42, ‘height‘: 76}}, {‘char‘: ‘%‘, ‘location‘: {‘top‘: 704, ‘left‘: 690, ‘width‘: 42, ‘height‘: 76}}]}], ‘log_id‘: 1380934582706110464, ‘words_result_num‘: 4}
看着挺乱的是吧,如果不了解JSON文件结构还真是有点头晕呐。
一、什么是JSON文件
如上,内容其实就是一堆字符串。当然它是有结构的,可以用来存储数据。
二、结构分析
学过python的同学都知道“{}“号表示字典(也叫对象),”[]“号是列表(也叫数组)。
仔细看上面,JSON就是通过这两种格式的组合来存储各种复杂数据的。
1、字典
字典就是{‘键名’:键值} 的这么一种形式存数据
键名必须用引号包起来,是个字符串。(单引号双引号都行)
键值可以是任何形式(字符串、数值、列表、字典...)。
它们之间通过冒号”:“关联成一对。形如{”key“:vaule}
如果字典有多个元素,使用逗号”,“隔开。如{"key1":vaule,"key2":vaule,"key3":vaule}
2、列表
列表就是[xx,xx,xx]的形式,元素之间用逗号”,“分割
python里列表甚至可以存储不同类型的元素,如["a","b","c",1,2,3]
3、例子分析:
看最上边的例子,最外层就是一个字典{‘words_result‘: [XXX,...] , ‘log_id‘: 1380934582706110464 , ‘words_result_num‘: 4}
此字典有三个元素(即键值对),为啥是三个?别忘了元素间是用逗号”,“隔开的。嗯......数完没?
第一个元素‘words_result‘: [XXX,...],键名为‘words_result‘,值是一个列表[XXX]
第二个元素‘log_id‘: 1380934582706110464,键名为‘log_id‘,值是个数值
第三个元素‘words_result_num‘: 4,键名为‘words_result_num‘,值也是个数值
我们需要的数据(文字及位置信息)都在第一个元素的列表[]里了。
来看看这个[XXX]列表里都有啥:
[{‘words‘: ‘勤道天‘, ‘location‘: {‘top‘: 190, ‘left‘: 135, ‘width‘: 499, ‘height‘: 136}, ‘chars‘: [{‘char‘: ‘勤‘, ‘location‘: {‘top‘: 190, ‘left‘: 135, ‘width‘: 81, ‘height‘: 136}}, {‘char‘: ‘道‘, ‘location‘: {‘top‘: 190, ‘left‘: 385, ‘width‘: 125, ‘height‘: 136}}, {‘char‘: ‘天‘, ‘location‘: {‘top‘: 190, ‘left‘: 509, ‘width‘: 82, ‘height‘: 136}}]}, {‘words‘: ‘刚欲平川智海‘, ‘location‘: {‘top‘: 337, ‘left‘: 161, ‘width‘: 471, ‘height‘: 113}, ‘chars‘: [{‘char‘: ‘刚‘, ‘location‘: {‘top‘: 337, ‘left‘: 230, ‘width‘: 51, ‘height‘: 63}}, {‘char‘: ‘欲‘, ‘location‘: {‘top‘: 337, ‘left‘: 265, ‘width‘: 56, ‘height‘: 62}}, {‘char‘: ‘平‘, ‘location‘: {‘top‘: 347, ‘left‘: 335, ‘width‘: 67, ‘height‘: 76}}, {‘char‘: ‘川‘, ‘location‘: {‘top‘: 384, ‘left‘: 501, ‘width‘: 41, ‘height‘: 66}}, {‘char‘: ‘智‘, ‘location‘: {‘top‘: 381, ‘left‘: 541, ‘width‘: 39, ‘height‘: 68}}, {‘char‘: ‘海‘, ‘location‘: {‘top‘: 378, ‘left‘: 579, ‘width‘: 39, ‘height‘: 68}}]}, {‘words‘: ‘政治家‘, ‘location‘: {‘top‘: 348, ‘left‘: 186, ‘width‘: 16, ‘height‘: 70}, ‘chars‘: [{‘char‘: ‘政‘, ‘location‘: {‘top‘: 374, ‘left‘: 186, ‘width‘: 16, ‘height‘: 10}}, {‘char‘: ‘治‘, ‘location‘: {‘top‘: 388, ‘left‘: 186, ‘width‘: 16, ‘height‘: 10}}, {‘char‘: ‘家‘, ‘location‘: {‘top‘: 402, ‘left‘: 186, ‘width‘: 16, ‘height‘: 10}}]}, {‘words‘: ‘任意2套省20%‘, ‘location‘: {‘top‘: 704, ‘left‘: 287, ‘width‘: 468, ‘height‘: 76}, ‘chars‘: [{‘char‘: ‘任‘, ‘location‘: {‘top‘: 704, ‘left‘: 287, ‘width‘: 51, ‘height‘: 76}}, {‘char‘: ‘意‘, ‘location‘: {‘top‘: 704, ‘left‘: 363, ‘width‘: 51, ‘height‘: 76}}, {‘char‘: ‘2‘, ‘location‘: {‘top‘: 704, ‘left‘: 433, ‘width‘: 42, ‘height‘: 76}}, {‘char‘: ‘套‘, ‘location‘: {‘top‘: 704, ‘left‘: 466, ‘width‘: 51, ‘height‘: 76}}, {‘char‘: ‘省‘, ‘location‘: {‘top‘: 704, ‘left‘: 545, ‘width‘: 50, ‘height‘: 76}}, {‘char‘: ‘2‘, ‘location‘: {‘top‘: 704, ‘left‘: 614, ‘width‘: 42, ‘height‘: 76}}, {‘char‘: ‘0‘, ‘location‘: {‘top‘: 704, ‘left‘: 639, ‘width‘: 42, ‘height‘: 76}}, {‘char‘: ‘%‘, ‘location‘: {‘top‘: 704, ‘left‘: 690, ‘width‘: 42, ‘height‘: 76}}]}]
开头就见到花括号”{“,没错,看来列表里边存了字典。
这里有个技巧,使用notepad++打开JSON文件,鼠标点到第一个花括号”{“上,与其一对的花括号”}“就会红色高亮显示。
我们大致观察一下,不难发现以下结构:[{},{},{},...]
列表里存了N个字典元素,而且每个字典的结构相同。
取出第一字典,再看看它的结构:
{‘words‘: ‘勤道天‘, ‘location‘: {‘top‘: 190, ‘left‘: 135, ‘width‘: 499, ‘height‘: 136}, ‘chars‘: [{‘char‘: ‘勤‘, ‘location‘: {‘top‘: 190, ‘left‘: 135, ‘width‘: 81, ‘height‘: 136}}, {‘char‘: ‘道‘, ‘location‘: {‘top‘: 190, ‘left‘: 385, ‘width‘: 125, ‘height‘: 136}}, {‘char‘: ‘天‘, ‘location‘: {‘top‘: 190, ‘left‘: 509, ‘width‘: 82, ‘height‘: 136}}]}
它的结构是:{‘words‘: 字符串, ‘location‘: 字典,chars:列表}
ok,你看出来了吗?至此我想大家应该已经会分析JSON的结构了吧。
三、取出数据
非常简单,都是使用索引器来取出值。
1、取列表元素
如一个列表list=[a,b,c]
想取第一个元素a,就这样list[0]
2、取字典元素
如一个字典dic={"words":"锅大侠","age":100,"sex":"unknown"}
取出年龄100,就这样dic[‘age‘]
3、实战演练
需求:取出所有的单个文字和位置,打印到txt文件里。
注:百度的返回结果是名为response的对象,通过response.json()方法直接取得JSON内容。
① 拿到结果列表(即通过键名”words_result“从字典中取出值,值是列表类型)
resultList=response.json()[‘words_result‘]
② 遍历列表,取出每个数组元素。只要字的列表
for item in resultList:
chars=item[‘chars‘] #字列表
③ 遍历字列表,取出字和位置信息
for item2 in chars:
char=item2[‘char‘] #字
location=item2[‘location‘]
top = location[‘top‘] #上
left = location[‘left‘] #左
width = location[‘width‘] #宽
height = location[‘height‘] #高
④ 输出效果
序号 内容
1 勤
宽度:81 高度:136
左间距:135 右间距:190
2 道
宽度:125 高度:136
左间距:385 右间距:190
3 天
宽度:82 高度:136
左间距:509 右间距:190
4 刚
宽度:51 高度:63
左间距:230 右间距:337
5 欲
宽度:56 高度:62
左间距:265 右间距:337
......