摘要:项目地址,另外知乎同名文章也是我发布的,大家可以多多关注首先观察控制台其次再看本地壁纸库现在进入正题,这个小项目用到了具体版本见,另外还用到了中的线程池阻塞队列生产消费者模式文件监听服务,所以至少要求版本为或者以上项目分为个类和一个方法入
项目地址,另外知乎同名文章也是我发布的,大家可以多多关注
首先观察控制台
其次再看本地壁纸库
现在进入正题,这个小项目用到了 Jsoup具体版本见 POM),另外还用到了 JDK中的线程池、阻塞队列(生产-消费者模式)、NIO2(文件监听服务 API),所以至少要求 JDK版本为7或者以上
项目分为5个类和一个方法入口类
生产者类(任务:从列表页拿到详情页链接并放入阻塞队列)
public class Producer implements Runnable { private String name; private BlockingQueueblockingQueue; public Producer(String name, BlockingQueue blockingQueue) { this.name = name; this.blockingQueue = blockingQueue; } @Override public void run() { Document doc = null; try { for(int i = 1; i < 12018; i ++) { System.out.println(); System.out.println(); System.out.println("current page:" + i); System.out.println("-----------------------------------"); if(i == 1) { doc = Jsoup.connect("https://alpha.wallhaven.cc/latest").get(); } else { doc = Jsoup.connect("https://alpha.wallhaven.cc/latest?page=" + i).get(); } Element div = doc.getElementById("thumbs"); Elements sections = div.getElementsByTag("section"); for (Element ele : sections) { Elements links = ele.getElementsByClass("preview"); for (Element e : links) { String href = e.attr("href"); blockingQueue.put(href); System.out.println(name + " put " + href); } } } blockingQueue.put(""); System.out.println(name + " is over"); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }
消费者类(任务:从队列拿到链接并获取图片源地址并将下载任务交给一个缓存线程池)
public class Consumer implements Runnable { private String name; private BlockingQueueblockingQueue; private ExecutorService taskPool; public Consumer(String name, BlockingQueue blockingQueue, ExecutorService taskPool) { this.name = name; this.blockingQueue = blockingQueue; this.taskPool = taskPool; } @Override public void run() { Document doc = null; try { String href = null; while((href = blockingQueue.take()) != "") { System.out.println(name + " take " + href); doc = Jsoup.connect(href).get(); Element img = doc.getElementById("wallpaper"); String src = "https:" + img.attr("src"); taskPool.submit(new DownloadTask(src)); } System.out.println(name + " is over"); } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }
下载任务执行类(任务:下载图片到本地)
public class DownloadTask implements Runnable { private static String path = "C:UsersaiyapengDesktopPaper"; private String src; private String name; public DownloadTask(String src) { this.src = src; int n = src.lastIndexOf("/"); this.name = src.substring(++n); } @Override public void run() { Response res = null; try { res = Jsoup.connect(src).ignoreContentType(true).timeout(30000).execute(); byte[] bytes = res.bodyAsBytes(); File file = new File(path + name); if (!file.exists()) { RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.write(bytes); raf.close(); } } catch (IOException e1) { e1.printStackTrace(); } } }
监听服务类(任务:将文件路径注册到监听服务上并开始监听)
public class ResourceListener { private static ExecutorService fixedThreadPool = Executors.newCachedThreadPool(); private WatchService ws; private ResourceListener(String path) { try { ws = FileSystems.getDefault().newWatchService(); start(); } catch (IOException e) { e.printStackTrace(); } } private void start() { fixedThreadPool.execute(new Listener(ws)); } public static void addListener(String path) { try { ResourceListener resourceListener = new ResourceListener(path); Path p = Paths.get(path); p.register(resourceListener.ws, StandardWatchEventKinds.ENTRY_CREATE); } catch (IOException e) { e.printStackTrace(); } } }
监听回调类(任务:执行回调任务)
public class Listener implements Runnable { private WatchService service; public Listener(WatchService service) { this.service = service; } @Override public void run() { try { while (true) { WatchKey watchKey = service.take(); List> watchEvents = watchKey.pollEvents(); for (WatchEvent> event : watchEvents) { System.err.println(event.context() + "已下载"); } watchKey.reset(); } } catch (InterruptedException e) { e.printStackTrace(); } } }
方法入口类
public class DownloadTaskExecutor { public static void main(String[] args) throws IOException { ResourceListener.addListener("C:UsersaiyapengDesktopPaper"); BlockingQueueblockingQueue = new SynchronousQueue (true); ExecutorService proservice = Executors.newSingleThreadExecutor(); ExecutorService conservice = Executors.newSingleThreadExecutor(); ExecutorService taskPool = Executors.newCachedThreadPool(); proservice.submit(new Producer("Producer", blockingQueue)); conservice.submit(new Consumer("Consumer", blockingQueue, taskPool)); proservice.shutdown(); conservice.shutdown(); } }
最后就是设置壁纸库并设定更换频率
感谢大家,有问题可以再评论区留言~~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70155.html
摘要:极简壁纸是一个期望呈现出简单高效美观的壁纸网站。灵感来源是爱壁纸,图片来源是极简壁纸网站建立于年月日。入口极简壁纸喜欢关于我们入口极简壁纸关于我们如果喜欢的话可以来看看,地址,对于网站有什么意见建议也欢迎回复留言。 showImg(https://segmentfault.com/img/remote/1460000017965030); 极简壁纸是一个期望呈现出简单高效美观的壁纸网站...
摘要:文章目录在线图片压缩在线压缩最好用的切图工具在线工具一键抠图免费字体免费素材图片和视频中国风配色网站免费壁纸免费短连接在线在线代码编辑在线流程图思维导图在线图片压缩传送门在线图片压缩网站已经优化超过十亿张图片,支持,,等格式的图片的压缩。 ...
摘要:爬取分辨率超清唯美壁纸简介壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空,有的人喜欢美女,有的人喜欢动物。 @[toc] 爬取5K分辨率超清唯美壁纸 简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空,有的人喜欢美女,有的人喜欢动物。然而,终究有一天你已经产生审美疲劳了,但你下定决定要换壁纸的时候,又发现网上的壁纸要...
摘要:前言之前初学的时候,有用爬虫爬过一些磁力链接详情见羞羞的爬虫但是没有并发,没有代理,那时也对异步不是很了解所以这次又写了个爬虫,爬取壁纸站的所有壁纸并且爬取开心代理的条,并将有用的存进文件中用到的模块控制并发解析库使用代理读写文件其中的具 前言 之前初学node的时候,有用爬虫爬过一些磁力链接详情见羞羞的node爬虫但是没有并发,没有代理,那时也对异步不是很了解所以这次又写了个爬虫,爬...
阅读 855·2021-11-24 09:38
阅读 1086·2021-10-08 10:05
阅读 2579·2021-09-10 11:21
阅读 2803·2019-08-30 15:53
阅读 1829·2019-08-30 15:52
阅读 1967·2019-08-29 12:17
阅读 3421·2019-08-29 11:21
阅读 1613·2019-08-26 12:17