[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[问题求助] 求同时精通Python和powershell的大神,把Py代码转成Ps

本帖最后由 5i365 于 2022-1-17 13:18 编辑

酷狗的歌词是专用的KRC格式的, 想把它转成LRC格式的, 在Github上找到了python版的工具,
很不错, 正在使用, 但是要装python, 即使打包成exe也不小, 看了下py代码, 只有七八十行, 实际处理字符串的代码也不多,
求同时精通Python和powershell的大神,把Py代码转成Ps, 非常感谢
下面有歌词解析代码的 python, java, c 语言版, 供参考


github地址:
https://github.com/veficos/krc2lrc

Python代码
  1. # coding=utf-8
  2. # author=veficos
  3. import codecs
  4. import zlib
  5. import re
  6. import os
  7. from tkinter import *
  8. from tkinter import ttk
  9. from tkinter.filedialog import askopenfilename, askdirectory
  10. def decompress_krc(krcbytes):
  11.     key = bytearray([ 0x0040, 0x0047, 0x0061, 0x0077, 0x005e, 0x0032, 0x0074, 0x0047, 0x0051, 0x0036, 0x0031, 0x002d, 0x00ce, 0x00d2, 0x006e, 0x0069])
  12.     decompress_bytes = []
  13.     i = 0
  14.     for ch in krcbytes[4:]:
  15.         decompress_bytes.append(ch ^ key[i % 16])
  16.         i = i + 1
  17.     decode_bytes = zlib.decompress(bytearray(decompress_bytes)).decode('utf-8-sig')
  18.     decode_bytes = re.sub(r'<[^>]*>', '', decode_bytes)
  19.     for match in re.finditer(r'\[(\d*),\d*\]', decode_bytes):
  20.         ms = int(match.group(1))
  21.         time = '[%.2d:%.2d.%.2d]' % ((ms % (1000 * 60 * 60)) / (1000 * 60), (ms % (1000 * 60)) / 1000, (ms % (1000 * 60)) % 100)
  22.         decode_bytes = decode_bytes.replace(match.group(0), time)
  23.     return decode_bytes
  24. def krc2lrc(file, saveto):
  25.     with codecs.open(file, 'rb') as f:
  26.         decode_bytes = decompress_krc(bytearray(f.read()))
  27.         fp = codecs.open(saveto, "w", 'utf-8')
  28.         fp.write(decode_bytes)
  29.         fp.close()
  30. root = Tk()
  31. savedir = ''
  32. def select_files_command():
  33.     names = askopenfilename(filetypes =(("Kugou Krc File", "*.krc"), ("All Files", "*.*")),
  34.                             title = "Choose a krc file.", multiple=True)
  35.    
  36.     try:
  37.         for file in names:
  38.             saveto = os.path.join(savedir, os.path.basename(file).replace('.krc', '.lrc') if savedir else file.replace('.krc', '.lrc'))
  39.             krc2lrc(file, saveto)
  40.             label = ttk.Label(root, text ="%s转换成功" % os.path.basename(file))
  41.             label.pack(side=BOTTOM)
  42.     except Exception as e:
  43.         label = ttk.Label(root, text ="转换失败: %s" % str(e))
  44.         label.pack(side=BOTTOM)
  45. def select_savedir_command():
  46.     global savedir
  47.    
  48.     name = askdirectory()
  49.     savedir = os.path.join(savedir, name)
  50.    
  51. Title = root.title("krc2lrc小工具")
  52. menu = Menu(root)
  53. root.config(menu=menu)
  54. file = Menu(menu)
  55. file.add_command(label = 'Open', command = select_files_command)
  56. file.add_command(label = 'SaveTo', command = select_savedir_command)
  57. menu.add_cascade(label = 'File', menu = file)
  58. menu.add_cascade(label = 'Exit', command = lambda:exit())
  59. root.mainloop()
复制代码

附上老胡的 逍遥叹 酷狗歌词:
https://wss1.cn/f/7dt99g1r74w 复制链接到浏览器打开

TOP

又搜到了一段JAVA解析的代码
  1. /**
  2. *
  3. */
  4. package cn.tcg.music.tools;
  5. import java.io.BufferedWriter;
  6. import java.io.ByteArrayOutputStream;
  7. import java.io.File;
  8. import java.io.FileFilter;
  9. import java.io.FileInputStream;
  10. import java.io.FileWriter;
  11. import java.io.IOException;
  12. import java.util.zip.Inflater;
  13. /**
  14. * 将KuGou歌词文件krc转换为lrc 创建于 2017年4月28日 下午9:52:11
  15. *
  16. * @author tcg2008
  17. *
  18. */
  19. public class KRC2LRC
  20. {
  21. private static int key[] =
  22. { 64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105 };
  23. /**
  24. * 是否krc格式
  25. *
  26. * @param datas
  27. * @return
  28. */
  29. public static boolean iskrc(byte[] datas)
  30. {
  31. if (datas.length < 4)
  32. {
  33. System.out.println("长度不够");
  34. return false;
  35. }
  36. if (datas[0] == 'k' && datas[1] == 'r' && datas[2] == 'c' && datas[3] == '1')
  37. {
  38. return true;
  39. }
  40. return false;
  41. }
  42. public static void main(String... args) throws IOException
  43. {
  44. //转换歌曲文件夹
  45. File inPath = new File("C:/Users/zzz/Desktop/krc");
  46. File outPath = new File("C:/Users/zzz/Desktop/lrc");
  47. outPath.mkdirs();
  48. File[] files = inPath.listFiles(new FileFilter()
  49. {
  50. @Override
  51. public boolean accept(File pathname)
  52. {
  53. return pathname.isFile();
  54. }
  55. });
  56. for (File krcPath : files)
  57. {
  58. String fileName = krcPath.getName();
  59. File lrcPath = new File(outPath, (fileName.substring(0, fileName.lastIndexOf(".")) + ".lrc"));
  60. try
  61. {
  62. krc2lrc(krcPath, lrcPath);
  63. } catch (IOException e)
  64. {
  65. e.printStackTrace();
  66. }
  67. }
  68. }
  69. public static void krc2lrc(File krcPath, File lrcPath) throws IOException
  70. {
  71. System.out.println(krcPath);
  72. try
  73. {
  74. byte[] datas = readAllBytes(krcPath);
  75. if (!iskrc(datas))
  76. {
  77. System.out.println("不是krc格式");
  78. return;
  79. }
  80. byte[] _datas = new byte[datas.length - 4];
  81. System.arraycopy(datas, 4, _datas, 0, datas.length - 4);
  82. for (int i = 0; i < _datas.length; i++)
  83. {
  84. _datas[i] = (byte) (_datas[i] ^ key[i % 16]);
  85. }
  86. Inflater decompresser = new Inflater();
  87. decompresser.setInput(_datas);
  88. ByteArrayOutputStream sb = new ByteArrayOutputStream();
  89. byte[] buf = new byte[1024];
  90. while (!decompresser.finished())
  91. {
  92. int leng = decompresser.inflate(buf);
  93. sb.write(buf, 0, leng);
  94. }
  95. // System.out.println("解压长度:" + sb.toByteArray().length);
  96. String lines[] = new String(sb.toByteArray()).split("\n");
  97. // System.out.println("行数:" + lines.length);
  98. try (BufferedWriter writer = new BufferedWriter(new FileWriter(lrcPath)))
  99. {
  100. for (String line : lines)
  101. {
  102. int i1 = line.indexOf("]");
  103. String timestr = line.substring(1, i1);
  104. String times[] = timestr.split(",");
  105. if (times.length == 2)
  106. {
  107. int ms = Integer.parseInt(times[0]);
  108. String time = String.format("[%02d:%02d.%02d]", (ms % (1000 * 60 * 60)) / (1000 * 60),
  109. (ms % (1000 * 60)) / 1000, (ms % (1000 * 60)) % 100);
  110. writer.write(time);
  111. writer.write(line.substring(i1 + 1).replaceAll("<.*?>", ""));
  112. } else
  113. {
  114. writer.write(line);
  115. }
  116. }
  117. }
  118. } catch (Exception e)
  119. {
  120. e.printStackTrace();
  121. }
  122. }
  123. /**
  124. * @param file
  125. * @return
  126. */
  127. private static byte[] readAllBytes(File file)
  128. {
  129. try (FileInputStream is = new FileInputStream(file))
  130. {
  131. byte[] data = new byte[(int) file.length()];
  132. is.read(data);
  133. return data;
  134. } catch (IOException e)
  135. {
  136. e.printStackTrace();
  137. }
  138. return null;
  139. }
  140. }
复制代码

TOP

又找到一段C解析代码, 供参考
  1. #ifdef WIN32
  2. #define  _CRT_SECURE_NO_WARNINGS
  3. #endif
  4. #include <stdio.h>
  5. #include <wchar.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <malloc.h>
  10. #include <sys/stat.h>
  11. #include "zlib/zconf.h"
  12. #include "zlib/zlib.h"
  13. const static wchar_t key[] = { L'@', L'G', L'a', L'w', L'^', L'2',
  14.                                L't', L'G', L'Q', L'6', L'1', L'-',
  15.                                L'Î', L'ò', L'n', L'i'};
  16. static unsigned char result[1024*1024];
  17. int sncasecmp(char *s1, char *s2, size_t n)
  18. {
  19.     unsigned int  c1, c2;
  20.     while (n) {
  21.         c1 = (unsigned int)*s1++;
  22.         c2 = (unsigned int)*s2++;
  23.         c1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 | 0x20) : c1;
  24.         c2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 | 0x20) : c2;
  25.         if (c1 == c2) {
  26.             if (c1) {
  27.                 n--;
  28.                 continue;
  29.             }
  30.             return 0;
  31.         }
  32.         return c1 - c2;
  33.     }
  34.     return 0;
  35. }
  36. int decompression(unsigned char *src, size_t srcsize, unsigned char *dst, size_t *dstsize)
  37. {
  38.     *dstsize = 1024 * 1024;
  39.     if (Z_OK != uncompress(result, dstsize, src, srcsize))
  40.         return -1;
  41.     return 0;
  42. }
  43. int isfilter(char *tok, int len)
  44. {
  45.     if (!sncasecmp(tok, "[id", 3)) {
  46.         return 1;
  47.     } else if (!sncasecmp(tok, "[by", 3)) {
  48.         return 1;
  49.     } else if (!sncasecmp(tok, "[hash", 5)) {
  50.         return 1;
  51.     } else if (!sncasecmp(tok, "[al", 3)) {
  52.         return 1;
  53.     } else if (!sncasecmp(tok, "[sign", 5)) {
  54.         return 1;
  55.     } else if (!sncasecmp(tok, "[total", 6)) {
  56.         return 1;
  57.     } else if (!sncasecmp(tok, "[offset", 7)) {
  58.         return 1;
  59.     }
  60.     return 0;
  61. }
  62. int create_lrc(char *path, unsigned char *lrc, size_t lrclen)
  63. {
  64.     size_t i;
  65.     FILE *fp;
  66.     int top = 0;
  67.     int j;
  68.     fp = fopen(path, "wb");
  69.     if (!fp) {
  70.         fprintf(stderr, "%s", strerror(errno));
  71.         return -1;
  72.     }
  73.     for (i = 0; i < lrclen; i++) {
  74.         int len;
  75.         if (top == 0) {
  76.             switch (lrc[i]) {
  77.             case '<':
  78.                 top++;
  79.                 break;
  80.             case '[':
  81.                 len = (strchr((char*)&lrc[i], ']') - (char*)&lrc[i]) + 1;
  82.                 for (j = 0; j < len; j++) {
  83.                     if (lrc[i+j] == ':') {
  84.                         if (isfilter((char*)&lrc[i], len)) {
  85.                             while (lrc[++i] != '\n' && i < lrclen) {
  86.                             }
  87.                         }
  88.                         goto filter_done;
  89.                     }
  90.                 }
  91.                 for (j = 0; j < len; j++) {
  92.                     int ms;
  93.                     if (lrc[i + j] == ',') {
  94.                         char ftime[14];
  95.                         lrc[i + j] = 0;
  96.                         ms = atoi((char*)&lrc[i + 1]);
  97.                         sprintf(ftime, "[%.2d:%.2d.%.2d]", (ms % (1000 * 60 * 60)) / (1000 * 60), (ms % (1000 * 60)) / 1000, (ms % (1000 * 60)) % 100);
  98.                      
  99.                         for (j = 0; j < 10; j++) {
  100.                             fputc(ftime[j], fp);
  101.                         }
  102.                         i = i + len - 1;
  103.                         break;
  104.                     }
  105.                 }
  106.                 break;
  107. filter_done:
  108.             default:
  109.                 fputc(lrc[i], fp);
  110.                 break;
  111.             }
  112.         } else if (top == 1 && lrc[i] == '>') {
  113.             top--;
  114.         }
  115.     }
  116.     fclose(fp);
  117.     return 0;
  118. }
  119. int main(int argc, char **argv)
  120. {
  121.     int i;
  122.     FILE *fp;
  123.     struct stat st;
  124.     unsigned char *src;
  125.     size_t dstsize;
  126.     if (argc < 2) {
  127.         printf("usage1: krc2lrc test.krc test.lrc\nusage2: krc2lrc test.krc\n");
  128.         return -1;
  129.     }
  130.     fp = fopen(argv[1], "rb");
  131.     if (!fp) {
  132.         fprintf(stderr, "%s", strerror(errno));
  133.         return -1;
  134.     }
  135.     if (fstat(fileno(fp), &st)) {
  136.         fprintf(stderr, "%s", strerror(errno));
  137.         return -1;
  138.     }
  139.    
  140.     src = (unsigned char *) malloc(st.st_size);
  141.     if (!src) {
  142.         fprintf(stderr, "%s", strerror(errno));
  143.         return -1;
  144.     }
  145.    
  146.     if (fread(src, sizeof(unsigned char), st.st_size, fp) != st.st_size) {
  147.         fprintf(stderr, "%s", strerror(errno));
  148.         return -1;
  149.     }
  150.     if (memcmp(src, "krc1", 4) != 0) {
  151.         fprintf(stderr, "error file format.");
  152.     }
  153.     src += 4;
  154.     for (i = 0; i < st.st_size; i++) {
  155.         src[i] = (unsigned char)(src[i] ^ key[i % 16]);
  156.     }
  157.     decompression(src, st.st_size, result, &dstsize);
  158.     if (argc == 2) {
  159.         char buf[FILENAME_MAX] = {0};
  160.         strncpy(buf, argv[1], strlen(argv[1]) - 4);
  161.         strcat(buf, ".lrc");
  162.         create_lrc(buf, result, dstsize);
  163.     } else if (argc == 3){
  164.         create_lrc(argv[2], result, dstsize);
  165.     }
  166.    
  167.     fclose(fp);
  168.     return 0;
  169. }
