webmagic 二次開發爬蟲 爬取網站圖片

webmagic的是一個無須配置、便於二次開發的爬蟲框架,它提供簡單靈活的API,只需少許代碼便可實現一個爬蟲。html

webmagic介紹 編寫一個簡單的爬蟲java

webmagic的使用文檔:http://webmagic.io/docs/git

webmagic的設計文檔:webmagic的設計機制及原理-如何開發一個Java爬蟲github

 

 

1.編寫一個核心的url過濾類web

 1 package com.xwer.spider.main;
 2 
 3 import java.util.List;
 4 
 5 import org.apache.log4j.Logger;
 6 
 7 import us.codecraft.webmagic.Page;
 8 import us.codecraft.webmagic.Site;
 9 import us.codecraft.webmagic.processor.PageProcessor;
10 import us.codecraft.webmagic.utils.UrlUtils;
11 
12 /**
13  * 定製爬蟲邏輯的核心類
14  * @author xwer
15  *
16  */
17 public class MM_Processor implements PageProcessor {
18     private Logger logger = Logger.getLogger(this.getClass());
19     // 部分一:抓取網站的相關配置,包括編碼、抓取間隔、重試次數等
20     private Site site = Site.me().setRetryTimes(5).setSleepTime(1000);
21     // 網頁匹配規則
22     private String urlPattern;
23     public MM_Processor(String startUrl, String urlPattern) {
24         // 設置所屬域
25         this.site = Site.me().setDomain(UrlUtils.getDomain(startUrl));
26         this.urlPattern = urlPattern;
27     }
28 
29     @Override
30     // process是定製爬蟲邏輯的核心接口,在這裏編寫抽取邏輯
31     public void process(Page page) {
32         site.setUserAgent("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
33         //圖片抓取規則
34         String imgRegex3 = "http://mm.howkuai.com/wp-content/uploads/20[0-9]{2}[a-z]/[0-9]{2}/[0-9]{2}/[0-9]{1,4}.jpg";
35         // 獲取目標連接 例如 http://www.meizitu.com/a/5535.html
36         List<String> requests = page.getHtml().links().regex(urlPattern).all();
37         logger.info("獲取到的目標連接是: "+requests);
38         logger.info("添加連接( "+requests.size()+" )條到集合");
39                   
40          //將獲取的連接存入到targetRequests中(list集合)
41         page.addTargetRequests(requests);
42         logger.info("隊列中存儲的連接數是: "+page.getResultItems().getAll().size());
43         
44         // 圖片的title,標題名稱,用於設定文件夾的名稱 
45          String imgHostFileName = page.getHtml().xpath("//title/text()").replace("\\p{Punct}", "").toString();
46         logger.info("獲取的標題是"+imgHostFileName);
47         
48         List<String> listProcess = page.getHtml().regex(imgRegex3).all();
49         logger.info("存入的圖片地址: "+listProcess);
50         // 此處將標題一併抓取,以後提取出來做爲文件名
51         listProcess.add(0, imgHostFileName);
52         logger.info("存入的圖片連接數量是: "+listProcess.size());
53         //將獲取到的頁面的數據放到resultItems集合中(map)
54         page.putField("img", listProcess);
55     }
56     @Override
57     public Site getSite() {
58         return site;
59     }
60 }

 

 

2.對獲取的結果進行持久化處理apache

 1 package com.xwer.spider.main;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.Map;
 6 import org.apache.log4j.Logger;
 7 import com.xwer.spider.utils.DownLoadUtils;
 8 import us.codecraft.webmagic.ResultItems;
 9 import us.codecraft.webmagic.Task;
10 import us.codecraft.webmagic.pipeline.Pipeline;
11 
12 /**
13  * 處理
14  * @author xwer
15  *
16  */
17 public class MM_Pipeline implements Pipeline {
18     private Logger logger = Logger.getLogger(this.getClass());
19     private String path;
20 
21     public MM_Pipeline() {
22         setPath("/MM/");
23     }
24 
25     public MM_Pipeline(String path) {
26         setPath(path);
27     }
28 
29     public void setPath(String path) {
30         this.path = path;
31     }
32 
33     // 處理下載的方法
34     @Override
35     public void process(ResultItems resultItems, Task task) {
36         logger.info("到了process" + resultItems);
37         String fileStorePath = this.path;
38         for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) {
39             if (entry.getValue() instanceof List) {
40                 List<String> list = new ArrayList<String>((List) entry.getValue());    
41                 //取出以前存的網頁的標題,拼接成一個新的文件夾名稱
42                 fileStorePath = new StringBuffer(fileStorePath)
43                                     .append(list.get(0))
44                                     .append("\\").toString();
45                 //遍歷圖片連接list
46                 for (int i = 1; i < list.size(); i++) {
47                     // 獲取文件惟一名字
48                     String realname = DownLoadUtils.subFileName(list.get(i));
49                     String uuidname = DownLoadUtils.generateRandonFileName(realname);
50                     // 這裏經過本身寫的下載工具前抓取到的圖片網址,並放在對應的文件中
51                     try {
52                         DownLoadUtils.download(list.get(i), uuidname, fileStorePath);
53                         logger.info("文件" + uuidname +"已經下載完畢");
54                     } catch (Exception e) {
55                         logger.warn("文件下載異常" + list.get(i));
56                         e.printStackTrace();
57                     }
58                 }
59             }
60             else {
61                 System.out.println(entry.getKey() + ":\t" + entry.getValue());
62             }
63         }
64     }
65 }

 

 

