使用HttpClient和Jsoup實現一個簡單爬蟲


一直很想了解一下爬蟲這個東西的,完全是出於興趣,其實剛開始是准備用python的,但是由於種種原因選擇了java,此處省略很多字... 總之,如果你想做一件事情的話就盡快去做吧,千萬不要把戰線拉得太長了,否則時間一長其實發現自己什么都沒做... 拖延症就是這樣慢慢形成了。

在寫一個爬蟲以前需要了解一下HTTP協議的,通常的B/S程序都是客戶端請求、服務端響應這種模式,通過一個URL就能從服務器上請求到一些信息。而爬蟲就是用程序實現了這個過程,用程序發起一個HTTP請求,然后接收服務端的響應結果,然后就從這些響應中抽取出你想要的信息。這里介紹了使用HttpClient和Jsoup編寫的一個網絡爬蟲,爬取了http://jandan.net/上的一些圖片,並且把圖片保存到本地。

HttpClient

官網地址:http://hc.apache.org/httpclient-3.x/  這是apache上的一個項目,主要作用是發起一個Http請求,並且接收響應,並且可以設置超時時間,比傳統Java中的API要方便很多。

Jsoup

官網地址:https://jsoup.org/ 雖然這是官方地址,但是卻是英文的,推薦看這里http://www.open-open.com/jsoup/ 這里是中文的文檔,看這里就足夠使用這個工具了,主要用於解析響應的html,但是也可以使用Jsoup發起一個http請求,但是功能沒有HttpClient強大。所有一般是用HttpClient請求,Jsoup解析。

包含的jar包:

jsoup-1.7.2.jar

commons-logging-1.1.3.jar

httpclient-4.5.3.jar

httpcore-4.4.6.jar

直接上代碼吧:這基本上是一個通用的類了,給定一個URL返回一個請求響應的html,並且設置了請求超時的參數。

package spider.img.service;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

/**
 * 2017-5-17 基礎類,通過URL返回一個響應的html
 * 
 * @author tom
 */
public class AbstractSpider {

    public static String getResult(String url) throws Exception {
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build();
                CloseableHttpResponse response = httpClient.execute(new HttpGetConfig(url))) {
            String result = EntityUtils.toString(response.getEntity());
            return result;
        } catch (Exception e) {
            System.out.println("獲取失敗");
            return "";
        }
    }
}

/**
 * 內部類,繼承HttpGet,為了設置請求超時的參數
 * 
 * @author tom
 *
 */
class HttpGetConfig extends HttpGet {
    public HttpGetConfig(String url) {
        super(url);
        setDefaulConfig();
    }

    private void setDefaulConfig() {
        this.setConfig(RequestConfig.custom()
                .setConnectionRequestTimeout(10000)
                .setConnectTimeout(10000)
                .setSocketTimeout(10000).build());
        this.setHeader("User-Agent", "spider");
    }
}

這里用了try-with-resource語法,是Java7的新特性,在try()括號中的資源會在try語句塊執行完之后自動釋放,所以不需要再finally中釋放資源。

 

爬取圖片的類:通過上面類的靜態方法返回的結果,獲取到返回的響應結果,然后通過jsoup解析。

package spider.img.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * 2017-5-17 爬取指定URL的圖片
 * 
 * @author tom
 *
 */
public class SpiderImgs {
    public SpiderImgs(String url) throws Exception {
        //獲取工具類返回的html,並用Jsoup解析
        String result = AbstractSpider.getResult(url);
        Document document = Jsoup.parse(result);
        document.setBaseUri(url);
        //獲取所有的img元素
        Elements elements = document.select("img");
        for (Element e : elements) {
            //獲取每個src的絕對路徑
            String src = e.absUrl("src");
            URL urlSource = new URL(src);
            URLConnection urlConnection = urlSource.openConnection();
            String imageName = src.substring(src.lastIndexOf("/") + 1, src.length());
            System.out.println(e.absUrl("src"));
            //通過URLConnection得到一個流,將圖片寫到流中,並且新建文件保存
            InputStream in = urlConnection.getInputStream();
            OutputStream out = new FileOutputStream(new File("E:\\IDEA\\imgs\\", imageName));
            byte[] buf = new byte[1024];
            int l = 0;
            while ((l = in.read(buf)) != -1) {
                out.write(buf, 0, l);
            }
        }
    }
}

 

寫一個單元測試試一下:

package spider.img.service.test;

import org.junit.Test;
import spider.img.service.SpiderImgs;

/**
 * 2017-5-17 單元測試
 * @author tom
 */
public class TestCase {
    @Test
    public void testGetResult() throws Exception{
        SpiderImgs spider=new SpiderImgs("http://jandan.net/ooxx/page-60#comments");
    }
}

控制台輸出了一些東西,本地也保存了圖片。

http://wx4.sinaimg.cn/mw600/0063qhYBgy1ffolz6oon2j30rs15o428.jpg
http://wx2.sinaimg.cn/mw600/0063qhYBgy1ffoiucdw5yj30xc0m9gpt.jpg
http://wx2.sinaimg.cn/mw600/0063qhYBgy1ffoivfcfpwj30xc0m9jt3.jpg
http://wx3.sinaimg.cn/mw600/0063qhYBgy1ffoiqgqqc0j30lc0w1402.jpg
http://wx3.sinaimg.cn/mw600/0063qhYBgy1ffoiqg5kz2j30hs0qogo7.jpg
http://wx4.sinaimg.cn/mw600/0063qhYBgy1ffoiqewsbej30go0l60wc.jpg
http://wx3.sinaimg.cn/mw600/0063qhYBgy1ffoiqdglc7j30lc0voq5k.jpg
http://wx4.sinaimg.cn/mw600/0063qhYBgy1ffoiqaz4dej30lc0w0gn6.jpg

 

github地址:https://github.com/silentyao/JavaImgSpider


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM