场景
在抓取第三方网站的数据时,有时会遇到这种情况:请求的url响应的是一段js文本,你要的是其中的数据。
样例
jsstr:
var result = {column:{name:0,age:1,tel:2,addr:3}, data:[['张三',19,'13500223344','北四环12号'],['李四',34,'88220334',],['王五',22,,]]};
说明:
key是不带引号的
存在空值,有的空值在中间,有的在末尾
字符串值用了单引号
以上均不符合json的标准.
方法
采用eval()
json.loads()
采用PyExecJs
采用demjson (执行效率慢)
采用Js2Py (推荐)
PyV8(未验证)
处理过程
eval
对等号右侧的字符串进行eval().但是因为key不带引号,不是合法的json字符串.当遇到不规范的情况时,会报异常。
第一步:规范json字符串
jsonstr = jsstr.split('=')[1] #取等号后面的部分
jsonstr = jsonstr.strip().rstrip(';') #去掉末尾;号
jsonstr = jsonstr.replace(''', '"') #单引号替换为双引号
jsonstr = jsonstr.replace(', ,', ', None,') #替换中间空值
jsonstr = jsonstr.replace(', ]', ', None]') #替换末尾空值
第二步:调整eval参数
eval(jsonstr, type('Dummy', (dict,), dict(getitem=lambda s,n:n))())
json.loads
会报类似json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes:
的异常。 即属性名必须用双引号包裹。而给属性名包裹引号有点麻烦。
PyExecJS
pip install PyExecJS
方式一:
>>>d = execjs.eval(jsstr)type(d)
方式二:
>>>js = execjs.compile(jsstr)js.eval('result')
{'column': {'name': 0, 'age': 1, 'tel': 2, 'addr': 3}, 'data': [['锟斤拷锟斤拷', 19, '13500223344', '锟斤拷锟侥伙拷锟斤拷锟斤拷锟斤拷'], ['锟斤拷锟斤拷', 34, '88220334'], ['锟斤拷锟斤拷', 22, None]]}
type(js)
缺点:中文处理不太好。
demjson
demjson的简介
python处理json是需要第三方json库来支持,工作中遇到处理json数据,是没有安装第三方的json库。demjson模块提供用于编码或解码用语言中性JSON格式表示的数据的类和函数(这在ajax Web应用程序中通常被用作XML的简单替代品)。此实现尽量尽可能遵从JSON规范(RFC 4627),同时仍然提供许多可选扩展,以允许较少限制的JavaScript语法。它包括完整的Unicode支持,包括UTF-32,BOM,和代理对处理。它还可以支持JavaScript的南方和无穷数字类型以及它的“未定义”类型。它还包括一个皮棉像JSON语法验证器测试对于严格遵守标准的JSON文本。
>>>data = demjson.decode(jsonstr)data['column']
{'addr': 3, 'age': 1, 'name': 0, 'tel': 2}
type(data)
优点:良好的处理中文处理
缺点:执行效率比较慢;
不算缺点的缺点:decode的返回值为dict,只能以data['column']方式引用属性值
Js2Py
pip install Js2Py
>>>import js2pyresult = js2py.eval_js(jsstr)
result
{'column': {'addr': 3, 'age': 1, 'name': 0, 'tel': 2}, 'data': [['张三', 19, '13500223344', '北四环12号'], ['李四', 34, '88220334'], ['王五', 22, None]]}
result.column.addr
type(js)
优点1:比较完美地处理中文
优点2:返回值为js2py.base.JsObjectWrapper对象,可直接使用属性名引用,如result.column
PyV8
Python3 安装不要使用pip,因为官方只支持 Python2,需要在这里下载对应系统的二进制文件:emmetio/pyv8-binaries
然后解压后将 PyV8.py 与 _PyV8.so (注意:如不是这两个文件名需要修改) ,将两文件复制到 Python 的 site-packages 目录下,如 /usr/local/lib/python3.6/site-packages
。
(转)
缺点:目前(2019.7)只支持到Python 3.3