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

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

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

1.下载网络图片

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

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

package action;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class Getpic {public Getpic() {}public static boolean saveUrlAs(String fileUrl, String savePath)/* fileUrl网络资源地址 */{try {/* 将网络资源地址传给,即赋值给url */URL url = new URL(fileUrl);/* 此为联系获得网络资源的固定格式用法,以便后面的in变量获得url截取网络资源的输入流 */HttpURLConnection connection = (HttpURLConnection) url.openConnection();DataInputStream in = new DataInputStream(connection.getInputStream());/* 此处也可用BufferedInputStream与BufferedOutputStream  需要保存的路径*/DataOutputStream out = new DataOutputStream(new FileOutputStream(savePath));/* 将参数savePath,即将截取的图片的存储在本地地址赋值给out输出流所指定的地址 */byte[] buffer = new byte[4096];int count = 0;while ((count = in.read(buffer)) > 0)/* 将输入流以字节的形式读取并写入buffer中 */{out.write(buffer, 0, count);}out.close();/* 后面三行为关闭输入输出流以及网络资源的固定格式 */in.close();connection.disconnect();return true;/* 网络资源截取并存储本地成功返回true */} catch (Exception e) {System.out.println(e + fileUrl + savePath);return false;}}public static void main(String[] args) {Getpic pic = new Getpic();/* 创建实例 *///需要下载的URLString photoUrl = "http://hiphotos.baidu.com/yanshennan/pic/item/03a505c8bcbaf6557f3e6f8a.jpg";// 截取最后/后的字符串String fileName = photoUrl.substring(photoUrl.lastIndexOf("/"));//图片保存路径String filePath = "E:";/* 调用函数,并且进行传参 */boolean flag = pic.saveUrlAs(photoUrl, filePath + fileName);System.out.println("Run ok!\n Get URL file " + flag);System.out.println(filePath);System.out.println(fileName);}}

2.提取出图片URL

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

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

<a href="http://blog.xiqiao.info/blogimg/programmers/53_run_result.gif">点击看大图</a></p>
<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结束的字符串,所以虽然下面那一行很长,但是也是只会得到一个字符串。

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

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

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

Pattern p1 = Pattern.compile(".*src.*[gif|jpg].*");

匹配出来,还要再提取出来,正则应该也可以做到,但是我还是选择用字符串取子串的方法来写,更简单。

String line = inputLine.substring(inputLine.indexOf("src"),inputLine.lastIndexOf("\" alt"));
Url = line.substring(line.indexOf("http"));

3.获取下一页

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

原网页html代码

<ul class="navigation"><li class="left"><a href="http://blog.xiqiao.info/category/programmers/page/3" >← Older Entries</a></li><li class="right"><a href="http://blog.xiqiao.info/category/programmers/" >Newer Entries →</a></li>
</ul>

上面,是一个上一页,一个下一页。要找出他,同样使用正则匹配。我写的烂,大家可自由发挥。

Pattern p2 = Pattern.compile(".*<li class=\"left\"><a href=\"http://blog.xiqiao.info/category/programmers/page/.*");

提取比较简单

Url = "http"+inputLine.substring(inputLine.indexOf(':'),inputLine.lastIndexOf('"'));

4.完整代码

//package com.xiqiao;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
/*** 批量下载“西乔的九卦”中的系列漫画《神秘的程序员》* @author guodongxiaren* 2013/11/14*/
public class DownLoad {private String path = "http://blog.xiqiao.info/category/programmers";private String filePath = "D:/day/net/pic";//可以改成你自己的路径,注意必须是已存在的路径private String fileName = null;private String Url = null;private Pattern p1 = Pattern.compile(".*src.*[gif|jpg].*");private Pattern p2 = Pattern.compile(".*<li class=\"left\"><a href=\"http://blog.xiqiao.info/category/programmers/page/.*");public static void  main(String[]args)throws IOException{DownLoad ia = new DownLoad();ia.start();}
/*** 解析出图片下载地址及图片名称* @param inputLine*/public void AddResolution(String inputLine){String line = inputLine.substring(inputLine.indexOf("src"),inputLine.lastIndexOf("\" alt"));Url = line.substring(line.indexOf("http"));System.out.println(Url);//为了便于查看图片,我把所有图片都改成jpg。。因为gif图片经常会用浏览器打开-_-#fileName = Url.substring(Url.lastIndexOf("/"),Url.lastIndexOf("."))+".jpg";}/*** 开始下载* @throws IOException*/public void start() throws IOException{URL name = new URL(path);URLConnection conn = name.openConnection();InputStream input = conn.getInputStream();InputStreamReader isr = new InputStreamReader(input);BufferedReader buffer = new BufferedReader(isr);String inputLine=null;Getpic pic = new Getpic();while((inputLine=buffer.readLine())!=null){Matcher matcher1 = p1.matcher(inputLine);Matcher matcher2 = p2.matcher(inputLine);try{if(matcher1.matches()){AddResolution(inputLine);boolean flag = pic.saveUrlAs(Url, filePath + fileName);System.out.println("Get URL file " + flag);System.out.println(filePath);System.out.println(fileName+" save successful");}}catch(StringIndexOutOfBoundsException e){}if(matcher2.matches()){Url = "http"+inputLine.substring(inputLine.indexOf(':'),inputLine.lastIndexOf('"'));name = new URL(Url);conn = name.openConnection();input = conn.getInputStream();isr = new InputStreamReader(input);buffer = new BufferedReader(isr);}}System.out.println("Successful");}/*** 感谢这段代码原作者* @author http://www.open-open.com/lib/view/open1329995970842.html* 内部类Getpic*/class Getpic {public  boolean saveUrlAs(String fileUrl, String savePath){try {URL url = new URL(fileUrl);HttpURLConnection connection = (HttpURLConnection) url.openConnection();DataInputStream in = new DataInputStream(connection.getInputStream());DataOutputStream out = new DataOutputStream(new FileOutputStream(savePath));byte[] buffer = new byte[4096];int count = 0;while ((count = in.read(buffer)) > 0){out.write(buffer, 0, count);}out.close();in.close();connection.disconnect();return true;} catch (Exception e) {System.out.println(e + fileUrl + savePath);return false;}}}
}

Java实现批量下载《神秘的程序员》漫画相关推荐

  1. 2017年最受欢迎的十篇神秘的程序员漫画

    嗷!2017年就这样结束了. 2016年最受欢迎的十篇神秘的程序员漫画 2015年最受欢迎的十篇神秘的程序员漫画 今年一共更新了36篇漫画.三期头像包,开了个新系列--我的男朋友/女朋友是程序员. ( ...

  2. 2015年最受欢迎的十篇神秘的程序员漫画

    嗷!2015年就这样结束了.西乔你挖的坑填了吗!填了吗! 说好的编辑器圣战呢,说好的表情包呢?说好的猫系列呢,说好的部落图鉴系列呢,Python / Ruby / Javascript / C++ 部 ...

  3. 西乔说要把「神秘的程序员们」当做一个文化产品来做

    西乔何许人也 她是「神秘的程序员们」系列漫画的原创作者,每篇漫画都能戳中程序员的笑点和泪点,经常有10W+的阅读量,可以说是最懂程序员的漫画作者:她做设计也管理项目,为FT中文网和纽约时报中文网重构或 ...

  4. java中forward和redirect_好程序员Java教程分享:Forward和Redirect的区别

    Java教程分享:Forward和Redirect的区别,用户向服务器发送了一次HTTP请求,该请求可能会经过多个信息资源处理以后才返回给用户,各个信息资源使用请求转发机制相互转发请求,但是用户是感觉 ...

  5. 集中派发福利:《神秘的程序员们》年度大抽奖

    来自程序员星的地球漫游者们,母星基地开始集中派发福利了--2016的年度抽奖活动.共设置5个奖项,共100名获奖者. 只想抽奖不想听故事的请快速往下翻--但如果你喜欢这部漫画,还是推荐听听<神秘 ...

  6. 关于Java实现批量下载MinIO指定目录下的所有文件

    关于Java实现批量下载MinIO指定目录下的所有文件 Straightforward String bucketName = "bucket01";// 检查'mybucket' ...

  7. 系列漫画:神秘的程序员们 全集连载——绝对经典

    系列漫画,神秘的程序员,全集连载如下: 系列漫画:神秘的程序员(一)--事务的本质 系列漫画:神秘的程序员(二)--图形界面 系列漫画:神秘的程序员(三)--封掉Google 系列漫画:神秘的程序员( ...

  8. 快来!礼物替你选好了:2022年神秘的程序员周历!

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 空山松子落,幽人应未眠.   呼叫 ...

  9. 神秘的程序员表情包 (第一发)

    咳咳,承诺已久的<神秘的程序员们>表情包终于出现了...对待西乔这种重症拖延患者还是要有耐心,不能随便放弃病人 在微信里添加自定义表情的方法,请自行搜索. ============ 吐槽版 ...

  10. java中怎样导入图片6_java程序员进阶篇之必须掌握的6张思维导图!

    原标题:java程序员进阶篇之必须掌握的6张思维导图! <java程序员的自我修养>的作者是MindMaster思维导图社区用户芒果,作者整理了一系列学习java程序的笔记,方便java程 ...

最新文章

  1. vb.net怎么调用fastreport报表_零编码制作报表可能吗?
  2. 信息系统项目管理师-挣值管理(PV、 AC、 EV、 ETC、 CV、 SV、 CPI、 SP)
  3. 基于verilog的洗衣机设计
  4. c2000 汇编语言指令,C2000系CMD文件的配置理解
  5. SQL Server 登录更换【Windows身份验证】为【SQL Server 身份验证】
  6. JAVA做一个五星评论打分字体,java中的Font
  7. 什么时候对象会进入老年代?
  8. Excel中复杂跨行跨列数据
  9. 数据库数据变大会导致查询慢_是什么导致数据库变慢?
  10. 两道关于前缀和的算法题
  11. 计算机技术在生物学中的应用鲁东大学,项目学习在高中生物学教学中的应用研究...
  12. spring集成shiro原理
  13. NVIDIA驱动安装(arm64平台可用)
  14. Linux 环境下载百度云资源,Firefox插件(百度网盘助手)
  15. Nginx学习(1)—— 下载和安装
  16. Windows服务描述及其原理
  17. 【Android】AppCompat V21:将 Materia Design 兼容到5.0之前的设备
  18. 安卓下的c语言ide,C语言编译器IDE安卓版下载-C语言编译器IDE下载v1.7 最新版-腾牛安卓网...
  19. C4d win7 64bit安装好之后,点击启动无反应
  20. 身份证正反面复印简单示意图

热门文章

  1. CNN之Xception Keras实现模型训练
  2. 张轩睿和Selina要复合?任家萱的粉丝们会同意吗
  3. 计算机科学箴言集 -- 编程珠玑续
  4. android offtime编程,OFFTIME - 做功课就憋玩手机了! - Android 应用 - iPad - 【最美应用】...
  5. nebula模拟器_【nebula街机模拟器中文版】nebula街机模拟器最新中文版游戏下载-街机中国...
  6. 使用regedit导入导出环境变量
  7. asp.net 邮件功能
  8. Docker从基础到企业生产应用学习笔记大总结
  9. CSS3和jQuery实现花瓣网固定顶部位置悬浮菜单效果
  10. 内存超频对游戏提升大吗 玩游戏有必要超频吗