Board logo

标题: [文本处理] 批处理如何获取json文件里的特定字符串? [打印本页]

作者: away    时间: 2017-4-28 22:24     标题: 批处理如何获取json文件里的特定字符串?

问题简述:
我在手机上的某个视频客户端下载了好几套unity3d的教学视频,然后我打算把手机里已经下载好的视频视频分类放进电脑里(不只有Unity教学视频,还有其他类型的视频),然而下载好的视频并不是“%title%.mp4"这样的简单名字,而是统一叫”0.blv",视频所以信息全放在视频的上一级目录里的entry.json的JS脚本里面。。。
样本1的路径:C:\Users\xxx\Desktop\New folder\2054259\1
样本1:
  1. {"avid":2054259,"cover":"http://i0.hdslb.com/bfs/archive/cd1a05782537b44006d86f59b6da612f27645b04.jpg","downloaded_bytes":46107090,"guessed_total_bytes":0,"is_completed":true,"page_data":{"cid":3180663,"from":"vupload","has_alias":false,"link":"","page":1,"part":"正片","raw_vid":"","rich_vid":"","tid":0,"type":"vupload","vid":"vupload_3180663","weblink":""},"prefered_video_quality":200,"seasion_id":0,"spid":0,"title":"unity3d教程-[夜黑风高yoo]-第一节-基础","total_bytes":46107090,"total_time_milli":532000,"type_tag":"lua.hdmp4.bili2api.2"}
复制代码
样本2的路径:C:\Users\xxx\Desktop\New folder\2054259\2
样本2:
  1. {"avid":2054259,"cover":"http://i0.hdslb.com/bfs/archive/cd1a05782537b44006d86f59b6da612f27645b04.jpg","downloaded_bytes":9148421,"guessed_total_bytes":0,"is_completed":true,"page_data":{"cid":3180664,"from":"vupload","has_alias":false,"link":"","page":2,"part":"赠品","raw_vid":"","rich_vid":"","tid":0,"type":"vupload","vid":"vupload_3180664","weblink":""},"prefered_video_quality":200,"seasion_id":0,"spid":0,"title":"unity3d教程-[夜黑风高yoo]-第一节-基础","total_bytes":9148421,"total_time_milli":127126,"type_tag":"lua.hdmp4.bili2api.2"}
复制代码
样本3的路径:C:\Users\xxx\Desktop\New folder\9182057\1
样本3:
  1. {"is_completed":true,"total_bytes":13861107,"downloaded_bytes":13861107,"title":"Mac软件推荐","type_tag":"lua.hdmp4.bili2api.2","cover":"http:\/\/i0.hdslb.com\/bfs\/archive\/141628374019371b16b0dca8bbdb28a2404a14ce.jpg","prefered_video_quality":200,"guessed_total_bytes":0,"total_time_milli":162912,"danmaku_count":5,"time_update_stamp":1492462494756,"avid":9182057,"spid":0,"seasion_id":0,"page_data":{"cid":15171062,"page":1,"from":"vupload","part":"P1","link":"","rich_vid":"","vid":"vupload_15171062","has_alias":false,"weblink":"","tid":95}}
复制代码
需要注意的东西有:
1,所有信息都写在同一行上,没有分行。(应该是所有的视频信息记录文件都是这样的,没有例外)
2, 样本1和样本2的区别在于他们是不同page的(应该说是不同Part),除了标题以外,我同时需要part后面的信息;
3, 而样本3和样本1和2的区别就在于视频title位置不一样,我的思路是, 这说明不能用for /f "tokens=%固定数字%,%固定数字% delims=" 这样的语句,否则提取样本3的视频标题信息时就会失误。还有,if是必须的。
4,虽然所有信息都在同一行。然而还是很有规律的。“,”把不同的信息分开,“:”把同样的信息赋值, 我的思路是:只要:变成=,那样或许就能直接用了。只是,怎么分行赋值呢?

