这篇文章将为大家详细讲解有关JavaScript中JSON转为Python可读取的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
数据是通过 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
字符串,代码如下:
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可读取的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。