/********************************************************************************************
* author:conowen@大钟
* E-mail:[email protected]
* http://blog.csdn.net/conowen
* 注:本文为原创,仅作为学习交流使用,转载请标明作者及出处。
********************************************************************************************/
一: 项目目的
最近项目设计到网联网视频采集聚合,写了一个关于互联网视频的信息爬虫的小程序,以youku在线视频网站为例,实现一个java平台下的应用程序,动态抓取互联网视频信息保存到本地xml文件,构建一个多媒体播放源中心。
二:项目第三方库:
1、jsoup (HTML代码解析器)
jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法来取出和操作数据。
jsoup的主要功能如下:
·从一个URL,文件或字符串中解析HTML;
·使用DOM或CSS选择器来查找、取出数据;
·可操作HTML元素、属性、文本;
jsoup是基于MIT协议发布的,可放心使用于商业项目。
官方地址:http://jsoup.org/
2、jdom (XML构建于解析工具)
通过jdom,可以很容易地构建符合规范的xml文件,并且,jdom提供对xml文件的快速解析。
官方地址:http://jdom.org/
三:开发大体过程:
如youku(优酷)在线视频播放网站,本身就做了互联网视频聚合,就是旗下的soku,以下就已soku为例
如电视剧所对应的url地址为:http://www.soku.com/channel/teleplaylist_0_0_0_1_1.html
通过浏览器查看这个页面的HTML代码分析可知
获取视频信息:
1、jsoup解析演示:
获取一个页面的内容,可以采用以下方式
Document doc = Jsoup.connect("http://example.com/").get();
当然,也可以设置一些连接参数,如浏览器userAgent
,超时时间,页面内存大小等等。
对页面的解析就如同对xml解析一样,很简单。通过tab或者class标签就可以获取相应的内容了。
2、jsoup抓取youku优酷视频信息
public void getVideoInfo(String pageUrl) {// 一页调用一次
try {
doc = Jsoup.connect(pageUrl).maxBodySize(1024 * 1024 * 10)
.timeout(6000).get();
// Added a maximum body response size to Jsoup.Connection, to
// prevent running out of memory when trying to read extremely
// large
// documents. The default is 1MB.
} catch (IOException e) {
// TODO Auto-generated catch block
getVideoInfo(pageUrl);
System.out.println("connect error");
e.printStackTrace();
}
divs_info = doc.getElementsByClass("p_link");// 视频专辑url,如电视剧
if (divs_info != null) {
if (divs_info.size() <= 0) {
divs_info = doc.getElementsByClass("v_link");// 视频播放url,如资讯
}
urls = divs_info.select("a[href]");
if (null != urls) {
int i = 0;
for (Element urlElement : urls) {
videoTitles.add(urlElement.attr("title"));
videoUrl.add(urlElement.attr("abs:href"));
i++;
}
}
}
divs_thumbs = doc.getElementsByClass("p_thumb");// 获取专辑图片
if (divs_thumbs != null) {
thumbs = divs_thumbs.select("img[original]");
if (thumbs.size() <= 0) {
divs_thumbs = doc.getElementsByClass("v_thumb");
thumbs = divs_thumbs.select("img[original]");
}
if (null != thumbs) {
int i = 0;
for (Element thumb : thumbs) {
videoThumbUrls.add(thumb.attr("abs:original"));
i++;
}
}
}
divs_pgm_source = doc.getElementsByClass("pgm-source");// 获取更新情况
// divs_pgm_source.select(query)
if (divs_pgm_source != null) {
for (Element thumb1 : divs_pgm_source) {
sourceId = thumb1.select("span");
sourceUrl = thumb1.select("a");
List videoSourceStatus = null;
List videoSourceUrl = null;
List videoSourceId = null;//保存获取的数据,以供构建xml文件
if (null != sourceId) {
videoSourceId = new ArrayList();
for (Element thumb2 : sourceId) {
videoSourceId.add(thumb2.attr("id"));
}
videoSourceIdList.add(videoSourceId);
}
if (null != sourceUrl) {
videoSourceStatus = new ArrayList();
for (Element thumb2 : sourceUrl) {
videoSourceStatus.add(thumb2.attr("status"));
}
videoSourceStatusList.add(videoSourceStatus);
}
if (null != sourceUrl) {
videoSourceUrl = new ArrayList();
for (Element thumb2 : sourceUrl) {
videoSourceUrl.add(thumb2.attr("href"));
}
videoSourceUrlList.add(videoSourceUrl);
}
}
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1、创建xml文件
xmlHelper.createXml(str, videoTitles, videoUrl, videoThumbUrls,
videoSourceIdList, videoSourceStatusList,
videoSourceUrlList, pageNum); // 创建xml
2、创建xml文件过程
public void createXml(String fileName, List videoTitles,
List videoUrl, List videoThumbUrls,
List> videoSourceIdList,
List> videoSourceStatusList,
List> videoSourceUrlList, int pageNum) {
// 创建根节点
Element root = new Element("videoInfo");
// 创建每一页的节点
Element pageElement = new Element("page");
//设置页码
pageElement.setAttribute("page", "" + pageNum);
Document Doc = new Document(root);
for (int i = 0; i < videoTitles.size(); i++) {
// 创建节点 videoId
Element VideoIdElement = new Element("videoId");
// 给 videoId 节点添加属性 id;
VideoIdElement.setAttribute("id", ""
+ (i + 1 + (pageNum - 1) * videoTitles.size()));
// 填写视频信息的值
VideoIdElement.addContent(new Element("videoTitle")
.setText(videoTitles.get(i)));
VideoIdElement.addContent(new Element("videoUrl").setText(videoUrl
.get(i)));
VideoIdElement.addContent(new Element("videoThumbUrls")
.setText(videoThumbUrls.get(i)));
for (int j = 0; j < videoSourceIdList.get(i).size(); j++) {
Element sourceElement = new Element("source");
sourceElement.setAttribute("id", ""
+ videoSourceIdList.get(i).get(j));
sourceElement.setAttribute("status", ""
+ videoSourceStatusList.get(i).get(j));
sourceElement.setAttribute("url", ""
+ videoSourceUrlList.get(i).get(j));
VideoIdElement.addContent(sourceElement);
}
// 添加每一个子视频到每一页上面
pageElement.addContent(VideoIdElement);
}
// 添加每一页的视频到根节点上面
root.addContent(pageElement);
Format format = Format.getCompactFormat();
format.setEncoding("utf-8"); // setEncoding 设置编码
format.setIndent(" ");
XMLOutputter XMLOut = new XMLOutputter(format);
try {
XMLOut.output(Doc, new FileOutputStream(fileName));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Format format = Format.getCompactFormat();
format.setEncoding("utf-8");
format.setIndent(" ");
构建出来的xml文件如下
来自星星的你
http://www.soku.com/detail/show/XMTEyNDE0NA==
http://g3.ykimg.com/0516000052AD289A675839358A07B6AA
食为奴
http://www.soku.com/detail/show/XMTA5MTQ1Mg==
http://g4.ykimg.com/0516000052F4A2C56758390A8D0C4E55
屌丝男士
http://www.soku.com/detail/show/XMTA4MzkwNA==
http://g1.ykimg.com/05160000519310F4670C4A1AE002FEB1
屌丝男士 第三季
http://www.soku.com/detail/show/XMTE0NzU2OA==
http://g4.ykimg.com/051600005305D18E6758397D8206CC34