Python & Json 的故事

最近因项目需要,整理网络电台资源数据,根据源Json数据抽取有效的电台数据生成excel表格导入服务端,同步生成特定的格式的Json数据文件以便设备端预置本地使用。

一、前言

因项目需要大量的网络电台资源数据,通常的方法其一是通过第三方平台购买,另一个种方式自已收集(爬数据)。客户提供两个方案商的设备,通过抓取网络数据包,发现列表都是预置本地,只能一个电台一个电台点击播放才能抓到网络电台数据(地址通常也采用重定向)。通过两天的数据包分析,也发现一些规律,但总体进度太慢了,通过设备端很难提高效率,必须想办法解决,看有没类似的App(相对擅长移动开发、逆向)可以快速抽取数据。

二、Json 转 Excel

通过解析某App,拿到一堆Json文件,根据服务端的要求(地区、国家代码、国家名称),抽取有用的数据生成 Excel 表格。整个数据的处理是很快,但99.99%的时间花在网络地址有效性判断上。

import glob

filelocation = "E:\\work\\cchip\\00自研项目\\网络收音机\\assets\\"
# 当前文件夹下搜索的文件名后缀
fileform = "json"

# 将合并后的表格存放到的位置
filedestination = "E:\\work\\cchip\\00自研项目\\网络收音机\\"
# 合并后的表格命名为file
file = "网络电台汇总数据"

import os
import xlsxwriter
from datetime import datetime

if os.path.exists(filedestination + file + datetime.now().strftime('%Y%m%d') + ".xlsx"):
    os.remove(filedestination + file + datetime.now().strftime('%Y%m%d') + ".xlsx")

filename = xlsxwriter.Workbook(filedestination + file + datetime.now().strftime('%Y%m%d') + ".xlsx")

sheet = filename.add_worksheet(datetime.now().strftime('%Y%m%d'))

filearray = []
for filestitle in glob.glob(filelocation + "*." + fileform):
    filearray.append(filestitle)
# 以上是从pythonscripts文件夹下读取所有json文件,并将所有的名字存储到列表filearray
print("在默认文件夹下有%d个文档哦" % len(filearray))
ge = len(filearray)

# 设置表头
sheet.write(0, 0, "NAME")
sheet.write(0, 1, "URL")
sheet.write(0, 2, "LOGO")
sheet.write(0, 3, "TAGS")
sheet.write(0, 4, "COUNTRY")
sheet.write(0, 5, "COUNTRY-ALL")
sheet.write(0, 6, "LOCATION")
sheet.write(0, 7, "LANGUAGE")
sheet.write(0, 8, "STATE")
sheet.write(0, 9, "VALID")

# 变量用来循环时控制写入单元格,感觉有更好的表达方式
lineindex = 0

import json
import pycountry as pc
import urllib.request

# 写数据
for i in range(ge):
    fname = filearray[i]
    print("正在读取:%s" % fname)

    with open(fname, encoding='utf8') as f:
        data = json.load(f)

        for list_item in data:
            lineindex += 1
            for key, value in list_item.items():
                if key == "name":
                    sheet.write(lineindex, 0, value)
                elif key == "url":
                    sheet.write(lineindex, 1, value)

                    print("URL:%s" % value)
                    try:
                        status = urllib.request.urlopen(value, timeout=20).code
                        print("URL is valid:%s" % status)
                        sheet.write(lineindex, 9, "YES")
                    except Exception as err:
                        print("URL is invalid:%s" % err)
                        sheet.write(lineindex, 9, "NO")
                elif key == "favicon":
                    sheet.write(lineindex, 2, value)
                elif key == "tags":
                    sheet.write(lineindex, 3, value)
                elif key == "countrycode":
                    sheet.write(lineindex, 4, value)
                    country1 = pc.countries.get(alpha_2=value)
                    sheet.write(lineindex, 5, country1.name)
                elif key == "language":
                    sheet.write(lineindex, 7, value)
                elif key == "state":
                    sheet.write(lineindex, 8, value)
                else:
                    pass

# 保存
filename.close()

三、 Excel 转 Json

因某些原因(成本、安全等),有些需要将网络电台数据预置在本地,所以就需要将 Excel 数据导成 按地区分目录生成国家电台文件。

from typing import List, Any

import xlrd
import json

#filelocation = "C:\\Users\\Think\\Desktop\\Json\\Location\\"
filelocation = 'C:/Users/Think/Desktop/Json/Location/'
# 合并后的表格命名为file
file = "网络电台汇总数据20220629"

data = xlrd.open_workbook('C:/Users/Think/Desktop/Json/网络电台汇总数据20220629.xlsx')
# 读取第一个工作表
table = data.sheets()[0]
# 统计行数
rows = table.nrows

lists = [[] for i in range(100)]   # 存放数据

keylist1 = table.col_values(4)[1:rows]
for i in range(0, len(keylist1)):
    if not isinstance(keylist1[i], str):
        keylist1[i] = str(keylist1[i])
keylist1.sort()

print(keylist1)

relist: List[Any] = list(set(keylist1))
relist.sort()
print(relist)

keycount = len(relist)
print(keycount)

locationlists = [[] for i in range(keycount)]   # 存放数据

for i in range(1, rows):
    values = table.row_values(i)

    for j in range(0, keycount):
        if values[4] == relist[j] and values[9] == "YES":
            locationlists[j] = values[6]
            lists[j].append(
                (
                    {
                        "name": values[0],
                        "url": values[1],
                        "favicon": values[2],
                        "tags": values[3],
                        "countrycode": values[4],
                        "country": values[5],
                        "location": values[6],
                        "language": values[7],
                    }
                )
            )

for j in range(0, keycount):
    print(locationlists[j])
    print(relist[j].lower())
    print(lists[j])

    if lists[j] == []:
       continue

    # 字典中的数据都是单引号,但是标准的json需要双引号
    js = json.dumps(lists[j], sort_keys=True, ensure_ascii=False, indent=4, separators=(',', ':'))
    #print(js)
    # 前面的数据只是数组,加上外面的json格式大括号
    #js = "{"+js+"}"
    # 可读可写,如果不存在则创建,如果有内容则覆盖
    jsFile = open(filelocation + locationlists[j] + "/station_" + relist[j].lower() + ".json", "w+", encoding='utf-8')
    jsFile.write(js)
    jsFile.close()