Java爬虫实战(二):抓取一个视频网站上2015年所有电影的下载链接

简介:

一 原理简介

       其实原理都跟第一篇文章差不多,不同的是鉴于这个网站的分类列表实在太多,如果不对这些标签加以取舍的话,需要花费的时间难以想象

wKiom1aEkt2Q8pl6AAIbgtJguRY014.png

 分类链接和标签链接都不要,不通过这些链接去爬取其他页面,只通过页底的所有类型电影的分页去获取其他页面的电影列表即可。同时,对于电影详情页面,仅仅只是抓取其中的电影标题和迅雷下载链接,并不进行深层次的爬行,详情页面的一些推荐电影等链接通通不要。

wKiom1aEkynSTrpPAAIy-OrLs0k412.png

       最后就是将所有获取到的电影的下载链接保存在videoLinkMap这个集合中,通过遍历这个集合将数据保存到MySQL里

注:如果对原理还是不够清晰的话,推荐看我的上一篇文章:http://www.zifangsky.cn/2015/12/java爬虫实战(一):抓取一个网站上的全部链接/

二 代码实现

       实现原理已经在上面说了,并且代码中有详细注释,因此这里就不多说了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
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 ;
     }
     
}

注:如果想要实现抓取其他网站的一些指定内容的话,需要将其中的一些正则表达式根据实际情况进行合理修改

三 测试效果

wKioL1aEk5LiQA3pAAFZpcGgbdU210.png

wKioL1aEk5Pz7FDYAAFQcrEAnqY514.png



本文转自 pangfc 51CTO博客,原文链接:http://blog.51cto.com/983836259/1730243,如需转载请自行联系原作者

相关文章
|
5月前
|
Java 开发工具
【Azure Storage Account】Java Code访问Storage Account File Share的上传和下载代码示例
本文介绍如何使用Java通过azure-storage-file-share SDK实现Azure文件共享的上传下载。包含依赖引入、客户端创建及完整示例代码,助你快速集成Azure File Share功能。
459 6
|
5月前
|
安全 Java 开发者
告别NullPointerException:Java Optional实战指南
告别NullPointerException:Java Optional实战指南
324 119
|
6月前
|
存储 前端开发 Java
【JAVA】Java 项目实战之 Java Web 在线商城项目开发实战指南
本文介绍基于Java Web的在线商城技术方案与实现,涵盖三层架构设计、MySQL数据库建模及核心功能开发。通过Spring MVC + MyBatis + Thymeleaf实现商品展示、购物车等模块,提供完整代码示例,助力掌握Java Web项目实战技能。(238字)
774 0
|
6月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
553 100
|
6月前
|
人工智能 Java API
Java AI智能体实战:使用LangChain4j构建能使用工具的AI助手
随着AI技术的发展,AI智能体(Agent)能够通过使用工具来执行复杂任务,从而大幅扩展其能力边界。本文介绍如何在Java中使用LangChain4j框架构建一个能够使用外部工具的AI智能体。我们将通过一个具体示例——一个能获取天气信息和执行数学计算的AI助手,详细讲解如何定义工具、创建智能体并处理执行流程。本文包含完整的代码示例和架构说明,帮助Java开发者快速上手AI智能体的开发。
2453 8
|
6月前
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
1087 12
|
5月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
11月前
|
数据采集 测试技术 C++
无headers爬虫 vs 带headers爬虫:Python性能对比
无headers爬虫 vs 带headers爬虫:Python性能对比
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
636 6
|
11月前
|
数据采集 存储 监控
Python 原生爬虫教程:网络爬虫的基本概念和认知
网络爬虫是一种自动抓取互联网信息的程序,广泛应用于搜索引擎、数据采集、新闻聚合和价格监控等领域。其工作流程包括 URL 调度、HTTP 请求、页面下载、解析、数据存储及新 URL 发现。Python 因其丰富的库(如 requests、BeautifulSoup、Scrapy)和简洁语法成为爬虫开发的首选语言。然而,在使用爬虫时需注意法律与道德问题,例如遵守 robots.txt 规则、控制请求频率以及合法使用数据,以确保爬虫技术健康有序发展。
1498 31