JavaScript中的JSON转为Python可读取

目录
  • 创作背景
  • 问题再现
  • 解决办法
    • 形参与实参对应关系
  • 格式化JSON
    • 给键加上双引号
    • 识别且替换值
    • 总代码
  • 不足

创作背景

最近本菜鸡在爬一个网站的时候,意外发现所需 JSON 数据在页面前端,但是不易提取,写下此篇博客以记录解决方案。

问题再现

数据是通过 JS 代码传递的,大致格式(仅 作举例说明 ,方便查看层次,实际 在同一行 )如下:

function (a, b, c, d){
    return {
        title: a,
        data: [
            {
            	data: b
        	},
            {
                data: c
            },
            {
                data: d
            }
    	]
    }
}('title', 2, 3, 4)

我要提取的是整个 JSON 格式的数据。

如果要直接提取,可以使用

re.findall('return (\{.*?\})\}\(', content)

得到结果,但如果要解析数据,会报以下的错:

意思是:键值对中的键需要被双引号包含

所以我们要完成任务的话,需要解决以下问题:

  • 键需要用 "" 包含。
  • 需要将形式参数 a, b, c, d 转化为实际参数 "title", 2, 3, 4

解决办法

形参与实参的对应关系容易解决,所以先解决这个问题。

形参与实参对应关系

可以使用以下代码得到 形式参数

''.join(re.findall('function\((.*?)\)\{', content)).split(',')

使用下述代码获得 实际参数

''.join(re.findall('}\((.*?)\)', content)).split(',')

因为 形式参数实际参数个数 一样,所以可以根据 列表索引 建立对应关系,使用 np.c_ 可以进行 列表横向合并

代码如下:

# 获得实际参数Argument = ''.join(re.findall('}\((.*?)\)', content)).split(',')# 获得形式参数Formal_parameter = ''.join(re.findall('function\((.*?)\)\{', content)).split(',')# 建立对应关系mapping = pd.DataFrame(np.c_[Formal_parameter, Argument])# 以形参作为索引mapping.set_index(0, drop=True, inplace=True)

结果如下:

格式化 JSON

要解决这个问题,我们需要先提取出 JSON 字符串,代码如下:

string = ''.join(re.findall('return (\{.*?\})\}\(', content))

结果如下:

