Java爬虫抓取视频网站下载链接
程序员文章站
2024-03-12 10:26:56
本篇文章抓取目标网站的链接的基础上,进一步提高难度,抓取目标页面上我们所需要的内容并保存在数据库中。这里的测试案例选用了一个我常用的电影下载网站()。本来是想抓取网站上的所...
本篇文章抓取目标网站的链接的基础上,进一步提高难度,抓取目标页面上我们所需要的内容并保存在数据库中。这里的测试案例选用了一个我常用的电影下载网站()。本来是想抓取网站上的所有电影的下载链接,后来感觉需要的时间太长,因此改成了抓取2015年电影的下载链接。
一 原理简介
其实原理都跟第一篇文章差不多,不同的是鉴于这个网站的分类列表实在太多,如果不对这些标签加以取舍的话,需要花费的时间难以想象。
分类链接和标签链接都不要,不通过这些链接去爬取其他页面,只通过页底的所有类型电影的分页去获取其他页面的电影列表即可。同时,对于电影详情页面,仅仅只是抓取其中的电影标题和迅雷下载链接,并不进行深层次的爬行,详情页面的一些推荐电影等链接通通不要。
最后就是将所有获取到的电影的下载链接保存在videolinkmap这个集合中,通过遍历这个集合将数据保存到mysql里
二 代码实现
实现原理已经在上面说了,并且代码中有详细注释,因此这里就不多说了,代码如下:
package action; import java.io.bufferedreader; import java.io.ioexception; import java.io.inputstream; import java.io.inputstreamreader; import java.net.httpurlconnection; import java.net.malformedurlexception; import java.net.url; import java.sql.connection; import java.sql.preparedstatement; import java.sql.sqlexception; import java.util.linkedhashmap; import java.util.map; import java.util.regex.matcher; import java.util.regex.pattern; public class videolinkgrab { public static void main(string[] args) { videolinkgrab videolinkgrab = new videolinkgrab(); videolinkgrab.savedata("http://www.80s.la/movie/list/-2015----p"); } /** * 将获取到的数据保存在数据库中 * * @param baseurl * 爬虫起点 * @return null * */ public void savedata(string baseurl) { map<string, boolean> oldmap = new linkedhashmap<string, boolean>(); // 存储链接-是否被遍历 map<string, string> videolinkmap = new linkedhashmap<string, string>(); // 视频下载链接 string oldlinkhost = ""; // host pattern p = pattern.compile("(https?://)?[^/\\s]*"); // 比如:http://www.zifangsky.cn matcher m = p.matcher(baseurl); if (m.find()) { oldlinkhost = m.group(); } oldmap.put(baseurl, false); videolinkmap = crawllinks(oldlinkhost, oldmap); // 遍历,然后将数据保存在数据库中 try { connection connection = jdbcdemo.getconnection(); for (map.entry<string, string> mapping : videolinkmap.entryset()) { preparedstatement pstatement = connection .preparestatement("insert into movie(moviename,movielink) values(?,?)"); pstatement.setstring(1, mapping.getkey()); pstatement.setstring(2, mapping.getvalue()); pstatement.executeupdate(); pstatement.close(); // system.out.println(mapping.getkey() + " : " + mapping.getvalue()); } connection.close(); } catch (sqlexception e) { e.printstacktrace(); } } /** * 抓取一个网站所有可以抓取的网页链接,在思路上使用了广度优先算法 对未遍历过的新链接不断发起get请求, 一直到遍历完整个集合都没能发现新的链接 * 则表示不能发现新的链接了,任务结束 * * 对一个链接发起请求时,对该网页用正则查找我们所需要的视频链接,找到后存入集合videolinkmap * * @param oldlinkhost * 域名,如:http://www.zifangsky.cn * @param oldmap * 待遍历的链接集合 * * @return 返回所有抓取到的视频下载链接集合 * */ private map<string, string> crawllinks(string oldlinkhost, map<string, boolean> oldmap) { map<string, boolean> newmap = new linkedhashmap<string, boolean>(); // 每次循环获取到的新链接 map<string, string> videolinkmap = new linkedhashmap<string, string>(); // 视频下载链接 string oldlink = ""; for (map.entry<string, boolean> mapping : oldmap.entryset()) { // system.out.println("link:" + mapping.getkey() + "--------check:" // + mapping.getvalue()); // 如果没有被遍历过 if (!mapping.getvalue()) { oldlink = mapping.getkey(); // 发起get请求 try { url url = new url(oldlink); httpurlconnection connection = (httpurlconnection) url .openconnection(); connection.setrequestmethod("get"); connection.setconnecttimeout(2500); connection.setreadtimeout(2500); if (connection.getresponsecode() == 200) { inputstream inputstream = connection.getinputstream(); bufferedreader reader = new bufferedreader( new inputstreamreader(inputstream, "utf-8")); string line = ""; pattern pattern = null; matcher matcher = null; //电影详情页面,取出其中的视频下载链接,不继续深入抓取其他页面 if(ismoviepage(oldlink)){ boolean checktitle = false; string title = ""; while ((line = reader.readline()) != null) { //取出页面中的视频标题 if(!checktitle){ pattern = pattern.compile("([^\\s]+).*?</title>"); matcher = pattern.matcher(line); if(matcher.find()){ title = matcher.group(1); checktitle = true; continue; } } // 取出页面中的视频下载链接 pattern = pattern .compile("(thunder:[^\"]+).*thunder[rr]es[tt]itle=\"[^\"]*\""); matcher = pattern.matcher(line); if (matcher.find()) { videolinkmap.put(title,matcher.group(1)); system.out.println("视频名称: " + title + " ------ 视频链接:" + matcher.group(1)); break; //当前页面已经检测完毕 } } } //电影列表页面 else if(checkurl(oldlink)){ while ((line = reader.readline()) != null) { pattern = pattern .compile("<a href=\"([^\"\\s]*)\""); matcher = pattern.matcher(line); while (matcher.find()) { string newlink = matcher.group(1).trim(); // 链接 // 判断获取到的链接是否以http开头 if (!newlink.startswith("http")) { if (newlink.startswith("/")) newlink = oldlinkhost + newlink; else newlink = oldlinkhost + "/" + newlink; } // 去除链接末尾的 / if (newlink.endswith("/")) newlink = newlink.substring(0, newlink.length() - 1); // 去重,并且丢弃其他网站的链接 if (!oldmap.containskey(newlink) && !newmap.containskey(newlink) && (checkurl(newlink) || ismoviepage(newlink))) { system.out.println("temp: " + newlink); newmap.put(newlink, false); } } } } reader.close(); inputstream.close(); } connection.disconnect(); } catch (malformedurlexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } try { thread.sleep(1000); } catch (interruptedexception e) { e.printstacktrace(); } oldmap.replace(oldlink, false, true); } } // 有新链接,继续遍历 if (!newmap.isempty()) { oldmap.putall(newmap); videolinkmap.putall(crawllinks(oldlinkhost, oldmap)); // 由于map的特性,不会导致出现重复的键值对 } return videolinkmap; } /** * 判断是否是2015年的电影列表页面 * @param url 待检查url * @return 状态 * */ public boolean checkurl(string url){ pattern pattern = pattern.compile("http://www.80s.la/movie/list/-2015----p\\d*"); matcher matcher = pattern.matcher(url); if(matcher.find()) return true; //2015年的列表 else return false; } /** * 判断页面是否是电影详情页面 * @param url 页面链接 * @return 状态 * */ public boolean ismoviepage(string url){ pattern pattern = pattern.compile("http://www.80s.la/movie/\\d+"); matcher matcher = pattern.matcher(url); if(matcher.find()) return true; //电影页面 else return false; } }
注:如果想要实现抓取其他网站的一些指定内容的话,需要将其中的一些正则表达式根据实际情况进行合理修改
三 测试效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。