想要的最终目的:
把视频被一层又一层包裹着的子目录中移指定目录(如果视频标题的前9个字符是一样的就放进同一个文件夹里面),
并且将视频重命名为%title%_%part%(视频指定号,%page%)
拿我给的样本举几个个例子:
样本1的名字:unity3d教程-[夜黑风高yoo]-第一节-基础_正片(9182057_p1).blv
样本2的名字:unity3d教程-[夜黑风高yoo]-第一节-基础_赠品 (2054259_p2).blv
样本3的名字:Mac软件推荐(9182057_p1).blv
其中样本1和样本2的视频放在同一个文件夹叫“unity3d教程”里面,而样本3放在一个叫做【Mac软件推荐】的文件夹里面
-------------------------------------------------------------------------------------------------------------
我的目前的代码
正如标题所说的一样,我卡在提取视频信息这一项了。。。我目前的代码是这样的:
  1. @echo off
  2. set dcd=.xml .json .sum
  3. for %%p in (%dcd% .bat) do set %%p=135412
  4. echo %date%,%time%>test.txt
  5. for /r "%cd%" %%i in (*) do (
  6. if not defined %%~xi (
  7. for /f "tokens=6,7,9 delims=\" %%f in ("%%i") do (
  8. echo -------------------------------------->>test.txt
  9. echo %%f —— %%g >>test.txt
  10.                         ::提取视频信息
  11. for /f "delims=" %%a in (%%f\%%g\Entry.json) do echo %%a|findstr /i "title" >>test.txt
  12. echo move "%%i" "%cd%" >>test.txt
  13. echo ren "%%~nxi" "%%f_%%g.flv" >>test.txt
  14. )
  15. )
  16. )
  17. start test.txt
  18. pause
  19. exit
复制代码
别看我到最后只用了一下findstr,在此之前我可是试过用set把","变成空格和把":"变成“=”,最后用for去逐条执行,set的替换过程很成功,可是到了for这一步的时候我遇到了未知错误;我也尝试过用call,去把视频信息提取这一步骤模块化,然而也是失败了;用for /f "tokens=%fir%,%sec% delims=," %%t in (blablabla) do if 循环,最后也是失败了;最后的最后把希望寄托在find和findstr身上,结果发现他们只定位到行……所以最后我也没办法了,只能来这里求助了……
-------------------------------------------------------------------------------------------------------------
问题重述
我有一堆的视频装在不同的文件夹里面,格式如下:
New folder\视频指定号\%page%\xxx\0.blv
而不同的文件夹里面有一个json文件是记载着视频信息的(在%page文件夹里面,和视频文件不在同一个目录里面)

我目前遇到的问题是,如何在New folder这个文件夹里放置一个批处理去提取每一个子文件夹里面的json文件里面的信息(%title%最重要,而%part%的话有就提取,没有的话就算了)并赋值给自己的批处理。而不是直接对着本身已经有的字符串进行分解。
而我,卡在提取%title%这一步了。
-------------------------------------------------------------------------------------------------------------
进展
重新考虑了一下用for去分行这个方法,又写了个测试提出文件信息专用的批处理。然而还是不行。思前想后,对电脑对了两天。结果偶然发现,原来是for语句get不到变量,所以只需要一个变量延迟就搞定了那个未知的错误。好吧。所以我现在的目前测试代码是:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%i in (2054259\2\Entry.json) do set "dtc=%%i"
  3. set "dtc=%dtc:~1%"
  4. echo;%dtc%
  5. pause
  6. echo off
  7. for %%t in (!dtc!) do (
  8. for /f "tokens=1,2* delims=:" %%a in ("%%t") do (
  9. if %%a=="title" (
  10. echo I found it!
  11. pause
  12. ) else (
  13. echo set %%a=%%b"
  14. )
  15. )
  16. )
  17. pause
复制代码
嗯,然后新一个谜题又出现了……为什么,为什么就是没有title?
作者: bbaa    时间: 2017-4-28 22:43

提供给你一个json解析器
作者: 老刘1号    时间: 2017-4-28 22:50

回复 2# bbaa


    目测楼主已经转成纯文本了~
作者: codegay    时间: 2017-4-28 22:53

很多语言中都内置支持json了,处理起很方便。不用这么绕。

http://batch-cn.qiniudn.com/s/tool/index.html 搜索json 结果很多工具。
作者: codegay    时间: 2017-4-28 22:56

http://stackoverflow.com/questio ... son-string-in-batch

http://www.pstips.net/use-json-to-create-objects.html
作者: 老刘1号    时间: 2017-4-28 23:26

回复 4# codegay


    http://batch-cn.qiniudn.com/s/tool/index.html?key=json
第三方库有直接搜索的参数~
作者: /zhqsystem/zhq    时间: 2017-4-28 23:44

本帖最后由 /zhqsystem/zhq 于 2017-4-28 23:50 编辑

自己缩减吧,主要是考虑多用途才写了2个重复段,另外样本与给出的结果不符
  1. for /f "delims=" %%i in ('dir/a-d/s/b "*.txt"')do (
  2. for /f "usebackq delims=" %%j in ("%%~fi")do (
  3.   set "#=%%j"
  4.   call:0
  5.   echo,!title!!part!!avid!%%~xi
  6. )
  7. )
  8. pause
  9. goto:eof
  10. :0
  11. set "title="
  12. set "avid="
  13. set "part="
  14. :1
  15. if not defined # goto:eof
  16. for /f "tokens=1,* delims={}:," %%y in ("!#!")do (
  17. set "#=%%z"
  18. for /f "delims=" %%i in (""title"")do if /i "%%y"=="%%i" (
  19.   for /f "tokens=1,* delims=:," %%y in ("%%z")do (
  20.    set "%%~i=%%~y"
  21.    if defined %%~i set "%%~i=%%~y"
  22.   )
  23. )
  24. for /f "delims=" %%i in (""avid"")do if /i "%%y"=="%%i" (
  25.   for /f "tokens=1,* delims=:," %%y in ("%%z")do (
  26.    set "%%~i=%%~y"
  27.    if defined %%~i set "%%~i= (%%~y)"
  28.   )
  29. )
  30. for /f "delims=" %%i in (""part"")do if /i "%%y"=="%%i" (
  31.   for /f "tokens=1,* delims=:," %%y in ("%%z")do (
  32.    set "%%~i=%%~y"
  33.    if defined %%~i set "%%~i=_%%~y"
  34.   )
  35. )
  36. )
  37. goto:1
  38. goto:eof
复制代码

作者: pcl_test    时间: 2017-4-29 00:49

本帖最后由 pcl_test 于 2017-5-5 11:47 编辑
  1. /*&cls
  2. @echo off
  3. dir /a-d/b/s 0.blv|cscript -nologo -e:jscript "%~f0"
  4. pause&exit
  5. */
  6. function ReadText(file, charset){
  7.     var txt="";
  8.     try{
  9.         var stream = new ActiveXObject('ADODB.Stream')
  10.         stream.Type = 2
  11.         stream.Mode = 3
  12.         stream.Charset = charset
  13.         stream.Open()
  14.         stream.LoadFromFile(file)
  15.         stream.Position = 0
  16.         txt = stream.ReadText()
  17.     }catch(Err){}
  18.     stream.Close()
  19.     return txt
  20. }
  21. var fso=new ActiveXObject('Scripting.FileSystemObject');
  22. var blv=WSH.StdIn.ReadAll().split(/[\r\n]+/);
  23. for(var i=0;i<blv.length;i++){
  24.     var json = blv[i].replace(/[^\\]+\\[^\\]+$/,'')+'entry.json';
  25.     if(fso.FileExists(json)){
  26.         var txt=ReadText(json, 'utf-8');
  27.         var m=eval('('+txt+')');
  28.         var newname=m['title']+'_'+m['page_data']['part']+'('+
  29.             m['avid']+'_'+m['page_data']['page']+').flv';
  30.             WSH.echo('ren "'+blv[i]+'" "'+newname+'"');
  31.     }
  32. }}
复制代码
  1. @echo off
  2. for %%a in ("avid":2054259,"page":1,"part":"正片","title":"unity3d教程-[夜黑风高yoo]-第一节-基础",……) do echo;%%a
  3. pause
复制代码

作者: away    时间: 2017-4-29 01:11

回复 6# 老刘1号


    谢谢,不过我不会用呃……我下载您给出的地址里的jsoned64,并把它放进C:\WINDOWS\system32里面,可是请问我该怎么样写才能拿到里面title和part所对应的数值啊?抱歉,我没用过第三方工具和学过JS……
作者: bbaa    时间: 2017-4-29 09:16

回复 3# 老刘1号


    此json解析也能解析文本
作者: away    时间: 2017-4-29 10:47

回复 8# pcl_test


    第一个代码主要还是用JS去执行的对吧,可惜只对样本1和样本2有效……还有,我不会改JS代码……总之,先谢谢你的代码了
    关于第二个代码你是想提示我用字符段去代入for是吧?我已经试过这个方法了。这是我写的测试bat.
  1. for /f "delims=" %%i in (9182057\1\Entry.json) do set "dtc=%%i"
  2. set "dtc=%dtc:~1%"
  3. set "dtc=%dtc::==%"
  4. echo;%dtc%
  5. pause
  6. for /f "delims=" %%a in ("%dtc%") do echo set %%a
  7. pause
