首页>JAVA>正文

神了!用Java批量下载《神秘的程序员》漫画

时间:2018-01-12 16:16:05   来源:果冻虾仁   阅读:

上周看了西乔的博客“西乔的九卦”。 《神秘的程序员们》系列漫画感觉很喜欢,很搞笑。这些漫画经常出现在CSDN“程序员”杂志末页的,以前也看过一些。

 

后来就想下载下来,但是一张一张的点击右键“另存为”,还有很多时候要点击“下一页,”确实让人淡疼。就想着写个程序搞定,自认确实水平一般,查阅了很多资料后,终于搞定。。。
 

大体的下载过程就是从网页url不断获取html源码的字符串,遇到图片地址,就下载,遇到下一页的地址,就修改原来的url为下一页的url,然后重复上一过程。
 

1.下载网络图片

首先要解决的是根据url下载单个网络图片的问题。之前确实没有这方面的经验。于是就问度娘,百度多了好几份代码,大都下载的图片效果很差。后来终于找到一个可行的,在此感谢作者。http://www.open-open.com/lib/view/open1329995970842.html

先贴出作者原代码,最终还要修改

 

[java] view plain copy
  1. package action;  
  2.   
  3. import java.io.DataInputStream;  
  4. import java.io.DataOutputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.URL;  
  8.   
  9. public class Getpic {  
  10.     public Getpic() {  
  11.     }  
  12.   
  13.     public static boolean saveUrlAs(String fileUrl, String savePath)/* fileUrl网络资源地址 */  
  14.     {  
  15.   
  16.         try {  
  17.             /* 将网络资源地址传给,即赋值给url */  
  18.             URL url = new URL(fileUrl);  
  19.               
  20.             /* 此为联系获得网络资源的固定格式用法,以便后面的in变量获得url截取网络资源的输入流 */  
  21.             HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  22.             DataInputStream in = new DataInputStream(connection.getInputStream());  
  23.               
  24.             /* 此处也可用BufferedInputStream与BufferedOutputStream  需要保存的路径*/  
  25.             DataOutputStream out = new DataOutputStream(new FileOutputStream(savePath));  
  26.               
  27.               
  28.             /* 将参数savePath,即将截取的图片的存储在本地地址赋值给out输出流所指定的地址 */  
  29.             byte[] buffer = new byte[4096];  
  30.             int count = 0;  
  31.             while ((count = in.read(buffer)) > 0)/* 将输入流以字节的形式读取并写入buffer中 */  
  32.             {  
  33.                 out.write(buffer, 0, count);  
  34.             }  
  35.             out.close();/* 后面三行为关闭输入输出流以及网络资源的固定格式 */  
  36.             in.close();  
  37.             connection.disconnect();  
  38.             return true;/* 网络资源截取并存储本地成功返回true */  
  39.   
  40.         } catch (Exception e) {  
  41.             System.out.println(e + fileUrl + savePath);  
  42.             return false;  
  43.         }  
  44.     }  
  45.   
  46.     public static void main(String[] args) {  
  47.         Getpic pic = new Getpic();/* 创建实例 */  
  48.           
  49.         //需要下载的URL  
  50.         String photoUrl = "http://hiphotos.baidu.com/yanshennan/pic/item/03a505c8bcbaf6557f3e6f8a.jpg";  
  51.   
  52.         // 截取最后/后的字符串  
  53.         String fileName = photoUrl.substring(photoUrl.lastIndexOf("/"));  
  54.           
  55.         //图片保存路径  
  56.         String filePath = "E:";  
  57.           
  58.         /* 调用函数,并且进行传参 */  
  59.         boolean flag = pic.saveUrlAs(photoUrl, filePath + fileName);  
  60.           
  61.         System.out.println("Run ok!\n Get URL file " + flag);  
  62.         System.out.println(filePath);  
  63.         System.out.println(fileName);  
  64.     }  
  65.   
  66. }  

 

2.提取出图片URL

我们可以轻松的获得一个html网页的源代码,图片地址也包含其中,接下来要做的就是如何从这些html代码中分析出图片的网络地址。我想到的就是“正则表达式”,原来只是用正则表达式在android里面匹配过电话号码-_-#,正则表达式确实博大精深。。一时半会真的吃不透。。以后慢慢学习啦。