复制代码

TOP

test.bat
  1. #&cls&@cd /d "%~dp0" & powershell -c "$cur_dir='%~dp0';Get-Content '%~0' | Out-String | Invoke-Expression" &pause&exit
  2. $file = '胡歌 - 逍遥叹.krc'
  3. #密钥
  4. $key = @(64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105)
  5. #加载dll
  6. [void][System.Reflection.Assembly]::LoadFile($cur_dir+'zlib.dll')
  7. #读取源文件
  8. $bytes = [System.IO.File]::ReadAllBytes($file)
  9. #解密
  10. $compress_bytes = New-Object 'System.Collections.ArrayList'
  11. for($i = 4; $i -lt $bytes.Count-4; $i++){ [void]$compress_bytes.Add(($bytes[$i] -bxor $key[($i-4)%16])) }
  12. #解压缩
  13. $str = [Ionic.Zlib.ZlibStream]::UncompressString($compress_bytes)
  14. #转lrc
  15. &{
  16.     $str -split '\r\n' | foreach {
  17.         if($_ -match '^\[(\d+),(\d+)\]'){
  18.             $t = (New-Object 'datetime' (([int]$Matches[1])*10000)).ToString('[mm:ss.ff]')
  19.             $s = $_ -replace '\[\d+?,\d+\]','' -replace '<\d+?,\d+?,\d+>',''
  20.             $t + $s
  21.         }
  22.     }
  23. } | Out-File ($file -replace 'krc$','lrc')
