要过节啦,下载了一批喜马拉雅的有声读物,准备放到SD卡里到车上听。到目录一瞧,嘿,都是些啥玩意。
│
├─323366
│
51937074.m4a
│
52070404.m4a
│
├─4756811
│
18556415.m4a
│
├─6729285
│
38100357.m4a
│
└─7651313
我想要的是类似这样的目录和歌曲名
│
├─CCTV朗读者
│
朗读者特别节目丨王姬:致母亲“妈妈,下辈子请您做我的女儿。”.m4a
│
├─冷历史
│
一线业务代表怎样像白起一样做起来.m4a
│
职场上千万不要犯和白起一样的错.m4a
│
├─摸金天师(盗墓小说):紫襟故事
│
《摸金天师》第001章 百辟刀(求订阅,打赏!).m4a
│
└─晓说2017
研究一下喜马拉雅的下载目录,发现它把每的节目由两个描述性的jSON文件和存放文件的目录组成。举个例子更容易明白,对上面的323366,
323366:
1) 322266info.json,节目描述文件
323366info.json描述了节目信息,其中主要的是"Title",表示节目名,“冷历史”;
2) 323366list.json
323366list.json表示节目里包含的曲目名,是一个JSON数组,每个表示一个曲目。list文件的第一个“Title”=“职场上千万不要犯和白起一样的错”
这玩意下载的多了,没法手动去逐个改,还不得累死我这老胳膊老腿的。所以决定写个Python程序,来完成这个任务。
这是我写的第二个python程序,所以坑还真不少,有得坑跟喜马拉雅有关。简单列一些,供以后参考。
1. 编码坑
之前就掉进python的坑里,好不容易爬出来,以为都应该明白了呢。现实总是残酷的多,要解析JSON文件,总得先读进来吧,如下:
with open("323366info.json",'r') as load_f:
load_dict = json.load(load_f)
print(load_dict["title"])
总是在load这句,报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xb2 in position 93: illegal multibyte sequence
即使在load里加入了“encoding=”utf-8””。以为又是cmd窗口的问题, 用chcp修改了代码页,无济于事。
仔细研究,发现open默认按字符方式打开,这时其实有一个编码隐含在这里,我的Windows系统是中文版,默认编码是GBK,Python3应该是取了这个默认值,所以修改CMD窗口无济于事。
了解了来龙去脉,修改就简单了,只需将第一句话修改成:
with open("323366info.json",'r',encoding = "utf-8") as load_f:
了解了来龙去脉,修改就简单了,只需将第一句话修改成:
with open("323366info.json",'r',encoding = "utf-8") as load_f:
2. 正则表达式坑
喜马拉雅的Title是用户上传的,所以Title里包含什么都不奇怪。但Windows目录名是有禁忌的,下面这些字符都不可以出现在文件和目录名中:
/\:*?"<>|]
可以管这些叫咒符,自然的想法就是遇到这些咒符,就查一下替换掉。
等一下,这不就是正则表达式擅长的吗,虽然没怎么用过,我还是决定试一试这高级玩意。
“\”,“:”,“?”,“|”,这些都是正则表达式的元字符,应该需要转义,但也有文档说,如果包含在“[...]"内,应该不需要,但实际上报错,还好可以在交互窗口中逐个试,最后发现应该写成这样才可以:
illegal_Char = re.compile(r"[/\\:*?\"<>|]")
也就是只有“\”和“"”需要转义,从道理上倒也讲得通,解释器找到“"”就认为这一个语句结束了,为什么不能说的更清楚些呢。
3. 喜马拉雅的同名节目坑
同一个节目目录下,居然有曲目完全同名。虽然知道喜马拉雅号称UGC(用户生成内容),但不能这么坑吧。
没办法,解决方法是,从xxxlist.json里找到了“ID”字段,不同曲目可能完全同名,但ID一定是不同的,如果遇到重名的,则给后出现的曲目加一个xxxxx的部分,比如如下罗辑思维的例子:
├─你是巨婴吗x[罗辑思维]No·198
├─你因挣钱而伟大 [罗辑思维]No.117
├─你因挣钱而伟大 [罗辑思维]No.1176585108
4. UTF-8与GBK的坑
对单字节高于0x80的字符,Unicode是支持的。比如,一些节目的Title里包含“-”字符,注意这里的“-”不是键盘上那个,而是在扩展ASCII里,这个被编码为0xA0,UTF-8编码为0xC2 A0,奇怪的是,GBK不支持这个字符,或者说python的decode函数不支持,所以总是报encoding error。后来发现可以先主动转一遍,对无法转换的字符,指定Ignore,则可以跳过.
print(old,"==>", new.encode("gbk","ignore").decode("gbk"))
差不多了,这些坑踩了个遍,我得第二个python程序可以正常工作了,我的国庆有声读物下载的也差不多了,有1700多个,运行一遍,10秒钟全部改完了。嗯,还不错。
贴上其中的一个关键函数,完整程序有需要者可以找我要
def ren_files(dir):