Java实现批量下载《神秘的程序员》漫画
上周看了西乔的博客“西乔的九卦”。《神秘的程序员们》系列漫画感觉很喜欢,很搞笑。这些漫画经常出现在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实现批量下载《神秘的程序员》漫画相关推荐
- 2017年最受欢迎的十篇神秘的程序员漫画
嗷!2017年就这样结束了. 2016年最受欢迎的十篇神秘的程序员漫画 2015年最受欢迎的十篇神秘的程序员漫画 今年一共更新了36篇漫画.三期头像包,开了个新系列--我的男朋友/女朋友是程序员. ( ...
- 2015年最受欢迎的十篇神秘的程序员漫画
嗷!2015年就这样结束了.西乔你挖的坑填了吗!填了吗! 说好的编辑器圣战呢,说好的表情包呢?说好的猫系列呢,说好的部落图鉴系列呢,Python / Ruby / Javascript / C++ 部 ...
- 西乔说要把「神秘的程序员们」当做一个文化产品来做
西乔何许人也 她是「神秘的程序员们」系列漫画的原创作者,每篇漫画都能戳中程序员的笑点和泪点,经常有10W+的阅读量,可以说是最懂程序员的漫画作者:她做设计也管理项目,为FT中文网和纽约时报中文网重构或 ...
- java中forward和redirect_好程序员Java教程分享:Forward和Redirect的区别
Java教程分享:Forward和Redirect的区别,用户向服务器发送了一次HTTP请求,该请求可能会经过多个信息资源处理以后才返回给用户,各个信息资源使用请求转发机制相互转发请求,但是用户是感觉 ...
- 集中派发福利:《神秘的程序员们》年度大抽奖
来自程序员星的地球漫游者们,母星基地开始集中派发福利了--2016的年度抽奖活动.共设置5个奖项,共100名获奖者. 只想抽奖不想听故事的请快速往下翻--但如果你喜欢这部漫画,还是推荐听听<神秘 ...
- 关于Java实现批量下载MinIO指定目录下的所有文件
关于Java实现批量下载MinIO指定目录下的所有文件 Straightforward String bucketName = "bucket01";// 检查'mybucket' ...
- 系列漫画:神秘的程序员们 全集连载——绝对经典
系列漫画,神秘的程序员,全集连载如下: 系列漫画:神秘的程序员(一)--事务的本质 系列漫画:神秘的程序员(二)--图形界面 系列漫画:神秘的程序员(三)--封掉Google 系列漫画:神秘的程序员( ...
- 快来!礼物替你选好了:2022年神秘的程序员周历!
点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 空山松子落,幽人应未眠. 呼叫 ...
- 神秘的程序员表情包 (第一发)
咳咳,承诺已久的<神秘的程序员们>表情包终于出现了...对待西乔这种重症拖延患者还是要有耐心,不能随便放弃病人 在微信里添加自定义表情的方法,请自行搜索. ============ 吐槽版 ...
- java中怎样导入图片6_java程序员进阶篇之必须掌握的6张思维导图!
原标题:java程序员进阶篇之必须掌握的6张思维导图! <java程序员的自我修养>的作者是MindMaster思维导图社区用户芒果,作者整理了一系列学习java程序的笔记,方便java程 ...
最新文章
- vb.net怎么调用fastreport报表_零编码制作报表可能吗?
- 信息系统项目管理师-挣值管理(PV、 AC、 EV、 ETC、 CV、 SV、 CPI、 SP)
- 基于verilog的洗衣机设计
- c2000 汇编语言指令,C2000系CMD文件的配置理解
- SQL Server 登录更换【Windows身份验证】为【SQL Server 身份验证】
- JAVA做一个五星评论打分字体,java中的Font
- 什么时候对象会进入老年代?
- Excel中复杂跨行跨列数据
- 数据库数据变大会导致查询慢_是什么导致数据库变慢?
- 两道关于前缀和的算法题
- 计算机技术在生物学中的应用鲁东大学,项目学习在高中生物学教学中的应用研究...
- spring集成shiro原理
- NVIDIA驱动安装(arm64平台可用)
- Linux 环境下载百度云资源,Firefox插件(百度网盘助手)
- Nginx学习(1)—— 下载和安装
- Windows服务描述及其原理
- 【Android】AppCompat V21:将 Materia Design 兼容到5.0之前的设备
- 安卓下的c语言ide,C语言编译器IDE安卓版下载-C语言编译器IDE下载v1.7 最新版-腾牛安卓网...
- C4d win7 64bit安装好之后,点击启动无反应
- 身份证正反面复印简单示意图
热门文章
- CNN之Xception Keras实现模型训练
- 张轩睿和Selina要复合?任家萱的粉丝们会同意吗
- 计算机科学箴言集 -- 编程珠玑续
- android offtime编程,OFFTIME - 做功课就憋玩手机了! - Android 应用 - iPad - 【最美应用】...
- nebula模拟器_【nebula街机模拟器中文版】nebula街机模拟器最新中文版游戏下载-街机中国...
- 使用regedit导入导出环境变量
- asp.net 邮件功能
- Docker从基础到企业生产应用学习笔记大总结
- CSS3和jQuery实现花瓣网固定顶部位置悬浮菜单效果
- 内存超频对游戏提升大吗 玩游戏有必要超频吗