最近因项目需要,整理网络电台资源数据,根据源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()