Board logo

标题: [网络工具] 下载51VOA网站上《美语三级跳 Go English》中的文本及音频 [打印本页]

作者: namejm    时间: 2011-4-9 01:36     标题: 下载51VOA网站上《美语三级跳 Go English》中的文本及音频

本帖最后由 namejm 于 2011-4-10 12:29 编辑

  下载51VOA网站上《美语三级跳 Go English》中的文字和音频并非本人一时心血来潮,而是源于论坛网友的一篇求助帖(http://bbs.bathome.net/thread-11802-1-1.html),具体要求为:将http://www.51voa.com/Go_English_1.html这个网站的下级链接采集成文本文件,文本内容包含标题,结尾至“这次的美语三级跳就播送到这里。”如果mp3音频也一并采集下来,最好。

  从初中到大学,教过本人English的teacher有男有女,惜乎Mister非帅哥,Miss非美眉,所以,本人的鸟语一向不咋地,此实乃本人人生中的一大憾事,因此之故,我对发奋学习English的人一向抱有敬意。既然该网友碰到了学英语中的大难题,那我就尽我所能助人一臂之力吧。

  例行公事地开始网页分析。

  打开http://www.51voa.com/Go_English_1.html,鼠标四处戳戳点点,左键进入、右键查看、Ctrl+F搜索、尝试下载……捣鼓了好一阵,把它们的家底查了个一清二楚:总共有71个网页及71个mp3需要下载,每个网页中都对应着一个mp3,mp3的下载地址是嵌在这些网页代码中的,而这些网页的真实url,又是在http://www.51voa.com/Go_English_1.htmlhttp://www.51voa.com/Go_English_2.html中被一一罗列了出来,所有的链接都是那么的直白无误,没有丝毫的矜持含蓄,所有的下载动作都无需验证账号密码。

  这是个简单的活,我告诉自己。

  打开记事本,轻车熟路地码字;再顺手打开cmd.exe窗口,随时做一些小测试。

  curl -o 轻轻松松就把 Go_English_1.html 和 Go_English_2.html 下到了本地,htox32c /ip /o0 /u3 再干脆利落地把html文件转换成了文本,保留了原始编码格式,保留了下载链接。

  for /f 读取转换后的文本,各种奇形怪状的字符就开始稀里哗啦地在cmd窗口中往下掉——坏了,转换后的文本文件肯定不是ANSI编码!记事本打开那些文本,点“文件/另存为”,一查“编码”栏目,"UTF-8"几个字符白纸黑字异常刺眼。more一下,type一下,竟然还是乱码,倒吸一口凉气:这,这,这,不是逼我出绝招么?

  我再也坐不住了,火速奔向白杨大侠的网站:http://baiy.cn,down一个wfr.exe下来,wfr index\*.txt -any -encin:utf-8 -encout:gbk -force,强制转换utf-8为gbk。htox32c.exe到底是小日本写成的工具,竟然没提供unicode转gbk的功能,还是2004年的作品,唉,岁月不饶人啊,不能与时俱进啊。

  解决了编码问题,剩下的事情就好办多了:一行行的字符串,直接丢进 for /f 中,findstr过滤过滤,skip=跳过头N行,delims=切分一下,tokens=接收住,set 再替换一下,揉成团、切成片、搓成条……一阵忙活,提出了N多网页地址和mp3文件地址,curl出马,down之!

  查看最终结果:70个txt,69个mp3。不对啊,应该是71个txt和71个mp3啊,揉了揉眼睛,再仔细一瞅,没错,就只下了那么多。

  排查,赶紧排查,看看少了些什么。

  左边世界之窗,右边TotalCommander,鼠标戳了又戳,键盘按了又按,睁大眼睛来来回回扫描了好几次,终于把漏掉的文件找出来了:少了标题为“517 boat...”的网页内容和编号为016a及007b的mp3。

  与其他文件相比,它们有什么特殊之处?

  先看网页文件,其他的标题都是含有关键词“课程”二字,唯有“517 boat”缺少此标记,恩,看来不能以“课程”作为前后行标记来提取URL,只能更换了。换什么好呢?看看转换后的txt,都有些什么规律。找啊找,终于发现了更直接的标记:URL都以字符串“</Voa_English_Learning/”打头呢,得,赶紧换标记吧,那提取URL的算法也得随之更换了。

  再瞅瞅016a和007b的mp3,我左看右看上看下看,看了半天,硬是没能从URL的构成上找到特别之处。URL放到迅雷里一下载,那速度也是嗖嗖的啊;换成其他的mp3链接,那速度更是嗖嗖的啊。嗯哼?哦,似乎016a和007b比其他的下载速度要稍慢,难道这也有问题?try,再try,似乎有点慢,莫非这网站动了什么手脚?百思不得其解,死马当做活马医吧,给curl加 --retry 重试,不行?再加 --retry-delay 延时,还不行?靠,我就不信邪了,下载mp3的代码单列出来,call一下子过程,子过程DownMp3中加检测语句:if not exist "..\result\%~1.mp3" goto DownMp3,你不给我down回来,我就让你给我一直下,累趴下了也非得下回来不可,哼哼,不老实干活就死循环,玩残你!

  折腾了老半天,顺手修复了几个小bug,调整了文件保存目录,规范了一下变量名,添加了一些注释……清扫完这些边边角角,世界终于和谐了。

  上代码:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. :: 获取含有具体网页下载链接清单的网页
  4. title 获取含有具体下载链接的网页
  5. md index 2>nul
  6. curl -o index\#1.html "http://www.51voa.com/Go_English_[1-2].html"
  7. htox32c /ip /o0 /u3 index\*.html
  8. wfr index\*.txt -any -encin:utf-8 -encout:gbk -force
  9. :: 提取具体网页的下载链接并下载之
  10. cls
  11. title 下载每一个教程的网页文件
  12. md content 2>nul
  13. pushd index
  14. for %%i in (*.txt) do (
  15.     for /f "skip=76 tokens=*" %%j in (%%i) do (
  16.         set "UrlHtml=%%j"
  17.         if "!UrlHtml:~0,23!"=="</Voa_English_Learning/" (
  18.             for /f "tokens=2*" %%k in ("!NameHtml!") do (
  19.                 set "NameHtml=%%l"
  20.                 set "NameHtml=!NameHtml: =!"
  21.                 set "NameHtml=!NameHtml::=:!"
  22.                 set "UrlHtml=http://www.51voa.com/!UrlHtml:~1,-1!"
  23.                 title 正在下载 %%k_!NameHtml! 的网页数据
  24.                 curl -o "..\content\%%k_!NameHtml!.html" "!UrlHtml!"
  25.             )
  26.         )
  27.         set "NameHtml=%%j"
  28.     )
  29. )
  30. popd
  31. :: 下载每一课程中的mp3文件,并提取所有课程中的文字内容分别保存
  32. cls
  33. title 网页转文本
  34. md result 2>nul
  35. pushd content
  36. htox32c /ip /o0 /u3 *.html
  37. wfr *.txt -any -encin:utf-8 -encout:gbk -force
  38. cls
  39. for %%i in (*.txt) do (
  40.     for /f "tokens=*" %%j in ('findstr /i "path\.asp\?url=.*\.mp3" "%%i"') do (
  41.         set "UrlMp3=%%j"
  42.         set "UrlMp3=http://archive.51voa.com/!UrlMp3:~16,-1!"
  43.         title 正在下载 !UrlMp3!
  44.         for /f "delims=_" %%k in ("!UrlMp3!") do set "NameMp3=%%~nk"
  45.         call :DownMp3 "!NameMp3!" "!UrlMp3!"
  46.     )
  47.     title 提取 %%i 的内容
  48.     set over=
  49.     (echo %%~ni&echo.&echo.
  50.     for /f "skip=76 tokens=*" %%j in (%%i) do (
  51.         if "%%j"=="这次的美语三级跳就播送到这里。"  set over=yes
  52.         if "%%j"=="Related Articles"  set over=yes
  53.         if not defined over echo %%j&echo.
  54.     ))>..\result\%%i
  55. )
  56. popd
  57. exit
  58. :DownMp3
  59. curl --retry 3 --retry-delay 2 -o "..\result\%~1.mp3" %2
  60. if not exist "..\result\%~1.mp3" goto DownMp3
  61. goto :eof
复制代码
  正文中提到的命令行工具可以在这些地方找到:

  1、Curl.exe:http://curl.haxx.se/(官网)或 http://bbs.bathome.net/thread-1761-1-1.html
  2、HtoX32c.exe:http://win32lab.com/(官网,日文)或 http://bbs.bathome.net/thread-1974-1-1.html(带中文帮助信息)
  3、wfr.exe:http://baiy.cn/utils/wfr/index.htm(官网)

  注意事项:由于本代码用到了目录跳转语句,如果把这些命令行工具与批处理文件放在同一目录下的话,处理会出错,建议把它们放在任意一个%path%目录下,推荐放在%SystemRoot%目录下,一般是c:\windows。
作者: Batcher    时间: 2011-4-9 19:34

wfr会被某些杀软误杀
作者: asnahu    时间: 2011-4-9 21:07

本帖最后由 asnahu 于 2011-4-10 07:39 编辑
  1. curl http://www.51voa.com/Go_English_[1-2].html | sed -n "/list/{:a s/[^\x22]\+[^l]\x22//; //ta; s/\x22G[^\n]\+n>/\x22/g; s/\/V/http:\/\/www.51voa.cm&/g; s/\x22/\n/g; p}" | wget -i -
复制代码

作者: namejm    时间: 2011-4-9 23:49

而mp3的url地址,刚好和相应网页的文件名相对应。

mp3的文件名和课程名并不完全对应,比如编号为016a的网页,对应的mp3为ge016a_22sep2010.mp3。类似的还有好几个,还是得老老实实地去具体帖子里查看。
当然,用批处理只是提供了一种途径,还有其他的方法可以办到。
作者: jh1688    时间: 2011-4-10 06:46

我用楼主的批处理无法下载,调试了一下发现在几个地方用上指定路径就OK了。我是一个菜鸟,说得不一定正确请指教:
  1. @echo on
  2. setlocal enabledelayedexpansion
  3. :: 获取含有具体网页下载链接清单的网页
  4. title 获取含有具体下载链接的网页
  5. md index 2>nul
  6. curl -o index\#1.html "http://www.51voa.com/Go_English_[1-2].html"
  7. htox32c /ip /o0 /u3 index\*.html
  8. wfr index\*.txt -any -encin:utf-8 -encout:gbk -force
  9. :: 提取具体网页的下载链接并下载之
  10. cls
  11. title 下载每一个教程的网页文件
  12. md content 2>nul
  13. pushd index
  14. for %%i in (*.txt) do (
  15.     for /f "skip=76 tokens=*" %%j in (%%i) do (
  16.         set "UrlHtml=%%j"
  17.         if "!UrlHtml:~0,23!"=="</Voa_English_Learning/" (
  18.             for /f "tokens=2*" %%k in ("!NameHtml!") do (
  19.                 set "NameHtml=%%l"
  20.                 set "NameHtml=!NameHtml: =!"
  21.                 set "NameHtml=!NameHtml::=:!"
  22.                 set "UrlHtml=http://www.51voa.com/!UrlHtml:~1,-1!"
  23.                 title 正在下载 %%k_!NameHtml! 的网页数据
  24.                 ..\curl -o "..\content\%%k_!NameHtml!.html" "!UrlHtml!"
  25.             )
  26.         )
  27.         set "NameHtml=%%j"
  28.     )
  29. )
  30. popd
  31. :: 下载每一课程中的mp3文件,并提取所有课程中的文字内容分别保存
  32. cls
  33. title 网页转文本
  34. md result 2>nul
  35. pushd content
  36. ..\htox32c /ip /o0 /u3 *.html
  37. ..\wfr *.txt -any -encin:utf-8 -encout:gbk -force
  38. cls
  39. for %%i in (*.txt) do (
  40.     for /f "tokens=*" %%j in ('findstr /i "path\.asp\?url=.*\.mp3" "%%i"') do (
  41.         set "UrlMp3=%%j"
  42.         set "UrlMp3=http://archive.51voa.com/!UrlMp3:~16,-1!"
  43.         title 正在下载 !UrlMp3!
  44.         for /f "delims=_" %%k in ("!UrlMp3!") do set "NameMp3=%%~nk"
  45.         call :DownMp3 "!NameMp3!" "!UrlMp3!"
  46.     )
  47.     title 提取 %%i 的内容
  48.     set over=
  49.     (echo %%~ni&echo.&echo.
  50.     for /f "skip=76 tokens=*" %%j in (%%i) do (
  51.         if "%%j"=="这次的美语三级跳就播送到这里。"  set over=yes
  52.         if "%%j"=="Related Articles"  set over=yes
  53.         if not defined over echo %%j&echo.
  54.     ))>..\result\%%i
  55. )
  56. popd
  57. exit
  58. :DownMp3
  59. ..\curl --retry 3 --retry-delay 2 -o "..\result\%~1.mp3" %2
  60. if not exist "..\result\%~1.mp3" goto DownMp3
  61. goto :eof
复制代码

作者: namejm    时间: 2011-4-10 12:24

哦,对了,我的那些命令行工具都是放在C:\Windows目录下的,不会因为频繁的跳转路径而找不到路径,如果把那些命令行工具放在批处理当前目录下的话会找不到的,忘了说明了,更新一下。
作者: Vast    时间: 2011-4-10 20:27

十分感谢老大鼎力之助,若不发奋学习,实有辜负之嫌。
作者: wc726842270    时间: 2011-4-10 21:49

和LZ的另外一篇文章有点像
http://bbs.bathome.net/thread-11728-1-1.html
当然是大体方面了.呵呵




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