用JavaScript获取网页中的js、css、Flash等文件
作者:马健
邮箱:stronghorse@tom.com主页:http://stronghorse.yeah.net
版本:1.01
初始发布日期:2005.08.29
最后更新日期:2005.09.28
目录
一、前言
二、从E书或网页中获取文件的一般步骤
三、从E书或网页中获取链接进来的css文件
四、从E书或网页中获取链接进来的js文件
五、从E书或网页中获取Flash文件
六、从E书或网页中获取背景音乐文件
七、从E书中获取图像文件
八、进入frame页面
九、其它问题
最近我又听到有人抱怨用miniKillEBook反编译电子书,只能得到HTML网页,得不到E书中的js、css、Flash、背景音乐等文件。其实只要各位对JavaScript代码有所了解,就算只用已经公开发布的CtrlN,要得到E书中的这些文件也不是很难。
事先声明:
1、下面所有方法均基于JavaScript,因此可能会给人绕圈子的感觉,效果也无法与直接调用IE非公开接口的IECracker、KillEBook相比。不过这样正好平衡:对于有意通过反编译学习他人做书经验的好学者,用JavaScript本身就是一个练手的过程,而这种方法又很难用于批量反编译,因此做书的人也不必产生过多的担忧。杀鸡取蛋的事俺是不做的,哈哈……
2、为了便于使用,下面给出的JavaScript写得都很傻瓜,所有URL分析工作都交给代码完成,各位只要会按Ctrl+C、Ctrl+V键就好。但是自动化操作毕竟有其极限,对于大多数网页来说用这些代码应该可以搞定,但是如果碰到搞不定的网页,还是要靠人工对HTML代码进行分析。在分析时如果碰到加密网页,可以用CtrlN的“HTML片段”功能,对加密HTML进行解码。在源代码中查找链接时,可以用搜索功能快速定位。
3、现在基于IE内核的电子书基本上通过自定义协议插件实现,对JavaScript协议插件的支持程度不一,因此如果代码在某些电子书上出现错误,请不必奇怪。
4、除了用于反编译E书,这些代码在平时浏览正常网页时也有用,如用来抓网页中的Falsh文件。
5、所有代码均在Windows XP SP2下测试通过,其它环境我没试,不过估计IE版本不能低于6.0。
6、所有代码均为我的原创,个人可以免费使用,网站转载、商业牟利请先获得我的授权。
从E书或普通网页中获取各种文件的步骤基本相同,只是需要输入的JavaScript代码不同:
- 启动CtrlN。这是为了防止电子书或网页禁用快捷键。如果你确认快捷键没有被禁,可以省略这一步,在第3步直接按Ctrl+N键。
- 打开电子书或IE,进入引用了需要抓取的css、js、Flash等文件的页面。注意这里必须是真正的页面,不能是frame。后面会谈到如何判断frame及如何进入frame页面。
- 将CtrlN的“快捷键行为”设置为“弹出新窗口”,然后用鼠标在欲抓取的网页上点一下,再按下Ctrl+N键,弹出新的IE窗口,里面显示的内容与欲抓取的页面内容相同,地址栏上显示有页面的URL。
- 在弹出的IE窗口中,根据需要将对应的JavaScript代码(后面会给出)复制、粘贴到地址栏上,然后按回车键即可。
对于IE 6,第一次运行JavaScript代码可能会在地址栏下弹出一个黄条,提示这段代码被阻止运行,点一下黄条,选择“允许阻止的内容”,然后再重复步骤3、4,即可看到结果。
JavaScript本身提供了获取外部css文件内容的接口,因此在前述一般步骤的步骤4中,将下面内容复制、粘贴到IE地址栏上,然后按回车键即可看到内容:
javascript:str='';c=document.styleSheets;for(i=0;i<c.length;i++){o=c[i];if (o.href=='')continue;str+='========== ';str+=o.href;str+='<br><xmp>\n';str+=o.cssText;str+='</xmp><br><br>\n';};document.write(str);
如果当前HTML页面没有链接到外部css文件,则步骤4完成后无反应或显示一个空页,这时可以检查一下页面的HTML源代码进行确认。如果当前页面链接了多个css文件,所有css文件内容都会显示出来,格式经过IE排版后可能和原始css代码不同,但是效果绝对相同。如果只显示出css文件的文件名,下面无内容,则说明E书没有把这个css打包进去。
对于某些电子书,也可以试试下面这段代码:
javascript:str='<HTML><HEAD><BASE HREF="';str+=document.URL;str+='"></HEAD><BODY><br>\n';c=document.styleSheets;for(i=0;i<c.length;i++){o=c[i];if (o.src=='')continue;str+='<a href="';str+=o.href;str+='">';str+=o.href;str+='</a><br>\n';};str+='</BODY></HTML>';document.write(str);
这段代码自动对网页进行检查,如果网页中嵌入了css文件,则自动显示出css文件的下载链接,否则显示一个空页或无反应。在链接上点鼠标右键再选“目标另存为”菜单,即可将文件保存到硬盘上。如果不能保存,可将js文件的URL复制到地址栏上,然后按回车试试。不过如果注册表项HKEY_CLASSES_ROOT\CSSfile\shell下面有open、edit等子项,则获得的css代码会直接在open或edit子项指定的程序中打开而不是提示存盘。这种方法的适用范围远远不如前面直接显示的方法,不是所有电子书都能用的,但只要能用,得到的绝对是原汁原味的css代码。
JavaScript没有提供获取js文件内容的接口,因此首先要对注册表进行改造:运行regedit,定位到HKEY_CLASSES_ROOT\.js,在它下面增加两个字符串类型的值:
Content Type=application/x-javascript
PerceivedType=text
如果修改的时候不放心,可以参考HKEY_CLASSES_ROOT\.css的缺省设置,它们只是Content Type的值不同。注册表改造是一次性的工作,改完就不用再动。
在改造完成后,用CtrlN抓取js文件的步骤与前述一般步骤相同,在步骤4中,将下面内容复制、粘贴到地址栏上,然后按回车键即可看到内容:
javascript:str='<HTML><HEAD><BASE HREF="';str+=document.URL;str+='"></HEAD><BODY><br>\n';c=document.scripts;for(i=0;i<c.length;i++){o=c[i];if (o.src=='')continue;str+='<a href="';str+=o.src;str+='">';str+=o.src;str+='</a><br>\n';};str+='</BODY></HTML>';document.write(str);
这段代码自动对网页进行检查,如果网页中嵌入了js文件,则自动显示出js文件的下载链接,否则显示一个空页或无反应。在链接上点鼠标右键再选“目标另存为”菜单,或直接点链接;即可将文件保存到硬盘上。如果不能保存,请先确认是否已经按照上面说的方法对注册表进行过设置;如果还不行,可以将js文件的URL复制到地址栏上,然后按回车试试。
比较怪异的是用eBook Workshop做的E书(页面URL以ada99:开头),在地址栏上敲入js文件的URL然后回车,会直接显示出js文件内容及其执行结果,需要点“查看->源文件”菜单才可以获得原始js文件代码。不过这种书一般都用unEbookWorkshop反编译了吧?
对于Flash这种嵌入对象的文件,直接下载就可以,因此在前述一般步骤的步骤4中,将下面内容复制、粘贴到地址栏上,然后按回车键即可看到内容:
javascript:str='<HTML><HEAD><BASE HREF="';str+=document.URL;str+='"></HEAD><BODY><br>\n';c=document.all;for(i=0;i<c.length;i++){o=c[i];if(o.tagName!="OBJECT")continue;sih=o.innerHTML;nd=document.createDocumentFragment();nd.appendChild(document.createElement('<bod></body>'));nd.firstChild.outerHTML=sih;no=document.createElement(nd.firstChild.outerHTML);document.body.appendChild(no);str+='<a href="';str+=no.src;str+='">';str+=no.src;str+='</a><br>\n';};str+='</BODY></HTML>';document.write(str);
这段代码自动对网页进行检查,如果网页中嵌入了Flash对象,则自动显示出swf文件的下载链接,否则显示一个空页或无反应。在链接上点鼠标右键,选“目标另存为”,即可将文件保存到硬盘上。如果直接点击链接,则会显示出Flash画面。
我经常看到有人问:“怎样抓取网页上的漂亮Flash?”,其实答案就是这么简单,平时上网俺也经常用这段代码抓Flash,不过需要注意:如果页面镶嵌在frame中,则需要突破frame进入真正的页面中才能使用这段代码。另外这段代码使用了createDocumentFragment方法,只能在IE 6上运行。
现在还有一种很极端的电子书:整本书只有一个网页,里面嵌入了一个Flash文件作为目录,点击Flash中的链接,则转入其它Flash文件,即真正的内容藏在一堆Flash文件里。对于这种电子书,用上面的代码一次只能抓到一个Flash,需要逐步点进去才能抓全,有的甚至要用flasm反编译出抓到的Flash文件的运行脚本,再从脚本中找出它所链接的其它Flash文件的文件名(俺都是很卑鄙地直接搜索.swf),然后将文件名转成绝对URL,即可生成下载链接。例如已知某Flash文件的绝对URL为http://ebook/pic.swf,则用下面的代码可以单独下载此文件:
javascript:document.write('<a href="http://ebook/pic.swf">右键另存为</a>');
这种方法每次都要改URL,当然比前面说的方法麻烦,但是有时候也只能用这种方法。顺带一提,flasm还真是个好东西,某些Flash文件在脚本中限制该文件只能在网络上播放,不能从本地硬盘播放,也可以用它去除这种限制。
背景音乐文件可以象Flash一样直接下载,因此在前述一般步骤的步骤4中,将下面内容复制、粘贴到地址栏上,然后按回车键即可看到内容:
javascript:str='<HTML><HEAD><BASE HREF="';str+=document.URL;str+='"></HEAD><BODY><br>\n';c=document.all;for(i=0;i<c.length;i++){o=c[i];if(o.tagName!="BGSOUND")continue;str+='<a href="';str+=o.src;str+='">';str+=o.src;str+='</a><br>\n';};str+='</BODY></HTML>';document.write(str);
这段代码自动对网页进行检查,如果嵌入了背景音乐,则自动显示出背景音乐的下载链接,否则显示一个空页或无反应。在链接上点鼠标右键,选“目标另存为”,即可将文件保存到硬盘上。
注意背景音乐一般隐藏在frame中(否则一换页面音乐就被打断了),如果弹出的页面包含frame,而不是真正包含背景音乐链接的页面,就会抓不到。这时还需要按后面说的步骤进入frame中的页面。
另外有些E书为了避免单调,会一次打包进去几个midi文件,每次运行的时候随机选择一个作为背景音乐。对于这样的E书,用上面的代码只能抓到当前背景音乐。如果想抓全部,只能自己对网页源代码进行分析,组合出全部背景音乐的URL,然后在地址栏上输入生成下载链接的JavaScript代码再回车,一次下载一个。注意在下载链接上也只能点右键后选“目标另存为”,不能直接点链接。如果实在没有本事对网页源代码进行分析,只能多运行几回、多抓几回了,正所谓“落后就要挨打”。示例:已知某音乐文件的绝对URL为http://ebook/1.mid,则生成下载链接的代码为:
javascript:document.write('<a href="http://ebook/1.mid">右键另存为</a>');
在前述一般步骤的步骤4中,将下面内容复制、粘贴到地址栏上,然后按回车键即可看到内容:
javascript:z=1;strUrl='';str='';function getImg(){if(strUrl!=''){str+=(z++);str+='. <IMG SRC="';str+=strUrl;str+='"><br><br>\n';};};c=document.images;for(i=0;i<c.length;i++){o=c[i];strUrl=o.src;getImg();};strUrl=document.body.background;getImg();c=document.all;for(i=0;i<c.length;i++){o=c[i];if(o.tagName=='TABLE'||o.tagName=='TD'){strUrl=o.background;getImg();};if(o.tagName=='AREA'){strUrl=o.href;getImg();};};document.write(str);
上面这段代码会把网页中能够找到的图片全部顺序显示出来。如果觉得图片太多看起来不方便,或有某些小图片看不清,也可以用下面这段代码显示图片链接,点击链接才显示图片:
javascript:z=1;strUrl='';str='';function getImg(){if(strUrl!=''){str+=(z++);str+='. <a href="';str+=strUrl;str+='">';str+=strUrl;str+='</a><br>\n';};};c=document.images;for(i=0;i<c.length;i++){o=c[i];strUrl=o.src;getImg();};strUrl=document.body.background;getImg();c=document.all;for(i=0;i<c.length;i++){o=c[i];if(o.tagName=='TABLE'||o.tagName=='TD'){strUrl=o.background;getImg();};if(o.tagName=='AREA'){strUrl=o.href;getImg();};};document.write(str);
由于代码限制,隐藏在页面js、css代码中的图片用上面的两段代码不能抓取,这时只能自己手工对HTML代码进行分析,在地址栏上直接输入图片的绝对URL再回车,也能显示出图片。
另外由于javascript协议插件的能力限制,上面两段代码都没有剔除重复链接,所以如果用这两段代码去抓BBS页面上的图,看到一大堆相同的图片时请不要诧异。
在图片或链接显示出来后,只有极少数E书中的图片可以直接另存为原始格式,绝大多数只能获取解码成Bitmap后的图片,方法为:在图片(注意是图片,不能是链接,链接必须点进去显示出图片)上点右键,选“图片另存为”菜单,即可将图片保存成bmp文件,文件名缺省是“无标题.bmp”,需要手工改名。如果URL中指定的文件不是bmp,而是jpg、gif或png等,则还需要用ACDSee等软件将保存下来的bmp转换成要求的格式。jpg还好说,gif、png的透明色需要手工处理,动画gif干脆就不要想了。
注意:如果只是对文件进行改名,没有对文件格式进行转换,在IE中将会显示不出图片。
平时上网的时候,也可以用上面的代码抓取所浏览网页的背景图片,这个时候选“图片另存为”,一般都能保存成原始格式。
从上面的叙述可以看出,在不使用IE内部接口的情况下,抓取图片可能是最麻烦,但效果又最差的一件苦差使。记得当年我就是因此一怒之下开始咬牙分析IE内核源代码的,还好最后终于获得了回报。不知道在看了上面的说明后,会不会有人血性大发,也走上当年我那条路?嘿嘿嘿……
上面给出的所有JavaScript代码都是针对当前页面的,也就是说,只有当前页面中真的包含音乐文件、Flash文件,才能抓到所需的文件。如果是frame,就必须进入frame中的页面,才能抓取。
检测当前页面是否是frame,最简单的办法就是按前述一般步骤进行操作,然后在步骤4中,将下面内容复制、粘贴到地址栏上,然后按回车键:
javascript:str='<HTML><HEAD><BASE HREF="';str+=document.URL;str+='"></HEAD><BODY><br>\n';c=document.all;for(i=0;i<c.length;i++){o=c[i];if(o.tagName!='IFRAME'&&o.tagName!='FRAME')continue;str+=o.tagName;str+=' : <a href="';str+=o.src;str+='">';if(o.name=='')str+=o.src;else str+=o.name;str+='</a><br>\n';};str+='</BODY></HTML>';document.write(str);
这段代码自动对网页进行检查,如果嵌入了frame(包括iframe),则自动显示出frame中的页面链接,否则显示一个空页或无反应。直接点击链接,即可进入相应的页面。
为了保证通用性,上面的代码只对第一层frame进行检查,这对iframe来说问题不大,因为不会有几个正常人会去玩嵌套iframe;但对于普通frame来说,嵌套的可能性还是很大的,而上面的代码需要一层层点进去才能见到嵌套frame,未免有点麻烦。解决的办法就是:如果用上面代码显示的全是FRAME,没有IFRAME,则可以用下面的代码显示全部嵌套frame:
javascript:str='';function getFrame(c,i,j){for(i=0;i<c.length;i++){o=c[i];for(k=0;k<j;k++)str+=' ';str+='<a href="';str+=o.location;str+='">';if(o.name!='')str+=o.name;else str+=o.location;str+='</a><br>\n';no=o.document.frames;if(no.length>0)getFrame(no,0,j+1)};};getFrame(document.frames,0,0);document.write(str);
这段代码自动对网页进行检查,显示出嵌套frame中所有页面的链接及嵌套关系,没有frame则显示一个空页或无反应。直接点击链接,即可进入相应的页面。注意如果页面中含有iframe,则上面的代码可能会出错,所以才要先用第一段代码检查一下有没有iframe。
如果网页中采用了js代码对frame进行检测,导致网页不能脱离frame运行,则为了获得嵌入frame页面中的内容,可以在用上面的代码显示出frame页面链接后,直接在页面链接上点右键选“目标另存为”,保存出HTML代码后再手工编辑或用TextForever等工具辅助编辑。
miniKillEBook v1.04以前的版本存在一个疏忽:我光想到处理FRAME,忘记处理IFRAME,因此在某些人中开始流传这样一种说法:将网页嵌入IFRAME,即可避免被miniKillEBook反编译。在v1.04出来之后,这种说法就真的只能成为传说了。
Q:如果按下Ctrl+N键后,弹出的IE窗口没有菜单、地址栏,怎么办?
A:从CtrlN ver 1.03开始,提供一个可以打开/关闭的“高级界面”,通过里面的“Script命令”功能,可以直接将要执行的JavaScript代码推送到IE窗口中执行,不用再在地址栏输入。
Q:如果E书起来后禁止了Windows的复制、粘贴功能,上面的js代码好长,不想一个字符一个字符敲,怎么办?
A:从CtrlN ver 1.03开始,提供一个可以打开/关闭的“高级界面”,通过里面的“Script命令”功能,可以直接将要执行的JavaScript代码或URL推送到IE窗口中执行,不用再在地址栏输入。如果您写了自己的JavaScript代码,也可以将它加到CtrlN.spt文件(纯文本文件)中,这样以后可以在Script命令选择窗口中直接选择。
附录 版本更新记录
Version 1.01
按照CtrlN ver 1.03的新增功能,对文档进行了修订。