Board logo

标题: [文本处理] [已解决]批处理如何遍历网页文件夹ID并输出至文本? [打印本页]

作者: lonron    时间: 2023-5-4 19:04     标题: [已解决]批处理如何遍历网页文件夹ID并输出至文本?

https://189.ly93.cc/api.php?c=list&shareCode=VVFnmuRviQRj&accessCode=? 是某网盘根文件夹里的数据,只需提取 isFolder 和 fileId 参数的值。
进入子文件夹的方式:当 “isFolder” 为 true 时,表示 fileId 值是子文件夹ID。(格式:https://189.ly93.cc/api.php?c=list&shareCode=VVFnmuRviQRj&accessCode=?&fileId=17位fileId
以下是一个大概的框架,请问要怎么写才能遍历根文件夹及多级子文件夹,以获取其文件夹的fileId,并输出至文本?

  1. @echo off
  2. for /f "delims=" %%a in ('powershell "(irm 'https://189.ly93.cc/api.php?c=list&shareCode=VVFnmuRviQRj&accessCode=?&fileId=').count"') do (
  3.     for /f "eol=F delims=| tokens=1-2" %%b in ('powershell "(irm 'https://189.ly93.cc/api.php?c=list&limit=%%a&shareCode=VVFnmuRviQRj&accessCode=?&fileId=').data | %% {'{0}|{1}' -f $_.isfolder,$_.fileid}"') do (
  4.         echo %%c>>test.txt
  5.     )
  6. )
  7. pause
复制代码

作者: jyswjjgdwtdtj    时间: 2023-5-4 19:29

搞不懂你为什么要在bat里调用ps?既然有json那直接用js啊?js也有可以get post的com组件可以用啊
作者: lonron    时间: 2023-5-4 19:39

回复 2# jyswjjgdwtdtj


原来用的就是纯bat的方式,要不是for不能支持一行8000多个字符,我根本不想用PS
主要还是完全不会js,一丁点都不会,憋都憋不出一句话。。。
而且我是拿实例学bat的过程中,只是这次刚好遇到的是json罢了。
作者: czjt1234    时间: 2023-5-4 19:57

回复 3# lonron


    纯bat能干啥?必须调用外部命令啊

attrib.exe
net.exe
arp.exe

等等windows自带的外部命令

还有众多的第三方命令

curl.exe
gwak.exe

那为啥不能调用

powershell.exe
cscript.exe
作者: jyswjjgdwtdtj    时间: 2023-5-4 20:01

回复 4# czjt1234


    我觉得吧 与其调用来调用去的 不如直接写ps或者js或者vbs
作者: lonron    时间: 2023-5-4 20:01

回复 4# czjt1234

没毛病,我并不反感用第三方命令,只是相对于js,PS我还能看得懂自己能修改,而且在我看来PS实现一些东西可以更简单点。只是原本我用的for取截取json数据有点笨办法的意思。。。不过也是弃之不用了
作者: jyswjjgdwtdtj    时间: 2023-5-4 20:05

本帖最后由 jyswjjgdwtdtj 于 2023-5-4 20:12 编辑

回复 3# lonron


    盲写一段(没测试过)
  1. var http=new ActiveXObject("msxml2.xmlhttp");
  2. http.Open("GET","https://189.ly93.cc/api.php?c=list&shareCode=3UBZ3ei6NJJz&accessCode=?",False)
  3. http.Send()
  4. var result=eval(http.ResponseText)
复制代码
大小写不熟悉 可能大小写上会出错
然后就
  1. WScript.Echo(result.data[0].fileId)
复制代码
输出72373164319523966

#-_-#莫名不能用……估计是json里有啥不兼容jscript的地方吧
还是去用ps好
作者: lonron    时间: 2023-5-4 20:18

回复 7# jyswjjgdwtdtj


    用PS是没问题的,主要是我现在不知道用bat该怎么写才能达到遍历所有子文件夹ID,然后给curl批量下载。获取这个网页数据的原理我都摸索出来了,我要的数据我都有,但就是不会写循环,好痛苦!!!
作者: jyswjjgdwtdtj    时间: 2023-5-4 20:47

回复 8# lonron


    那你为啥要用bat呢?直接用ps不成?( ̄_ ̄|||)
作者: jyswjjgdwtdtj    时间: 2023-5-4 20:59

  1. set dom=createobject("htmlfile")
  2. set http=createobject("msxml2.xmlhttp")
  3. http.open "GET","https://189.ly93.cc/api.php?c=list&shareCode=3UBZ3ei6NJJz&accessCode=?",false
  4. http.send()
  5. dom.parentwindow.execscript("var j="&http.responsetext)
  6. set json=dom.parentwindow.j
复制代码
这个json就是js对象 你可以使用它来干啥啥
作者: buyiyang    时间: 2023-5-4 22:15

本帖最后由 buyiyang 于 2023-5-4 22:19 编辑

给一个循环的例子
  1. @echo off
  2. if "%~1"=="" (
  3.     set "url=https://189.ly93.cc/api.php?c=list&limit=10&shareCode=3UBZ3ei6NJJz&accessCode=?") else (
  4.     set "url=%~1"
  5. )
  6. setlocal enabledelayedexpansion
  7. for /f "delims=" %%a in ('powershell "(irm '%url%').path | %% {'{0}' -f $_.fileName}"') do (
  8.     timeout /t 1 /nobreak
  9.     for /f "eol=0 delims=| tokens=1-3" %%b in ('powershell "(irm '%url%').data | %% {'{0}|{1}|{2}|{3}' -f $_.fileSize,$_.fileId,$_.fileName,$_.isFolder}"') do (
  10.         if "%%e"=="true" (
  11.         set "url=%url%&fileId=%%c"
  12.         call "%~0" "!url!"
  13.         ) else (
  14.         curl
  15.         )
  16.     timeout /t 1 /nobreak
  17.     )
  18. )
  19. pause
复制代码

作者: pd1    时间: 2023-5-5 00:14

当“isFolder”参数为true时表示子文件夹ID、为false时表示文件ID。
我是没理解两种情况你要怎么分开处理?
分别怎么处理要给出来
作者: lonron    时间: 2023-5-5 08:22

回复 12# pd1


    他们的实际应用关系就是红色加粗部分的:

父(子)文件夹ID都是以第一个网页最后面加&fileId=xxxx呈现的。(可以理解为类似本地情况下,进入某个文件夹。)
文件ID就是在要下载的时候要用,在curl后面的下载地址里面呈现的。
作者: idwma    时间: 2023-5-5 10:34

  1. #@&cls&powershell "type '%~0'|out-string|iex"&pause&exit
  2. $global:a='https://189.ly93.cc/api.php?c=list&shareCode=3UBZ3ei6NJJz&accessCode=?'
  3. $global:b='https://189.ly93.cc/3UBZ3ei6NJJz/{0}?accessCode=?'
  4. function test($id){
  5.     irm ($global:a+'&fileId='+$id)|%{
  6. $path=($_.path|%{$_.fileName}) -join '\'
  7.         md $path
  8. $_.data|%{
  9.     if($_.isFolder){test($_.fileId)}else{
  10. curl --ssl-no-revoke -Lo ($path+'\'+$_.fileName) ($global:b -f $_.fileId)
  11.     }
  12. }
  13.     }
  14. }
  15. test
复制代码

作者: idwma    时间: 2023-5-8 14:18

  1. #@&cls&powershell "type '%~0'|out-string|iex"&pause&exit
  2. $global:a='https://189.ly93.cc/api.php?c=list&shareCode=VVFnmuRviQRj&accessCode=?'
  3. $global:b='https://189.ly93.cc/VVFnmuRviQRj/{0}?accessCode=?'
  4. function test($id){
  5.     irm ($global:a+'&fileId='+$id)|%{
  6. $_.data|%{
  7.     if($_.isFolder){$_.fileId;test($_.fileId)}
  8. }
  9.     }
  10. }
  11. test|sc test.txt
复制代码

作者: lonron    时间: 2023-5-8 18:26

回复 15# idwma


    是我要的效果,非常感谢,另外问下,是否有纯P的方法?
作者: czjt1234    时间: 2023-5-8 18:34

回复 15# idwma


    这个牛叉了,我试了用vbs,写了好几十行,没高兴写下去
作者: idwma    时间: 2023-5-8 18:58

回复 16# lonron

是不是像一楼的放到bat的for里
  1. @echo off
  2. for /f "delims=" %%a in ('powershell "function test($id){(irm ('https://189.ly93.cc/api.php?c=list&shareCode=VVFnmuRviQRj&accessCode=?'+'&fileId='+$id)).data|%%{if($_.isFolder){$_.fileId;test($_.fileId)}}};test"') do (
  3.         echo %%a>>test.txt
  4. )
  5. pause
复制代码

作者: idwma    时间: 2023-5-8 19:00

回复 17# czjt1234


    看前辈们用过递归刚好练习一下
作者: lonron    时间: 2023-5-8 19:21

回复 18# idwma


    万分感谢,终于解决了,纠结了我好几天了 T_T,我光改问题说明想让大家看清楚,就改了好几次。
作者: czjt1234    时间: 2023-5-8 19:39

回复 20# lonron


    据说程序员最怕的就是改需求
作者: lonron    时间: 2023-5-8 19:43

回复 21# czjt1234


    隔行如隔山啊,同样是脚本语言,对PS和P实在很吃力,有的问题用pascal就容易多了
作者: lonron    时间: 2023-5-8 21:02

本帖最后由 lonron 于 2023-5-8 22:11 编辑

回复 18# idwma


    老师,不好意思,刚刚认真测试代码后发现有三个问题被我忽略了。还恳请您再次帮忙修改下,谢谢:

1、是需要在遍历的开始就先输出一行根目录ID。(根目录ID在path字段里可以获取,但是子文件夹path字段里的feliId是包括自身以及所有上级目录ID数据的,就是目录树。)
2、是这个页面有一个条数限制,默认是30条数据。(格式是在 c=list 后面加上 &limit= 条数,count 字段是当前目录的文件和文件夹总数。)
3、是这个网站好像对抓取数据有做过载保护,所以需要每次获取一条ID后延迟一秒。(测试过一秒一条基本安全没出现过报错。)
作者: idwma    时间: 2023-5-8 22:59

回复 23# lonron
  1. @echo off
  2. for /f "delims=" %%a in ('powershell "function test($id){irm ('https://189.ly93.cc/api.php?c=list&limit=99999999999&shareCode=VVFnmuRviQRj&accessCode=?'+'&fileId='+$id)|%%{if(!$global:a){($global:a=$_.path.fileId)}$_.data|%%{if($_.isFolder){$_.fileId;sleep -m 500;test($_.fileId)}}}};test"') do (
  3.         echo %%a>>test.txt
  4. )
  5. pause
复制代码

作者: lonron    时间: 2023-5-8 23:04

回复 24# idwma


    这个limit能获取实际的数吗?
作者: idwma    时间: 2023-5-8 23:10

回复 25# lonron


可以但要套一层循环
现在这样不好吗可以少发一次网络请求
作者: lonron    时间: 2023-5-8 23:16

回复 26# idwma


    条数这个我确实一开始也这么想的,不过我本来就是拿实例学习的,如果老师您方便,还希望您能帮我修改下,真的非常感谢!
作者: idwma    时间: 2023-5-8 23:36

  1. @echo off
  2. for /f "delims=" %%a in ('powershell "function test($id){$z=irm ('https://189.ly93.cc/api.php?c=list&shareCode=VVFnmuRviQRj&accessCode=?'+'&fileId='+$id);$z='https://189.ly93.cc/api.php?c=list&limit='+$z.count+'&shareCode=VVFnmuRviQRj&accessCode=?'+'&fileId='+$id;sleep 1;irm $z|%%{if(!$global:a){($global:a=$_.path.fileId)}$_.data|%%{if($_.isFolder){$_.fileId;sleep -m 500;test($_.fileId)}}}};test"') do (
  3.         echo %%a>>test.txt
  4. )
  5. pause
复制代码

作者: lonron    时间: 2023-5-8 23:48

回复 28# idwma


    非常感谢!!!最后有一个小小的疑问,就是单独把ps这段放入控制台的时候,我发现第一条和第二条是同时出现的,其他都是按固定的延迟显示出来,还有就是抓取ID中途我ctrl+c终止,重新运行这段代码时,根目录的ID不会读取了这是为什么?
作者: idwma    时间: 2023-5-9 14:32

一二条在同一个页面
重置变量$a
  1. powershell "$a=0;function test($id){$z=irm ('https://189.ly93.cc/api.php?c=list&shareCode=VVFnmuRviQRj&accessCode=?'+'&fileId='+$id);$z='https://189.ly93.cc/api.php?c=list&limit='+$z.count+'&shareCode=VVFnmuRviQRj&accessCode=?'+'&fileId='+$id;sleep 1;irm $z|%%{if(!$global:a){($global:a=$_.path.fileId)}$_.data|%%{if($_.isFolder){sleep -m 500;$_.fileId;test($_.fileId)}}}};test"
复制代码

作者: lonron    时间: 2023-5-17 23:58

本帖最后由 lonron 于 2023-5-18 09:44 编辑

回复 30# idwma

https://189.ly93.cc/api.php?c=list&code=7n6r22uae6Jn&pwd=r6sf
   
老师,麻烦您再帮我看下,由于这个网页的api更新了,path字段里现在变成没有fileid和filename字段了,而是直接用实际id配对实际name这种格式,这种情况要怎么获取根id呢?另外,path里的(子)文件夹名称又要怎样写才能全部获取出来?
powershell "$a=0;function test($id){$z=irm ('https://189.ly93.cc/api.php?c=list&code=7n6r22uae6Jn&pwd=r6sf'+'&id='+$id);$z='https://189.ly93.cc/api.php?c=list&limit='+$z.count+'&code=7n6r22uae6Jn&pwd=r6sf'+'&id='+$id;sleep 1;irm $z|%%{if(!$global:a){($global:a=$_.path.fileId)}$_.data|%%{if($_.isdir){sleep -m 500;$_.id;test($_.id)}}}};test"

作者: idwma    时间: 2023-5-18 17:22

回复 31# lonron
  1. $a=0;
  2. function test($id){
  3. $y='https://189.ly93.cc/api.php?c=list&code=7n6r22uae6Jn&pwd=r6sf&fileId=';
  4. $z=irm ($y+$id);
  5. if($z.count -gt 30){sleep 1;$z=irm ($y+$id+'&limit='+$z.count)}
  6. $z|%{
  7. if(!$global:a){($global:a=$_.path.psobject.properties.name)}
  8. sleep 1;
  9. $_.data|%{if($_.isdir){$_.id;test($_.id)}}
  10. }
  11. }
  12. test
复制代码

作者: lonron    时间: 2023-5-18 19:18

回复 32# idwma


    有点看懵了,似乎是比原来代码多加了一个前置判断总条数是否大于30?
作者: idwma    时间: 2023-5-18 21:30

回复 33# lonron


前面的不用管把原来的改成第7行一样的就行了
全部获取是要全部显示出来吗
$_.path.psobject.name 是id
$_.path.psobject.value 是文件夹名称
path对象类型变了,可以看下帮助https://learn.microsoft.com/zh-c ... bout-pscustomobject
作者: lonron    时间: 2023-5-20 12:31

本帖最后由 lonron 于 2023-5-20 12:35 编辑

回复 32# idwma


    老师,网站所有者跟我说,直接用count赋值给limit的这种方式不可取,会让他的服务器有一定的风险,可能会存在瞬时post或get过多数据的情况。所以他建议我limit应该固定在100以内,然后用&page=的方式来分流获取数据。这貌似涉及到循环了,还请您再帮忙修改下源代码,实在不好意思一直劳烦您,真的非常感谢!
作者: idwma    时间: 2023-5-20 14:52

回复 35# lonron
  1. $a=0;
  2. function test($id){
  3.     $limit=100;
  4.     $y='https://189.ly93.cc/api.php?c=list&code=7n6r22uae6Jn&pwd=r6sf&fileId=';
  5.     $z=irm ($y+$id+'&limit='+$limit);
  6.     $b=$z.count;
  7.     $c={
  8. z|%{
  9.     if(!$global:a){($global:a=$_.path.psobject.properties.name)}
  10.     sleep 1;
  11.     $_.data|%{if($_.isdir){$_.id;test($_.id)}}
  12. }
  13.     }
  14.     if($b -le 100){&$c}else{
  15. &$c;
  16. for($($i=1;$b+=100);($b-=$limit) -gt 0;++$i){
  17.     sleep 1;
  18.     $z=irm ($y+$id+'&limit='+$lilmit+'&page='+$i);
  19.     &$c
  20. }
  21.     }
  22. }
  23. test
复制代码

作者: lonron    时间: 2023-5-20 15:25

回复 36# idwma


    测试了下第102个开始出现部分重复了,https://189.ly93.cc/file/list?code=QBBzaevemUbm&pwd=4d0d&id=&limit=100 这是用来测试的数据您看下,然后path字段又被他修改回原来了,所以还是用原来的path.id就可以了。
作者: idwma    时间: 2023-5-20 16:30

回复 37# lonron
  1. $a=0;
  2. function test($id){
  3.     $limit=100;
  4.     $y='https://189.ly93.cc/file/list?code=QBBzaevemUbm&pwd=4d0d&id=';
  5.     $z=irm ($y+$id+'&limit='+$limit);
  6.     $b=$z.count;
  7.     $c={
  8. $z|%{
  9.     if(!$global:a){($global:a=$_.path.id)}
  10.     sleep 1;
  11.     $_.data|%{if($_.isdir){$_.id;test($_.id)}}
  12. }
  13.     }
  14.     if($b -le 100){&$c}else{
  15. &$c;
  16. for($($i=2;$b+=100);($b-=$limit) -gt 0;++$i){
  17.     sleep 1;
  18.     $z=irm ($y+$id+'&limit='+$lilmit+'&page='+$i);
  19.     &$c
  20. }
  21.     }
  22. }
  23. test
复制代码

作者: lonron    时间: 2023-5-20 19:01

回复 38# idwma


    还是重复的,和刚才那个区别 $i 一个是1 一个是2
作者: idwma    时间: 2023-5-20 20:32

回复 39# lonron


    18行改成这样
  1. $z=irm ($y+$id+'&limit='+$limit+'&page='+$i);
复制代码





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