WebMagic+curl採集圖片 頂 原 薦

一、事出必有因

    前段時間公司讓去採集一些單品的圖片,單品的圖片約清晰越好。

二、最初思路

    在WebMagic沒有找到下載文件用的下載器(Downloader),一開始是在網上找的HttpClient的代碼,想要自己實現一個文件下載的Downloader,但是由於單個圖片太大,由於網絡不穩定,有時候在下載時就總是出現線程假死狀態。

  /**
     * 從網絡Url中下載文件(我一開始是使用這個方法去下載圖片,但是總是出問題。)
     * @param urlStr
     * @param fileName
     * @param savePath
     * @throws IOException
     */
    public static void  downLoadFromUrl(String urlStr,String fileName,String savePath) throws IOException{
        URL url = new URL(urlStr);  
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
                //設置超時間爲3秒
        conn.setConnectTimeout(3*1000);
        //防止屏蔽程序抓取而返回403錯誤
        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

        //得到輸入流
        InputStream inputStream = conn.getInputStream();  
        //獲取自己數組
        byte[] getData = readInputStream(inputStream);    

        //文件保存位置
        File saveDir = new File(savePath);
        if(!saveDir.exists()){
            saveDir.mkdir();
        }
        File file = new File(saveDir+File.separator+fileName);    
        FileOutputStream fos = new FileOutputStream(file);     
        fos.write(getData); 
        if(fos!=null){
            fos.close();  
        }
        if(inputStream!=null){
            inputStream.close();
        }


        System.out.println("info:"+url+" download success"); 

    }