复制代码
需要zlib库,和bat放一起zlib.dll

TOP

回复 5# went


    感谢帮忙, 真没想到用ps就这么几行代码, 测试了一下,报下面的错误:

Exception calling "LoadFile" with "1" argument(s): "An attempt was made to load an assembly from a network location whi
ch would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET
Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox
the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for mo
re information."
At line:6 char:1
+ [void][System.Reflection.Assembly]:oadFile($cur_dir+'zlib.dll')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: ( [], MethodInvocationException
    + FullyQualifiedErrorId : NotSupportedException

Unable to find type [Ionic.Zlib.ZlibStream].
At line:13 char:8
+ $str = [Ionic.Zlib.ZlibStream]::UncompressString($compress_bytes)
+        ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (Ionic.Zlib.ZlibStream:TypeName) [], RuntimeException
    + FullyQualifiedErrorId : TypeNotFound

请按任意键继续. . .

TOP

回复 5# went

这样也报错
    Add-Type -Path $cur_dir'zlib.dll'

TOP

本帖最后由 went 于 2022-1-17 22:25 编辑

回复 7# 5i365


    dll下载了吗,改成这样呢
  1. [void][System.Reflection.Assembly]::UnsafeLoadFrom($cur_dir+'zlib.dll')
复制代码
!!!!!
1

评分人数

    • 5i365: 下载了, 用这个就可以了! 技术牛X, 乐于助 ...技术 + 1

TOP

回复 8# went


    请问为啥用PS就这么几行代码就搞定了呢? 太意外了, 我预想代码会少一些, 但是没想到这么少!

TOP

本帖最后由 5i365 于 2022-1-17 22:34 编辑

回复 8# went


    不过, 还是得需要一个外在的dll才行,

我在上面github页面点进去, 发现那个C版的代码里有个 编译好的exe文件, 只有100k左右, 这样一算, 都带一个附加文件, 运行效率, 肯定是C生成的exe高

但是不明白, 为什么java版的代码, 就不用别的附加文件呢

TOP

回复 9# 5i365


    powershell在便捷性上确实秒杀其它脚本
    参考http://www.doczj.com/doc/52a6af6f5bcfa1c7aa00b52acfc789eb172d9ea8.html

TOP

回复 11# went


    感谢分享, 实在看不懂,

要是不用dll就能搞定就好了

TOP

回复 10# 5i365


    c是用的zlib的静态库,不需要额外的dll,powershell不行
  1. #include "zlib/zconf.h"
  2. #include "zlib/zlib.h"
复制代码

TOP

回复 13# went


    要是能把这个功能加到您的 那个coder编码工具里就好了, 以后想用coder了, 上次自己试了下, 还是没有能力把它集成到PS代码中, 集成进去后, 就不用带coder.exe了

想把coder集成到ps代码的最后位置

TOP

回复 14# 5i365


    真想把coder.exe放到ps里,用base64存放
    但coder.exe还是有16kb,我觉得大可不必

TOP

返回列表