然后,我们需要有个思路,如下:

  • {, 后边,: 之前的部分是 ,需要加上双引号。
  • :[{ 后边,], 之前的部分都是 ,需要识别且替换。

给键加上双引号

因为涉及到 插入元素Python 中只有 列表 能担此重任,所以我们需要先 将字符串转为列表 ,代码如下:

string = list(''.join(re.findall('return (\{.*?\})\}\(', content)))

然后,我们需要设置一个变量,当识别出是 的时候就 1 ,否则为 0

key_flag = 0

如果我们按照上文中的规则识别出 ,就要从当前位开始,一直到 : 之前的这部分都用 双引号 包含。

还有些特殊情况,比如

  • 嵌套字典 ,比如一个列表中值均为字典 。
  • 空字典{ 后边是 }

考虑到特殊情况,代码如下:

index = 0

while True:
    # 如果索引超出范围,就跳出循环
    if index >= len(string):
        break
    # 给键加双引号
    if key_flag:
        # 在当前位插入一个双引号
        string.insert(index, '"')
        index += 1
        # 循环读取
        while True:
            # 直到出现 ":",循环读取的部分为 键
            # 在 键 的最后添加一个双引号
            if string[index] == ':':
                string.insert(index, '"')
                # 重置 key_flag
                key_flag = 0
                # 终止循环
                break
            # 读取下一位
            index += 1
    # 当前字符为 "{" 或 ",",则后边的为 键
    if string[index] in '{,':
        key_flag = 1
        # 嵌套时,则将索引移向下一位
        if string[index+1] in '{':
            index += 1
        # 如果为空字典,则重置 key_value
        if string[index+1] in '}':
            key_flag = 0

    index += 1

结果如下(因篇幅限制,代码无法截全):

可以看到,已经将所有的键用双引号包含。

识别且替换值

这一部分还是小有难度的。

首先,和上边一样,我们还是需要一个变量,记录当前识别 的状态,1 代表识别出来了,0 代表没有。

value_flag = 0

不过也是有特殊情况:

  • 值已经是字符串 ,但 字符串中有 :
  • 值是 js 语句 ,不过其不是我们要提取的数据。

考虑到特殊情况,代码如下:

while True:

    if index >= len(string):
        break
    # 检测到 值
    if value_flag:
        # 取出当前字符
        value = string.pop(index)
        # 如果字符是数字、"[" 和 "{" 或者已经是字符串
        if value in '"1234567890[{' or is_value:
            value_flag = 0
            string.insert(index, value)
            index += is_value
        # 不符合上述情况
        else:
            # 循环取出 值 字符串
            while True:
                # 如果为 "," 或 "}",则代表已取完
                if string[index] in ',}':
                    break
                value += string.pop(index)
            # 如果 值 字符串在对应关系中,就替换
            if value in mapping.index:
                # 因为是在当前位不断插入,所以要将数据反向
                trans = mapping.loc[value][::-1]
            # 如果不在,则直接替换成空字符串
            else:
                trans = '""'
            # 计算索引要移动几位
            length = len(trans)
            # 插入对应的数据
            for c in trans:
                string.insert(index, c)
            # 索引移动
            index += length

            value_flag = 0

            continue
    # 如果识别到 ":" 且该 ":" 不在值字符串中
    if string[index] in ':' and not is_value:
        value_flag = 1
        # 如果是值是字符串,则设置 is_value
        if string[index+1] in '"':
            is_value = 1
    # 识别值字符串结束,并重置 is_value
    elif string[index] in '"' and is_value:
        is_value = 0

    index += 1

结果如下:

可以看到,转换的还是挺成功的。

总代码

content = '''
function(a,b,c,d){return {title:a,data:[{data:b},{data:c},{data:d}]}}("title",2,3,4)
'''

string = list(''.join(re.findall('return (\{.*?\})\}\(', content)))

is_value = 0
key_flag = 0
value_flag = 0

index = 0

while True:

    if index >= len(string):
        break

    if key_flag:

        string.insert(index, '"')
        index += 1

        while True:
            if string[index] == ':':
                string.insert(index, '"')
                key_flag = 0
                break
            index += 1

    elif value_flag:

        value = string.pop(index)

        if value in '"1234567890[{' or is_value:
            value_flag = 0
            string.insert(index, value)
            index += is_value
        else:

            storage = index

            while True:
                if string[index] in ',}':
                    break
                value += string.pop(index)

            if value in mapping.index:
                trans = mapping.loc[value][::-1]
            else:
                trans = '""'
            length = len(trans)

            for c in trans:
                string.insert(index, c)

            index += length

            value_flag = 0

            continue

    if string[index] in '{,':
        key_flag = 1
        if string[index+1] in '{':
            index += 1
        if string[index+1] in '}':
            key_flag = 0

    elif string[index] in ':' and not is_value:
        value_flag = 1
        if string[index+1] in '"':
            is_value = 1

    elif string[index] in '"' and is_value:
        is_value = 0

    index += 1

''.join(string)

结果如下:

这时候就可以使用 json.loads 来提取数据了。

结果如下:

不足

其实上述代码是有不足的地方的。因为这段 js 代码是特殊的,是 在一行 ,且 没有多余的空格

不过也是有解决办法的:

如果 有空格 怎么办? —> 在 提取形参使用形参转换实参 时使用 strip 去除两侧的空格即可。

代码不在一行 怎么办? —> 使用 .replace('\t', '').replace('\n', '') 去除 换行符制表符 ,然后再进行格式化工作。

其实如果只是 代码不在一行 的问题的话,js.loads 会帮我们去除 \n 之类的,直接提取重要部分。

不过如果要使用我的代码的话,目前只支持 在一行js 代码。

还有就是有些 将键值对的值设置成逻辑运算式 ,比如 a || "" 这种,也不太好提取,还得根据问题调整。

这些都只是思路,大家可以自行尝试,如果有问题也及时提出来。

到此这篇关于JavaScript中的JSON转为Python可读取的文章就介绍到这了,更多相关JavaScript JSON转为Python内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python读取json数据还原表格批量转换成html

    目录 一.实操 1.首先创建一个新的文档 2.添加文本 二.word转成html 1.使用pydocx转换 2.使用win32模块 背景: 由于需要对ocr识别系统的表格识别结果做验证,通过返回的json文件结果对比比较麻烦,故需要将json文件里面的识别结果还原为表格做验证. 文件部分内容如下: {"row":"6","col","5""start_row": 0, "start_column&

  • Python解析JSON数据的基本方法实例代码

    目录 一.JSON数据格式介绍 二.Python处理JSON数据 json.dumps json.loads 语法 总结 一.JSON数据格式介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. JSON建构于两种结构:json是Javascript中的对象和数组中的对象,本质上来讲就是有特定结构的字符串,所以可以通过这两种结构可以表示各种复杂的结构: 1 对象: 对象在js中表示为”{}”括起来的内容,数据结构为{key:value, key:v

  • Python JSON模块的使用详情

    目录 1.dumps( )将Python数据转成JSON格式 1.1设置缩进indent 1.2排序sort_keys 2.loads( )将JSON格式数据转成Python数据 1.dumps( )将Python数据转成JSON格式 转换对应表: Python JSON dict object list,tuple array str,unicode string int,float,long number True true False false None null import json

  • 详解python读写json文件

    python处理json文本文件主要是以下四个函数: 函数 作用 json.dumps 对数据进行编码,将python中的字典 转换为 字符串 json.loads 对数据进行解码,将 字符串 转换为 python中的字典 json.dump 将dict数据写入json文件中 json.load 打开json文件,并把字符串转换为python的dict数据 json.dumps / json.loads 数据转换对照: json python object dict array list str

  • python 将html转换为pdf的几种方法

    将 HTML 网页转换为 PDF 是很多人常见的一个需求,在浏览器上,我们可以通过浏览器的"打印"功能直接将网页打印输出为 PDF. 但是如果有多个网页就不好办了. 二进制软件 网络上存在很多将 HTML 转换为 PDF 的软件和工具.比较著名的有 Carelib.wkhtmltopdf. whtmltopdf wkhtmltopdf 真是一个优秀的 HTML 转换 PDF 工具.其借助 Qt 的 WebKit 渲染引擎,将 HTML 文档渲染导出为 PDF 文档或图像. 功能十分完善

  • JavaScript中的JSON转为Python可读取

    目录 创作背景 问题再现 解决办法 形参与实参对应关系 格式化JSON 给键加上双引号 识别且替换值 总代码 不足 创作背景 最近本菜鸡在爬一个网站的时候,意外发现所需 JSON 数据在页面前端,但是不易提取,写下此篇博客以记录解决方案. 问题再现 数据是通过 JS 代码传递的,大致格式(仅 作举例说明 ,方便查看层次,实际 在同一行 )如下: function (a, b, c, d){ return { title: a, data: [ { data: b }, { data: c },

  • 在JavaScript中使用JSON数据

    JSON 是 JavaScript 原生格式,这意味着 在 JavaScript 中处理 JSON 数据不需要任何特殊的 API 或工具包. JSON语法 JSON建构于两种结构: 对象--名称/值对的集合.不同的语言中,它被理解为对象,纪录,结构,字典,哈希表,有键列表(keyed list),或者关联数组.一个对象以"{"(左括号)开始,"}"(右括号)结束.每个"名称"后跟一个":"(冒号):"'名称/值' 对

  • JavaScript中的JSON 中文版翻译

    大家看可以先看下面的例子 var json_jb51 = {"showinfo": [ {"title": "我们", "url": "www.jb51.net", "author": "dxy"}, {"title": "服务器", "url": "s.jb51.net", "

  • JavaScript中对JSON对象的基本操作示例

    JSON对象 1.对象的属性: 对象的属性是有键值对组成的,其中key为一个字符串,value可以为任何的Javascript对象. //使用[]设置和获取对象的属性 var obj = new Object(); obj["www.jb51.net"] = "http://www.jb51.net"; alert(obj["www.jb51.net"]); 2.变量既是属性: Javascript引擎在初始化时会构建一个全局对象,所有的变量都是

  • 深入理解 JavaScript 中的 JSON

    我们先来看一个JS中常见的JS对象序列化成JSON字符串的问题,请问,以下JS对象通过JSON.stringify后的字符串是怎样的?先不要急着复制粘贴到控制台,先自己打开一个代码编辑器或者纸,写写看,写完再去仔细对比你的控制台输出,如果有误记得看完全文并评论,哈哈. var friend={ firstName: 'Good', 'lastName': 'Man', 'address': undefined, 'phone': ["1234567",undefined], 'full

  • JavaScript中解析JSON数据的三种方法

    概述 现在JSON格式在web开发中越来越受重视,特别是在使用ajax开发项目的过程中,经常需要将json格式的字符串返回到前端,前端解析成JS对象(JSON ). ECMA-262(E3)中没有将JSON概念写到标准中,还好在 ECMA-262(E5)中JSON的概念被正式引入了,包括全局的JSON对象和Date的toJSON方法. 解析JSON数据的三种方法 eval()方法 解析JSON数据的最常用方法是使用javascript的eval()方法,代码如下: 复制代码 代码如下: func

  • javascript中判断json的方法总结

    简单地说, JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串(伪对象) ,然后就可以在函数之间轻松地传递这个字符串,或者 在异步应用程序中将字符串从 Web 客户端传递给服务器端程序 .这个字符串看起来有点儿古怪(稍后会看到几个示例),但是 JavaScript 很容易解释它,而且 JSON 可以表示比名称/ 值对更复杂的结构.例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表. 判断json是否为空 复制代码 代码如下: var jsonStr ={}; 1.判

  • Javascript中JSON数据分组优化实践及JS操作JSON总结

    现有一堆数据,我需要按时间进行分组,以便前端视图呈现 [ {"date":"2017-12-22","start_time":"10:00:00","end_time":"10:00:00","status":"Performance Time"}, {"date":"2017-12-22","st

  • Python中使用json.load()和json.loads()加载json数据的方法实例

    目录 前言 预备知识: 使用方法 总结 前言 最近在python里面用json读取json文件,可是老是不成功,特此记录一下. 预备知识: def load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """Deserialize ``fp`` (a ``.read()``-suppor

  • javascript中JSON.parse()与eval()解析json的区别

    本文实例讲述了javascript中JSON.parse()与eval()解析json的区别.分享给大家供大家参考,具体如下: JSON(JavaScript Object Notation)是一种轻量级的数据格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是Javascript原生格式,这意味着在javascript中处理JSON数据 基本格式: varjsonData='{"data1":"Hello,","data2"

随机推荐