3.編寫一個下載圖片的工具類app

 1 package com.xwer.spider.utils;
 2 
 3 import java.io.File;
 4 import java.io.FileOutputStream;
 5 import java.io.InputStream;
 6 import java.io.OutputStream;
 7 import java.net.URL;
 8 import java.net.URLConnection;
 9 import java.util.UUID;
10 
11 /**
12  * 下載相關的工具類
13  * 
14  * @author xwer
15  *
16  */
17 public class DownLoadUtils {
18 
19     /**
20      * 下載圖片工具
21      * 
22      * @param urlString
23      *            圖片連接地址
24      * @param filename
25      *            圖片的文件名字
26      * @param savePath
27      *            圖片保存的路徑
28      * @throws Exception
29      */
30     public static void download(String urlString, String filename, String savePath) throws Exception {
31         // 構造URL
32         URL url = new URL(urlString);
33         // 打開鏈接
34         URLConnection con = url.openConnection();
35         // 設置請求頭
36         con.addRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
37         // 設置請求超時爲5s
38         con.setConnectTimeout(5 * 1000);
39         // 輸入流
40         InputStream is = con.getInputStream();
41 
42         // 1K的數據緩衝
43         byte[] bs = new byte[1024];
44         // 讀取到的數據長度
45         int len;
46         // 輸出的文件流
47         File sf = new File(savePath);
48         if (!sf.exists()) {
49             sf.mkdirs();
50         }
51         OutputStream os = new FileOutputStream(sf.getPath() + "\\" + filename);
52         // 開始讀取
53         while ((len = is.read(bs)) != -1) {
54             os.write(bs, 0, len);
55         }
56         // 完畢,關閉全部連接
57         os.close();
58         is.close();
59     }
60 
61     /**
62      * 截取真實文件名
63      * 
64      * @param fileName
65      * @return
66      */
67     public static String subFileName(String fileName) {
68         // 查找最後一個 \出現位置
69         int index = fileName.lastIndexOf("\\");
70         if (index == -1) {
71             return fileName;
72         }
73         return fileName.substring(index + 1);
74     }
75 
76     /**
77      * 得到隨機UUID文件名
78      * 
79      * @param fileName
80      * @return
81      */
82     public static String generateRandonFileName(String fileName) {
83         // 得到擴展名
84         String ext = fileName.substring(fileName.lastIndexOf("."));
85         return UUID.randomUUID().toString().replace("-", "") + ext;
86     }
87 }

 

4.配置一個日誌的輸出文件(用戶打印日誌)框架

 1 ### direct log messages to stdout ###
 2 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 3 log4j.appender.stdout.Target=System.out
 4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 5 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
 6 
 7 ### direct messages to file mylog.log ###
 8 log4j.appender.file=org.apache.log4j.FileAppender
 9 log4j.appender.file.File=c:/mylog3.log
10 log4j.appender.file.layout=org.apache.log4j.PatternLayout
11 log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
12 
13 ### set log levels - for more verbose logging change 'info' to 'debug' ###
14 log4j.rootLogger=info, stdout ,file

 

5.編寫程序的入口類dom

 

 1 package com.xwer.spider.main;
 2 
 3 import java.util.regex.Pattern;
 4 
 5 import org.junit.Test;
 6 
 7 
 8 
 9 import us.codecraft.webmagic.Spider;
10 import us.codecraft.webmagic.scheduler.FileCacheQueueScheduler;
11 
12 public class MM_test {
13     public static void main(String[] args) {
14         //圖片的存放路徑,PiPline須要用到
15         String fileStorePath = "D:\\test\\";
16         
17         //過濾網頁的正則  http://www.meizitu.com/a/more_1.html
18         String urlPattern = "http://www.meizitu.com/[a-z]/[0-9]{1,4}.html";
19         //自定義的解析器核心
20         MM_Processor mmSprider = new MM_Processor("http://www.meizitu.com/", urlPattern);
21         
22         //設置一些種子連接
23         String[] urls ={"http://www.meizitu.com/",
24                         "http://www.meizitu.com/a/4221.html",
25                         "http://www.meizitu.com/a/4467.html",
26                         "http://www.meizitu.com/a/5467.html",
27                         "http://www.meizitu.com/a/5065.html",
28                         "http://www.meizitu.com/a/4278.html",
29                         "http://www.meizitu.com/a/699.html",
30                         };
31         //啓動爬蟲
32         Spider.create(mmSprider).addUrl(urls)
33                                 .setScheduler(new FileCacheQueueScheduler("D:\\webmagic\\cach"))
34                                 .addPipeline(new MM_Pipeline(fileStorePath))
35                                 .thread(10)
36                                 .run();
37     }
38     
39     
40     

 

6. 爬取結果ide

相關文章
相關標籤/搜索