复制代码
结果set的舍弃字符和字符替换成功,可是还是没能分行,最重要的是按下任意键后(因为在最后一句前有个pause嘛),整个窗口就消失了。这说明最后一句有问题,但是原因我可是想不明白。
作者: 老刘1号    时间: 2017-5-2 22:57

回复 9# away


    没用过+1
作者: codegay    时间: 2017-5-3 07:07

jq这东西,有做数据科学人在用。
https://stedolan.github.io/jq/
作者: pcl_test    时间: 2017-5-3 09:17

本帖最后由 pcl_test 于 2017-5-3 10:44 编辑

回复 11# away
1、只对样本1和样本2有效?样本3不是可以解析吗?把无效的json文件打包上传附件看看
  1. @echo off
  2. more +9 "%~f0"|mshta ^
  3.     ^"javascript:var fso=new ActiveXObject('Scripting.FileSystemObject');^
  4.     var txt=fso.GetStandardStream(0).readall();^
  5.     var json=eval('('+txt+')');^
  6.     var out=json['title']+'\r\n'+json['page_data']['part']+'\r\n'+^
  7.         json['avid']+'\r\n'+json['page_data']['page'];^
  8.     fso.GetStandardStream(1).Write(out);close()^"|more
  9. pause&exit
  10. {"is_completed":true,"total_bytes":13861107,"downloaded_bytes":13861107,"title":"Mac软件推荐","type_tag":"lua.hdmp4.bili2api.2","cover":"http:\/\/i0.hdslb.com\/bfs\/archive\/141628374019371b16b0dca8bbdb28a2404a14ce.jpg","prefered_video_quality":200,"guessed_total_bytes":0,"total_time_milli":162912,"danmaku_count":5,"time_update_stamp":1492462494756,"avid":9182057,"spid":0,"seasion_id":0,"page_data":{"cid":15171062,"page":1,"from":"vupload","part":"P1","link":"","rich_vid":"","vid":"vupload_15171062","has_alias":false,"weblink":"","tid":95}}
复制代码
2、你试过的for方法不是我提供的参考方法,这样不是分行了吗?
  1. ::{"is_completed":true,"total_bytes":13861107,"downloaded_bytes":13861107,"title":"Mac软件推荐","type_tag":"lua.hdmp4.bili2api.2","cover":"http:\/\/i0.hdslb.com\/bfs\/archive\/141628374019371b16b0dca8bbdb28a2404a14ce.jpg","prefered_video_quality":200,"guessed_total_bytes":0,"total_time_milli":162912,"danmaku_count":5,"time_update_stamp":1492462494756,"avid":9182057,"spid":0,"seasion_id":0,"page_data":{"cid":15171062,"page":1,"from":"vupload","part":"P1","link":"","rich_vid":"","vid":"vupload_15171062","has_alias":false,"weblink":"","tid":95}}
  2. @echo off
  3. set /p json=<"%~f0"
  4. for %%a in (%json:~3,-1%) do echo;%%a
  5. pause
复制代码

作者: away    时间: 2017-5-4 23:45

回复 14# pcl_test


    对哦,set还能这么用。不止样本3,我把整个文件夹都进行简化,打包上论坛了,你可以去顶楼下载。至于你给的第一个批处理运行的结果,它是这样显示的:
  1. ren "C:\Users\xxx\Desktop\Newfolder\2054259\1\lua.hdmp4.bili2api.2\0.blv" "unity3d鏁欑▼-[澶滈粦椋庨珮yoo]-绗竴鑺?鍩虹_姝g墖(2054259_1).flv"
  2. ren "C:\Users\xxx\Desktop\Newfolder\2054259\2\lua.hdmp4.bili2api.2\0.blv" "unity3d鏁欑▼-[澶滈粦椋庨珮yoo]-绗竴鑺?鍩虹_璧犲搧(2054259_2).flv"
  3. C:\Users\xxx\Desktop\Newfolder\求助得来的批处理2.bat(13, 9) Microsoft JScript compilation error: Expected '}'
  4. Press any key to continue . . .
复制代码
嗯……文件名不知为何乱码了……
作者: pcl_test    时间: 2017-5-5 11:49

回复 15# away

乱码是因为编码问题,8楼已改
作者: idzyr    时间: 2018-11-28 16:10

楼主说的是哔哩哔哩下载的视频吧
作者: wx623255984    时间: 2019-5-29 15:29

回复 15# away


    说了半天最后也没有把你的最终版放上来   凸-_-凸




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2