返回列表 发帖

[文本处理] 批处理如何获取json文件里的特定字符串?

问题简述:
我在手机上的某个视频客户端下载了好几套unity3d的教学视频,然后我打算把手机里已经下载好的视频视频分类放进电脑里(不只有Unity教学视频,还有其他类型的视频),然而下载好的视频并不是“%title%.mp4"这样的简单名字,而是统一叫”0.blv",视频所以信息全放在视频的上一级目录里的entry.json的JS脚本里面。。。
样本1的路径:C:\Users\xxx\Desktop\New folder\2054259\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"}COPY
样本2的路径:C:\Users\xxx\Desktop\New folder\2054259\2
样本2:
{"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"}COPY
样本3的路径:C:\Users\xxx\Desktop\New folder\9182057\1
样本3:
{"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}}COPY
需要注意的东西有:
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软件推荐】的文件夹里面
-------------------------------------------------------------------------------------------------------------
我的目前的代码
正如标题所说的一样,我卡在提取视频信息这一项了。。。我目前的代码是这样的:
@echo off
set dcd=.xml .json .sum
for %%p in (%dcd% .bat) do set %%p=135412
echo %date%,%time%>test.txt
for /r "%cd%" %%i in (*) do (
if not defined %%~xi (
for /f "tokens=6,7,9 delims=\" %%f in ("%%i") do (
echo -------------------------------------->>test.txt
echo %%f —— %%g >>test.txt
                        ::提取视频信息
for /f "delims=" %%a in (%%f\%%g\Entry.json) do echo %%a|findstr /i "title" >>test.txt
echo move "%%i" "%cd%" >>test.txt
echo ren "%%~nxi" "%%f_%%g.flv" >>test.txt
)
)
)
start test.txt
pause
exitCOPY
别看我到最后只用了一下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不到变量,所以只需要一个变量延迟就搞定了那个未知的错误。好吧。所以我现在的目前测试代码是:
@echo off&setlocal enabledelayedexpansion
for /f "delims=" %%i in (2054259\2\Entry.json) do set "dtc=%%i"
set "dtc=%dtc:~1%"
echo;%dtc%
pause
echo off
for %%t in (!dtc!) do (
for /f "tokens=1,2* delims=:" %%a in ("%%t") do (
if %%a=="title" (
echo I found it!
pause
) else (
echo set %%a=%%b"
)
)
)
pauseCOPY
嗯,然后新一个谜题又出现了……为什么,为什么就是没有title?

提供给你一个json解析器

TOP

回复 2# bbaa


    目测楼主已经转成纯文本了~

TOP

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

http://batch-cn.qiniudn.com/s/tool/index.html 搜索json 结果很多工具。
去学去写去用才有进步。安装python3代码存为xx.py 双击运行或右键用IDLE打开按F5运行

TOP

去学去写去用才有进步。安装python3代码存为xx.py 双击运行或右键用IDLE打开按F5运行

TOP

回复 4# codegay


    http://batch-cn.qiniudn.com/s/tool/index.html?key=json
第三方库有直接搜索的参数~

TOP

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

自己缩减吧,主要是考虑多用途才写了2个重复段,另外样本与给出的结果不符
for /f "delims=" %%i in ('dir/a-d/s/b "*.txt"')do (
for /f "usebackq delims=" %%j in ("%%~fi")do (
  set "#=%%j"
  call:0
  echo,!title!!part!!avid!%%~xi
)
)
pause
goto:eof
:0
set "title="
set "avid="
set "part="
:1
if not defined # goto:eof
for /f "tokens=1,* delims={}:," %%y in ("!#!")do (
set "#=%%z"
for /f "delims=" %%i in (""title"")do if /i "%%y"=="%%i" (
  for /f "tokens=1,* delims=:," %%y in ("%%z")do (
   set "%%~i=%%~y"
   if defined %%~i set "%%~i=%%~y"
  )
)
for /f "delims=" %%i in (""avid"")do if /i "%%y"=="%%i" (
  for /f "tokens=1,* delims=:," %%y in ("%%z")do (
   set "%%~i=%%~y"
   if defined %%~i set "%%~i= (%%~y)"
  )
)
for /f "delims=" %%i in (""part"")do if /i "%%y"=="%%i" (
  for /f "tokens=1,* delims=:," %%y in ("%%z")do (
   set "%%~i=%%~y"
   if defined %%~i set "%%~i=_%%~y"
  )
)
)
goto:1
goto:eofCOPY
这么好的论坛你上哪找,运行测试环境为6.1.7601-64
注:请遵守互联网信息安全,勿用于非法用途

TOP

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

TOP

回复 6# 老刘1号


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

TOP

回复 3# 老刘1号


    此json解析也能解析文本

TOP

回复 8# pcl_test


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

TOP

回复 9# away


    没用过+1

TOP

jq这东西,有做数据科学人在用。
https://stedolan.github.io/jq/
去学去写去用才有进步。安装python3代码存为xx.py 双击运行或右键用IDLE打开按F5运行

TOP

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

回复 11# away
1、只对样本1和样本2有效?样本3不是可以解析吗?把无效的json文件打包上传附件看看
@echo off
more +9 "%~f0"|mshta ^
    ^"javascript:var fso=new ActiveXObject('Scripting.FileSystemObject');^
    var txt=fso.GetStandardStream(0).readall();^
    var json=eval('('+txt+')');^
    var out=json['title']+'\r\n'+json['page_data']['part']+'\r\n'+^
        json['avid']+'\r\n'+json['page_data']['page'];^
    fso.GetStandardStream(1).Write(out);close()^"|more
pause&exit
{"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}}COPY
2、你试过的for方法不是我提供的参考方法,这样不是分行了吗?
::{"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}}
@echo off
set /p json=<"%~f0"
for %%a in (%json:~3,-1%) do echo;%%a
pauseCOPY

TOP

回复 14# pcl_test


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

TOP

返回列表