这里我们看一点西乔博客的html源码

 

[html] view plain copy
  1. <a href="http://blog.xiqiao.info/blogimg/programmers/53_run_result.gif">点击看大图</a></p>  
  2. <p style="text-align: center;"><a href="http://blog.xiqiao.info/blogimg/programmers/53_run_result.gif" target="_blank"><img title=" 运行结果——《神秘的程序员们》系列漫画" src="http://blog.xiqiao.info/blogimg/programmers/53_run_result_thumb.gif" alt=" 运行结果——《神秘的程序员们》系列漫画" /></a></p>  
其中包含有图片地址。用BufferedReader的readLine方法得到的是一行行的字符串,也就是遇到\r,\n结束的字符串,所以虽然下面那一行很长,但是也是只会得到一个字符串。

 

开始我的想法是截取第一段中的图片地址,但是后来发现问题,这段代码代表的是原网页中“点击看大图”的链接。而《神秘的程序员》系列博文里有的是没有这个“点击看大图”的文字链接。于是我就想截取下一段,字符串。

但是这段字符串包含两个图片网址,其中一个是高清大图,另一个是一般的大小。你或许会说那就下高清的吧,确实,但是有的博文图片偏偏是没有高清的,这样匹配起来又会出问题,或许你可以根据判断语句来区别对待,优先下载高清的,没有就下载普通的。但是我这里为了实现起来简单,就统一下载一般大小的图片了。

下面是我蛋疼的正则表达式,写法有很多。。

 

[java] view plain copy
  1. Pattern p1 = Pattern.compile(".*src.*[gif|jpg].*");  
匹配出来,还要再提取出来,正则应该也可以做到,但是我还是选择用字符串取子串的方法来写,更简单。

 

 

[java] view plain copy
  1. String line = inputLine.substring(inputLine.indexOf("src"),inputLine.lastIndexOf("\" alt"));  
  2. Url = line.substring(line.indexOf("http"));  

 

3.获取下一页

实际上漫画是在很多个网页中的。你看漫画的时候也要点击,下一页,下一页。就是网页上的“← Older Entries

原网页html代码

 

[html] view plain copy
  1. <ul class="navigation">  
  2.         <li class="left"><a href="http://blog.xiqiao.info/category/programmers/page/3" >← Older Entries</a></li>  
  3.     <li class="right"><a href="http://blog.xiqiao.info/category/programmers/" >Newer Entries →</a></li>  
  4. </ul>  
上面,是一个上一页,一个下一页。要找出他,同样使用正则匹配。我写的烂,大家可自由发挥。

 

 

[java] view plain copy
  1. Pattern p2 = Pattern.compile(".*<li class=\"left\"><a href=\"http://blog.xiqiao.info/category/programmers/page/.*");  
提取比较简单

 

 

[java] view plain copy
  1. Url = "http"+inputLine.substring(inputLine.indexOf(':'),inputLine.lastIndexOf('"'));  

 

4.完整代码

 