(上面代碼參考:java 從網絡Url中下載文件

三、自己實現的Java curl下載器(Pipeline)

    curl是PHP的一個工具,也是linux上自帶的一個命令,簡稱神器

$ which curl
/usr/bin/curl

1、curl簡單命令介紹

  • 下載單個文件,默認將輸出打印到標準輸出中(STDOUT)中

curl https://www.baidu.com/
  • 通過-o/-O選項保存下載的文件到指定的文件中

-o:將文件保存爲命令行中指定的文件名的文件中
-O:使用URL中默認的文件名保存文件到本地

1 # 將文件下載到本地並命名爲mygettext.html
2 curl -o mygettext.html http://www.gnu.org/software/gettext/manual/gettext.html
3 
4 # 將文件保存到本地並命名爲gettext.html
5 curl -O http://www.gnu.org/software/gettext/manual/gettext.html

同樣可以使用轉向字符">"對輸出進行轉向輸出

  • 同時獲取多個文件

curl -O URL1 -O URL2

若同時從同一站點下載多個文件時,curl會嘗試重用鏈接(connection)。

  • 斷點續傳

通過使用-C選項可對大文件使用斷點續傳功能,如:

1 # 當文件在下載完成之前結束該進程
2 $ curl -O http://www.gnu.org/software/gettext/manual/gettext.html
3 ##############             20.1%
4 
5 # 通過添加-C選項繼續對該文件進行下載,已經下載過的文件不會被重新下載
6 curl -C - -O http://www.gnu.org/software/gettext/manual/gettext.html
7 ###############            21.1%
  • curl 取得HTTP返回的狀態碼:-w %{http_code}

curl https://www.baidu.com/ -o ./baidu.html -w %{http_code} -s
## -w %{http_code} 控制額外輸出(小寫w)
## -s silent 模式,不輸出任何東西(小寫s)
## -o ./baidu.html 把下載的數據保存到當前文件夾下的baidu.html(小寫o)

參考:CURL常用命令

          常用HTTP狀態碼和CURL 000問題

2、實現Java curl下載器

  • 如果是window系統,需要先下載curl.exe(抱歉沒有用過Mac)

  • 去Github下載curl。打開src/目錄,就是curl.exe
            

  • java curl Downloader

package com.lacerta.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class DownloadPictureUtil {

	public static void main(String[] args) {
		long i = System.currentTimeMillis();
		boolean b = downloadPicture(
				"https://www.baidu.com/img/bd_logo1.png",
				"D:/curltest.jpg");
		System.out.println("下載是否成功:" + b + "\t使用時間" + (System.currentTimeMillis() - i) + "ms");
	}

	public static boolean downloadPicture(String imgURL, String target) {
		String[] cmds = { //
				"C:/Users/AnXiaole/Downloads/curl-7.52.1/src/curl", //
				"-o", //把下載的數據保存到指定的文件中,這裏是target(小寫o)
				target, //
				imgURL, //需要下載的URI網址
				"-s", //silent 模式,不輸出任何東西(小寫s)
				"-w \n%{http_code}"//控制額外輸出(小寫w)
		};
		ProcessBuilder pb = new ProcessBuilder(cmds);
		pb.redirectErrorStream(true);
		Process p;
		BufferedReader br = null;
		try {
			p = pb.start();
			String line = null;
			br = new BufferedReader(new InputStreamReader(p.getInputStream()));
			while ((line = br.readLine()) != null) {
				if (line.trim().contains("200")) {
					System.out.println("Download Img 200:\t" + cmds[2]);
					return true;
				}
				if (line.trim().contains("404")) {
					System.out.println("Download Img 404:\t" + cmds[2]);
					return false;
				}
			}
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
  • 和WebMagic集成的使用方法

在我自定義的FilePipeline:IntaoFilePipeline中使用DownloadPictureUtil下載器:
boolean b = DownloadPictureUtil.downloadPicture(url, path + (i + 1) + ".jpg");

package com.lacerta.intao.babyimg.designerchildrenswear;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

import com.lacerta.util.DownloadPictureUtil;

import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.FilePipeline;

public class IntaoFilePipeline extends FilePipeline {

	public IntaoFilePipeline() {
		setPath("/data/webmagic/");
	}

	public IntaoFilePipeline(String path) {
		setPath(path);
	}

	@Override
	public void process(ResultItems resultItems, Task task) {
		String path = this.path + task.getUUID()
				+ PATH_SEPERATOR /* + resultItems.get("單品品牌\t") */ + resultItems.get("單品id\t") + PATH_SEPERATOR;
		PrintWriter printWriter = null;
		try {
			printWriter = new PrintWriter(new OutputStreamWriter(
					new FileOutputStream(getFile(path + "單品" + resultItems.get("單品id\t") + ".html"), true), "UTF-8"));

			printWriter.println("<meta charset=\"utf-8\">");
			printWriter.println("當前採集地址:\t" + resultItems.getRequest().getUrl() + "<br/>");
			for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) {
				printWriter.println(entry.getKey() + ":\t" + entry.getValue() + "<br/>");
			}

			Object object = resultItems.get("圖片路徑\t");// 獲得WebMagic抓取到的圖片路徑list
			if (object != null) {
				List<String> picUrl = (List<String>) object;
				for (int i = 0; i < picUrl.size(); i++) {
					String url = picUrl.get(i);
					for (int j = 0; j <= task.getSite().getRetryTimes(); j++) {
						boolean b = DownloadPictureUtil.downloadPicture(url, path + (i + 1) + ".jpg");
						if (b) {
							break;
						} else {
							try {
								Thread.sleep(task.getSite().getSleepTime());
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (printWriter != null) {
				printWriter.close();
			}
		}
	}

}
  • WebMagic啓動方法

	public static void main(String[] args) throws IOException {

		Spider spider = Spider.create(new IntaoPageProcessor())//
				.setScheduler(
						new FileCacheQueueScheduler("D:/資料包/work/lacerta/intao/" + site.getDomain() + "/scheduler"))
				.addPipeline(new ConsolePipeline())//
				.addPipeline(new IntaoFilePipeline("D:/資料包/work/lacerta/intao"))// 加入IntaoFilePipeline
		;

		spider.addUrl("這裏是要下載的url,這裏就寫我當時抓取的url了");

		spider.thread(60).run(); // 當時我使用了60個線程。
	}

四、參考

CURL常用命令

常用HTTP狀態碼和CURL 000問題

curl / Download

利用webmagic下載圖片

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章