Java爬蟲之多線程下載IMDB中Top250電影的圖片

介紹

  在博客:Java爬蟲之下載IMDB中Top250電影的圖片中咱們實現了利用Java爬蟲來下載圖片,可是效率不算過高。本次分享將在此基礎上,利用多線程,提升程序運行的效率。java

思路

  本次分享創建在博客Java爬蟲之下載IMDB中Top250電影的圖片上,整體的爬蟲思路沒有變化,只是在此基礎上引入多線程。多線程的思路以下:node

  • Java的每一個任務類必須實現Runnable接口,所以,咱們將新建ImageDownload類來實現Runnable接口。ImageDownload類的構造函數的參數有: url:網站的網址, dir: 圖片儲存目錄。並在run()方法中實現將網頁中的圖片下載到本地。
  • 在主函數中,調用ImageDownload類,利用多線程實現爬蟲下載,提升運行效率。

程序

  ImageDownload類的代碼完整以下:apache

package wikiScrape;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import org.apache.commons.io.FileUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

/* ImageDownload類實現Runnable接口
 * ImageDownload類的構造參數: url:網址的網址, dir: 圖片存儲目錄
 * ImageDownload類實現了將網頁中的圖片下載到本地
 */

public class ImageDownload implements Runnable{
    private String url;
    private String dir;
    
    public ImageDownload(String url, String dir) {
        this.url = url;
        this.dir = dir;
    }
    
    // run()函數: 將網頁中的電影圖片下載到本地
    @Override
    public void run(){
        
        // 利用URL解析網址
        URL urlObj = null;
        try{
            urlObj = new URL(url);

        }
        catch(MalformedURLException e){
            System.out.println("The url was malformed!");
        }

        // URL鏈接
        URLConnection urlCon = null;
        try{
            // 打開URL鏈接
            urlCon = urlObj.openConnection(); 
            // 將HTML內容解析成UTF-8格式
            Document doc = Jsoup.parse(urlCon.getInputStream(), "utf-8", url);
            // 提取電影圖片所在的HTML代碼塊
            Elements elems = doc.getElementsByClass("ss-3 clear");
            Elements pic_block = elems.first().getElementsByTag("a");
            
            for(int i=0; i<pic_block.size(); i++) {
                // 提取電影圖片的url, name
                String picture_url = pic_block.get(i).getElementsByTag("img").attr("src");
                String picture_name = pic_block.get(i).getElementsByClass("bb").text()+".jpg";
                // 用download()函數將電影圖片下載到本地
                download(picture_url, dir, picture_name);
                System.out.println("第"+(i+1)+"張圖片下載完畢!");
            }
            
        }
        catch(IOException e){
            System.out.println("There was an error connecting to the URL");
        }

    }
    
    // download()函數利用圖片的url將圖片下載到本地
    public static void download(String url, String dir, String filename) {  
        try { 
            
            /* httpurl: 圖片的url
             * dirfile: 圖片的儲存目錄
             */
            URL httpurl = new URL(url);  
            File dirfile = new File(dir); 
            
            // 若是圖片儲存的目錄不存在,則新建該目錄
            if (!dirfile.exists()) {    
                dirfile.mkdirs();  
            }  
            
            // 利用FileUtils.copyURLToFile()實現圖片下載
            FileUtils.copyURLToFile(httpurl, new File(dir+filename));  
        } 
        catch(Exception e) {  
            e.printStackTrace();  
        } 
    }
    
}

  主函數ImageScraper.java的代碼以下:segmentfault

package wikiScrape;

/* 本爬蟲利用多線程爬取http://www.imdb.cn/IMDB250/中Top250的圖片
 * 先利用Jsoup解析獲得該網頁中的圖片的url
 * 而後利用FileUtils.copyURLToFile()函數將圖片下載到本地
 */

import wikiScrape.ImageDownload;

import java.util.ArrayList;
import java.util.concurrent.*;
import java.util.Date;

public class ImageScraper {

    public static void main(String[] args) {
        Date d1 = new Date();
        
        System.out.println("爬蟲開始......");
        
        // 爬取的網址列表,一共十個網頁
        ArrayList<String> urls = new ArrayList<String>();
        urls.add("http://www.imdb.cn/IMDB250/");
        for(int i=2; i<=10; i++) {
            urls.add("http://www.imdb.cn/imdb250/"+ Integer.toString(i));
        }
        
        String dir = "E://log/";  // 圖片儲存目錄
        
        // 利用多線程下載每一個頁面中的圖片
        ExecutorService executor = Executors.newCachedThreadPool();
        
        // Create and launch 100 threads
        for(int i=0; i<10; i++) {
            executor.execute(new ImageDownload(urls.get(i), dir));
        }
        
        executor.shutdown();
        
        // wait until all tasks are finished
        while(!executor.isTerminated()) {
        }
        
        System.out.println("程序運行完畢!");
        Date d2 = new Date();
        
        // 計算程序的運行時間,並輸出
        long seconds = (d2.getTime()-d1.getTime())/1000;
        System.out.println("一共用時: "+seconds+"秒.");
        
    }
    
}

運行

  運行上述主函數,結果以下:多線程

程序運行結果

  一共也是下載了244張圖片,運行結果與博客:Java爬蟲之下載IMDB中Top250電影的圖片中的結果如出一轍,可是時間卻少了一半!可見利用多線程來寫爬蟲效率至關高!
  本次分享到此結束,歡迎你們交流~~ide

相關文章
相關標籤/搜索