[java] view plain copy
  1. //package com.xiqiao;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.net.URL;  
  8. import java.net.URLConnection;  
  9. import java.util.regex.Matcher;  
  10. import java.util.regex.Pattern;  
  11.   
  12. import java.io.DataInputStream;  
  13. import java.io.DataOutputStream;  
  14. import java.io.FileOutputStream;  
  15. import java.net.HttpURLConnection;  
  16. /** 
  17.  * 上海尚学堂java培训组 shsxt.com
  18.  * @author guodongxiaren 
  19.  * 薇芯 java8733 获取更多技术文章资料
  20.  */  
  21. public class DownLoad {  
  22.   
  23.     private String path = "http://blog.xiqiao.info/category/programmers";  
  24.     private String filePath = "D:/day/net/pic";//可以改成你自己的路径,注意必须是已存在的路径  
  25.     private String fileName = null;  
  26.     private String Url = null;  
  27.     private Pattern p1 = Pattern.compile(".*src.*[gif|jpg].*");  
  28.     private Pattern p2 = Pattern.compile(".*<li class=\"left\"><a href=\"http://blog.xiqiao.info/category/programmers/page/.*");  
  29.       
  30.     public static void  main(String[]args)throws IOException{  
  31.     DownLoad ia = new DownLoad();  
  32.     ia.start();  
  33.     }  
  34. /** 
  35.  * 解析出图片下载地址及图片名称 
  36.  * @param inputLine 
  37.  */  
  38.     public void AddResolution(String inputLine)  
  39.     {  
  40.         String line = inputLine.substring(inputLine.indexOf("src"),inputLine.lastIndexOf("\" alt"));  
  41.         Url = line.substring(line.indexOf("http"));  
  42.         System.out.println(Url);  
  43.              //为了便于查看图片,我把所有图片都改成jpg。。因为gif图片经常会用浏览器打开-_-#  
  44.          fileName = Url.substring(Url.lastIndexOf("/"),Url.lastIndexOf("."))+".jpg";  
  45.     }  
  46.       
  47. /** 
  48.  * 开始下载 
  49.  * @throws IOException 
  50.  */  
  51.     public void start() throws IOException{  
  52.         URL name = new URL(path);  
  53.         URLConnection conn = name.openConnection();  
  54.         InputStream input = conn.getInputStream();  
  55.         InputStreamReader isr = new InputStreamReader(input);  
  56.         BufferedReader buffer = new BufferedReader(isr);  
  57.         String inputLine=null;  
  58.   
  59.         Getpic pic = new Getpic();  
  60.         while((inputLine=buffer.readLine())!=null){  
  61.             Matcher matcher1 = p1.matcher(inputLine);  
  62.             Matcher matcher2 = p2.matcher(inputLine);  
  63.             try{  
  64.             if(matcher1.matches()){  
  65.                 AddResolution(inputLine);  
  66.                 boolean flag = pic.saveUrlAs(Url, filePath + fileName);  
  67.           
  68.                 System.out.println("Get URL file " + flag);  
  69.                 System.out.println(filePath);  
  70.                 System.out.println(fileName+" save successful");  
  71.                 }  
  72.             }catch(StringIndexOutOfBoundsException e){}  
  73.             if(matcher2.matches()){  
  74.                  Url = "http"+inputLine.substring(inputLine.indexOf(':'),inputLine.lastIndexOf('"'));  
  75.                 name = new URL(Url);  
  76.                 conn = name.openConnection();  
  77.                 input = conn.getInputStream();  
  78.                 isr = new InputStreamReader(input);  
  79.                 buffer = new BufferedReader(isr);  
  80.             }  
  81.         }  
  82.         System.out.println("Successful");  
  83.     }  
  84.   
  85.   
  86. /** 
  87.  * 感谢这段代码原作者 
  88.  * @author http://www.open-open.com/lib/view/open1329995970842.html 
  89.  * 内部类Getpic 
  90.  */  
  91.     class Getpic {  
  92.     public  boolean saveUrlAs(String fileUrl, String savePath)  
  93.     {  
  94.         try {  
  95.             URL url = new URL(fileUrl);  
  96.               
  97.             HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  98.             DataInputStream in = new DataInputStream(connection.getInputStream());  
  99.               
  100.             DataOutputStream out = new DataOutputStream(new FileOutputStream(savePath));  
  101.               
  102.             byte[] buffer = new byte[4096];  
  103.             int count = 0;  
  104.             while ((count = in.read(buffer)) > 0)  
  105.             {  
  106.                 out.write(buffer, 0, count);  
  107.             }  
  108.             out.close();  
  109.             in.close();  
  110.             connection.disconnect();  
  111.             return true;  
  112.   
  113.         } catch (Exception e) {  
  114.             System.out.println(e + fileUrl + savePath);  
  115.             return false;  
  116.         }  
  117.     }  
  118.   }  
  119. }  

原文:http://blog.csdn.net/guodongxiaren/article/details/16116071
作者:果冻虾仁
分享:0

电话咨询

客服热线服务时间

周一至周五 9:00-21:00

周六至周日 9:00-18:00

咨询电话

021-67690939
15201841284

微信扫一扫