慕课网视频解析源码分析

来源:互联网 发布:阿里云重装系统在哪里 编辑:程序博客网 时间:2024/06/05 21:52


本源码是参考网上给出的源码加以修改而来,并在eclipse上多次成功下载视频

参考:http://e12e.com/archives/

下面一步一步实现其过程

1.导入jar包

要用到的两个jar包:Json.jar,Jsoup.jar   (至于版本号,应该是随便下载一个均可)


2.慕课网HTML网页网址分析(在慕课网下右键查看源码可以看到HTML)

因为是对本HTML解析,所以了解其结构很重要。

程序中获取大课程名称是通过寻找<h2>标签获得的,因为在learn下的界面中只有课程名是h2标签

title=doc.getElementsByTag("h2").html();
------------------------------
获取每一个节课的数组串,以及后面的获取子节的标题等等均是在HTML的基础上

-

3.建立连接,获取HTML的Document,这里的classNo对应的课程标号,使用Jsoup解析,并获取含有video的<a>元素。

关于File文件路径写法的问题可参考:http://blog.csdn.net/molu_chase/article/details/52314952

关于Jsoup的知识参考:http://blog.csdn.net/molu_chase/article/details/52318572

                // Jsoup的Document对象Document doc = null;String title;String savePath;String[] videoNos;String videoName;int classNo = 372;try {// 获取Jsoup连接Connection con = Jsoup.connect("http://www.imooc.com/learn/" + classNo);// 获取Document对象doc = con.get();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 获取标签为h2的元素,并获取HTML代码,这个是整个课程的名称title = doc.getElementsByTag("h2").html();title = classNo + "_" + title;// 地址的写法,根目录用\\,子目录用/savePath = "F:\\imooc/Android/" + title + "/";File file = new File(savePath);System.out.println(title);// 这个用法还没找到,我的理解是查找标签a中含有video的标签元素Elements videos = doc.select(".video a");
-----------------------------------------------------------------------------------
4.对子元素进行操作,下面代码包括了全部的实现函数,后面会一个个分析

for语句对在learn网址下的获得的子节进行解析

videoName的值是通过element.text()获取的文本进行修改的,把不需要的部分去掉


               // 选择高清int videoDef = 1;for (Element element : videos) {videoNos = element.attr("href").split("/");if (videoNos[0].equals("")) {// System.out.println(videoNos[2]);DealChildrenHtml.doGetFile(videoNos[2]);// 获取元素的文本videoName = element.text();videoName = videoName.substring(0, videoName.length() - 4).trim();videoName = videoName.replace(" ", "").replace("(", "").replace(")", "").replace(":", "").replace("-","_");// 获取视频下载地址DownLoadVideo.getVideoURL(videoNos[2], videoDef, videoName, title);}}DownloadCourse.getCourseURLAndName(set, title);System.out.println("下载完毕!");
-------------------------------------------------------------
5.doGetFile()

doGetFile()将每节课的课件存到Set集合中,,存入的是网址,避免重复

public class DealChildrenHtml {/** * 下载课件,即每次打开一个video视频的网页中显示的课件 *  * @param videoNo * videoNo是访问网址video后面的数字字符串 * 例:144,则访问的视频地址为http://www.imooc.com/video/144 * @param title * title是课程名 */public static void doGetFile(String videoNo) {// TODO Auto-generated method stubDocument document=null;String filePath;String[] s;String lastName;String fileName;//System.out.println("start"+videoNo);try {document=Jsoup.connect("http://www.imooc.com/video/"+videoNo).timeout(10*1000).get();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}Elements efilePaths=document.select(".coursedownload a");//System.out.println("---------------------------------------");for (Element element : efilePaths) {filePath=element.attr("href");/* * Java中String.split方法传入的参数是一个RegularExpr,是一个正则表达式。             * 在正则表达式中,点号表示所有字符的意思,所以需要用\来转义。             * 则\\.表示的是\. 即. */s=filePath.split("\\.");lastName=s[s.length-1];fileName=element.attr("title");//lastName是通过.分解后的最后一个部分,课件是直接放在HTML中的,即最后一个部分就是文件后缀名//将课件的地址等信息添加到set集合中Main.set.add(filePath+"!"+fileName+"."+lastName);//downLoadFromUrl(filePath, fileName + "." + lastName,//"./download/" + className + "/课程资料/");}}}

-----------------------------------------------------

6.getVideoURL()

getVideoURL()是获取的视频的下载地址,将地址传给downloadByURLAndName2()

这里用到了之前定义的VideoDef,因为解析的Json中有三个视频文件地址,分别是L,M,H,我这里就选M了,超清可以将VideoDef改为2

至于其中Json的操作可以访问网址查看Json代码

也可以参考http://blog.csdn.net/molu_chase/article/details/52319718

public class DownLoadVideo {/** * Json处理获取Video的URL *  * @param videoNo * @param videoDef * @param videoName */public static void getVideoURL(String videoNo,int videoDef,String videoName,String title){Document jsonDoc = null;String jsonData;JSONObject jsonObject;JSONArray mpath;try {//获取Json格式的网页DocumentjsonDoc=Jsoup.connect("http://www.imooc.com/course/ajaxmediainfo/?mid="+ videoNo + "&mode=flash").timeout(10000).get();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}//这个Document就是个Json代码jsonData=jsonDoc.text();//通过Json字符串创建Json对象jsonObject=new JSONObject(jsonData)mpath=jsonObject.getJSONObject("data").getJSONObject("result").getJSONArray("mpath");String downloadPath=mpath.getString(videoDef).toString().trim();downloadVideoByURL(downloadPath,videoName,title);}private static void downloadVideoByURL(String downloadPath, String videoName,String title) {// TODO Auto-generated method stubDownloadCourse.downloadByURLAndName2(downloadPath, videoName+".mp4", title);}}
-
---------------------------------------

7.getCourseURLAndName()

getCourseURLAndName()通过Set中的网址来下载课件,同样,下载的操作交给downloadByURLAndName2()

public static void getCourseURLAndName(Set<String> set,String title){//System.out.println("getCourseUrlAndName");for (String string : set) {//在传给Set的string时,以!为界将网址和filename分开了String[] path=string.split("!");String url=path[0];String fileName=path[1];//System.out.println(url+"  "+fileName);downloadByURLAndName2(url, fileName,title);}}

--------------------------------

8.downloadByURLAndName2()

下载文件,之前用字符流接收,然后用FileWriter写入,虽然下载了,但是打不开,转码也无济于事,虽然下载的大小没变。

见http://blog.csdn.net/molu_chase/article/details/52321851

不过这种方式下载是最快的,相比于用缓冲流和单个字节流

public static void downloadByURLAndName2(String url,String fileName,String title){//System.out.println("downloadByURLAndName");long startTime;long bytes;startTime=System.currentTimeMillis();bytes=0;try {URL httpUrl=new URL(url);HttpURLConnection con=(HttpURLConnection)httpUrl.openConnection();InputStream in=con.getInputStream();new File("F:\\imooc/Android/"+title+"/").mkdir();File file=new File("F:\\imooc/Android/"+title+"/"+fileName);FileOutputStream fos=new FileOutputStream(file);byte[] b=new byte[1024];int len;while((len=in.read(b))!=-1){bytes+=len;fos.write(b, 0, len);}fos.close();in.close();System.out.println(fileName+"下载完成");long endTime=System.currentTimeMillis();long bp=(bytes/((endTime-startTime)));Main.bps.add(bp);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}




源码地址:https://github.com/moluchase/JavaResolveHTML

整理了一下,做了一个jar可执行文件:https://github.com/moluchase/javaResolveHtml2

1 0