揭秘Java網(wǎng)絡(luò)爬蟲程序原理

隨著互聯(lián)網(wǎng)+時代的來臨,越來越多的互聯(lián)網(wǎng)企業(yè)層出不窮,涉及游戲、視頻、新聞、社交、電商、房產(chǎn)、旅游等眾多行業(yè)。如今互聯(lián)網(wǎng)成為大量信息的載體,如何有效地從中提取有價值的信息并利用這些信息成為一個巨大的挑戰(zhàn)

爬蟲,一個可怕的怪物,從百度、Google等搜索引擎公司誕生開始便有了它的身影,如今移動互聯(lián)網(wǎng)時代爬蟲更是猖狂,每個網(wǎng)站似乎都被它光顧過,只是你看不到,不過你放心它不干壞事,你能在網(wǎng)上迅速搜索到你到的信息應(yīng)該都是它的功勞,它每天會默默無聞的采集互聯(lián)網(wǎng)上的豐富信息供大家查詢共享。Java作為互聯(lián)網(wǎng)開發(fā)的主流語言,廣泛應(yīng)用于互聯(lián)網(wǎng)領(lǐng)域,本課程使用java技術(shù)為大家講解如何編寫爬蟲程序爬取網(wǎng)絡(luò)上有價值的數(shù)據(jù)信息。

知識點

  • 爬蟲的架構(gòu)解析
  • 爬蟲基本原理分析
  • 編寫爬蟲程序
  • 爬蟲在電商中的應(yīng)用

1. 爬蟲簡介

我們訪問某一個網(wǎng)頁的時候,在地址欄輸入網(wǎng)址,按回車,該網(wǎng)站的服務(wù)器就會返回一個HTML文件給我們,瀏覽器解析返回的數(shù)據(jù),展示在UI上。同樣爬蟲程序也是模仿人的操作,給網(wǎng)站發(fā)送一個請求,網(wǎng)站會給爬蟲程序返回一個HTML文件,爬蟲程序再根據(jù)返回的數(shù)據(jù)進行抓取分析


爬蟲簡介

1.1 爬蟲概論

網(wǎng)絡(luò)爬蟲(Web crawler)也叫網(wǎng)絡(luò)蜘蛛(Web spide)自動檢索工具(automatic indexer),是一種”自動化瀏覽網(wǎng)絡(luò)“的程序,或者說是一種網(wǎng)絡(luò)機器人。

爬蟲被廣泛用于互聯(lián)網(wǎng)搜索引擎或其他類似網(wǎng)站,以獲取或更新這些網(wǎng)站的內(nèi)容和檢索方式。它們可以自動采集所有其能夠訪問到的頁面內(nèi)容,以供搜索引擎做進一步處理(分檢整理下載的頁面),而使得用戶能更快的檢索到他們需要的信息。

通俗的講,就是把你手動打開窗口,輸入數(shù)據(jù)等等操作用程序代替。用程序替你獲取你想要的信息,這就是網(wǎng)絡(luò)爬蟲

1.2 爬蟲應(yīng)用

1.2.1 搜索引擎

爬蟲程序可以為搜索引擎系統(tǒng)爬取網(wǎng)絡(luò)資源,用戶可以通過搜索引擎搜索網(wǎng)絡(luò)上一切所需要的資源。搜索引擎是一套非常龐大且精密的算法系統(tǒng),搜索的準(zhǔn)確性,高效性等都對搜索系統(tǒng)有很高的要求。

搜索引擎原理

1.2.2 數(shù)據(jù)挖掘

大數(shù)據(jù)分析

爬蟲除了用來做搜索外,還可以做非常多的工作,可以說爬蟲現(xiàn)在在互聯(lián)網(wǎng)項目中應(yīng)用的非常廣泛。
互聯(lián)網(wǎng)項目通過爬取相關(guān)數(shù)據(jù)主要進行數(shù)據(jù)分析,獲取價值數(shù)據(jù)。那么爬蟲具體可以做那么分析,下面可以簡單做一個簡單了解:

  • 股票分析---預(yù)測股市
  • 社會學(xué)方面統(tǒng)計預(yù)測
    • 情緒地圖
    • 飲食分布圖
    • 票房分析預(yù)測
    • 機場實時流量
    • 公交系統(tǒng)實時線路
    • 火車票實時銷售統(tǒng)計
  • App下載量分析

1.3 爬蟲原理

1.3.1 爬蟲目的

一般來講對我們而言需要抓取的是某個網(wǎng)站或者某個應(yīng)用的內(nèi)容,提取有用的價值,進行數(shù)據(jù)分析。

1.3.2 爬蟲框架設(shè)計

為了開發(fā)的方便,也可以使用爬蟲框架來開發(fā)項目中的爬蟲;一個通用的網(wǎng)絡(luò)爬蟲的框架如圖所示:

網(wǎng)絡(luò)爬蟲框架.png

網(wǎng)絡(luò)爬蟲的基本工作流程如下:

  1. 首先選取一部分精心挑選的種子URL
  2. 將這些URL放入待抓取URL隊列
  3. 從待抓取URL隊列中取出待抓取在URL,解析DNS,并且得到主機的ip,并將URL對應(yīng)的網(wǎng)頁下載下來,存儲進已下載網(wǎng)頁庫中。此外,將這些URL放進已抓取URL隊列
  4. 分析已抓取URL隊列中的URL,分析其中的其他URL,并且將URL放入待抓取URL隊列,從而進入下一個循環(huán)

2. Java爬蟲框架

2.1 Nutch

Nutch屬于分布式爬蟲,爬蟲使用分布式,主要是解決兩個問題:1)海量URL管理;2)網(wǎng)速。如果要做搜索引擎,Nutch1.x是一個非常好的選擇。Nutch1.x和solr或者es配合,就可以構(gòu)成一套非常強大的搜索引擎,否則盡量不要選擇Nutch作為爬蟲。用Nutch進行爬蟲的二次開發(fā),爬蟲的編寫和調(diào)試所需的時間,往往是單機爬蟲所需的十倍時間不止。

2.2 Heritrix

Heritrix 是個“Archival Crawler”——來獲取完整的、精確的、站點內(nèi)容的深度復(fù)制。包括獲取圖像以及其他非文本內(nèi)容。抓取并存儲相關(guān)的內(nèi)容。對內(nèi)容來者不拒,不對頁面進行內(nèi)容上的修改。重新爬行對相同的URL不針對先前的進行替換。爬蟲主要通過Web用戶界面啟動、監(jiān)控和調(diào)整,允許彈性的定義要獲取的url。

2.3 crawler4j

crawler4j是Java實現(xiàn)的開源網(wǎng)絡(luò)爬蟲。提供了簡單易用的接口,可以在幾分鐘內(nèi)創(chuàng)建一個多線程網(wǎng)絡(luò)爬蟲。

2.4 WebCollector

WebCollector使用了Nutch的爬取邏輯(分層廣度遍歷),Crawler4j的的用戶接口(覆蓋visit方法,定義用戶操作),以及一套自己的插件機制,設(shè)計了一套爬蟲內(nèi)核。

2.5 WebMagic

WebMagic項目代碼分為核心和擴展兩部分。核心部分(webmagic-core)是一個精簡的、模塊化的爬蟲實現(xiàn),而擴展部分則包括一些便利的、實用性的功能。WebMagic的架構(gòu)設(shè)計參照了Scrapy,目標(biāo)是盡量的模塊化,并體現(xiàn)爬蟲的功能特點。

3. HttpClient&Jsoup

爬蟲實現(xiàn)的技術(shù)有很多,對于java語言來說,有很多的選擇,可以是很多開源的爬蟲框架,也可以使用基本httpClient,Jsoup來爬取網(wǎng)頁

3.1 HttpClient簡介

HttpClient 是 apache 組織下面的一個用于處理 HTTP 請求和響應(yīng)的開源工具。它不是一個瀏覽器,也不處理客戶端緩存等瀏覽器的功能。它只是一個類庫!它在 JDK 的基本類庫基礎(chǔ)上做了更好的封裝。

HttpClient 項目依賴于 HttpCore(處理核心的 HTTP 協(xié)議)、commons-codec(處理與編碼有關(guān)的問題的項目)和 commons-logging(處理與日志記錄有關(guān)問題的項目)。如果你希望能夠通過 HttpClient 向服務(wù)器上傳文件等與 multipart 編碼類型有關(guān)的請求,以及其它復(fù)雜的MIME 類型,那么,你需要另外一個依賴包:HttpMime(它是專門處理與 MIME 類型有關(guān)問題的項目),在下載的 HttpClient 包中(下載地址)已經(jīng)包含了 HttpMime

項目中使用的 HttpClient 版本為:4.0.1GA,httpClient需要有以下依賴包:

httpclient.png
  • httpclient-4.0.1.jar
  • httpcore-4.0.1.jar
  • httpmime-4.0.1.jar

又依賴于 mime4j(apache-mime4j-0.6.jar)

  • commons-codec-1.4.jar
  • commons-logging-1.1.1.jar
  • commons-io-1.4.jar – 為了更方便處理與 IO 有關(guān)的需求

3.2 HttpClient抓取網(wǎng)頁流程

使用HttpClient發(fā)送請求、接收響應(yīng)很簡單,一般需要如下幾步:

  1. 創(chuàng)建HttpClient對象。
  2. 創(chuàng)建請求方法的實例,并指定請求URL。如果需要發(fā)送GET請求,創(chuàng)建HttpGet對象;如果需要發(fā)送POST請求,創(chuàng)建HttpPost對象。
  3. 如果需要發(fā)送請求參數(shù),可調(diào)用HttpGet、HttpPost共同的setParams(HetpParams params)方法來添加請求參數(shù);對于HttpPost對象而言,也可調(diào)用setEntity(HttpEntity entity)方法來設(shè)置請求參數(shù)。
  4. 調(diào)用HttpClient對象的execute(HttpUriRequest request)發(fā)送請求,該方法返回一個HttpResponse。
  5. 調(diào)用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務(wù)器的響應(yīng)頭;調(diào)用HttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務(wù)器的響應(yīng)內(nèi)容。程序可通過該對象獲取服務(wù)器的響應(yīng)內(nèi)容。
  6. 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接。

3.3 簡單抓取代碼

用HttpClient發(fā)送請求,請求頭不帶cookie,用EntityUtils解析響應(yīng)結(jié)果

public class MyHttpClient {
    /***
     * 需求:使用httpClient爬取傳智播客官方網(wǎng)站數(shù)據(jù)
     * 
     * @param args
     * @throws Exception
     * @throws ClientProtocolException
     */
    public static void main(String[] args) throws Exception {

        // 創(chuàng)建HttpClient對象
        HttpClient hClient = new DefaultHttpClient();

        // 設(shè)置響應(yīng)時間,設(shè)置傳智源碼時間,設(shè)置代理服務(wù)器(不使用本機的IP爬取,以防止被服務(wù)器識別從而IP加入黑名單)
        hClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000)
                .setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000)
                .setParameter(ConnRouteParams.DEFAULT_PROXY, new HttpHost("111.155.124.67", 8123));

        // 爬蟲URL大部分都是get請求,創(chuàng)建get請求對象
        HttpGet hget = new HttpGet("http://www.itcast.cn/");
        // 向傳智播客官方網(wǎng)站發(fā)送請求,獲取網(wǎng)頁源碼
        HttpResponse response = hClient.execute(hget);
        // EntityUtils工具類把網(wǎng)頁實體轉(zhuǎn)換成字符串
        String content = EntityUtils.toString(response.getEntity(), "utf-8");
        System.out.println(content);

    }

}

解析結(jié)果

Jsoup網(wǎng)絡(luò)爬蟲

用HttpClient發(fā)送請求,請求頭帶cookie,用EntityUtils解析響應(yīng)結(jié)果

//使用httpClient發(fā)送請求,使用Jsoup分析網(wǎng)頁
public static void main(String[] args) throws Exception {
    //創(chuàng)建httpClient客戶端
    HttpClient hClient = new DefaultHttpClient();
    //創(chuàng)建http發(fā)送請求對象,Httpget
    HttpGet hget = new HttpGet("http://www.itcast.cn");
    //設(shè)置請求頭
    hget.setHeader("Cookie", "login_sid_t=f39c57f474a4fbffeeac8b0d727c7310; " +
            "YF-Ugrow-G0=169004153682ef91866609488943c77f; " +
            "YF-V5-G0=cd5d86283b86b0d506628aedd6f8896e; WBStorage=7754ff192036c629|undefined;" +
            " _s_tentry=-; YF-Page-G0=074bd03ae4e08433ef66c71c2777fd84; " +
            "Apache=1025338456965.9829.1478277156276; " +
            "SINAGLOBAL=1025338456965.9829.1478277156276; " +
            "ULV=1478277156293:1:1:1:1025338456965.9829.1478277156276:; " +
            "SUB=_2AkMvQDcef8NhqwJRmP4Uzm7mbYxwzA_EieLBAH7sJRMxHRl" +
            "-yj9jqmwNtRBn0SIxPIgzk6P4Umq_twX_A70bVg..; " +
            "SUBP=0033WrSXqPxfM72-Ws9jqgMF55529P9D9W5J2ZDKK_Q-h8ni.aX3E1Ci");
    hget.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 " +
            "(KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36");
    //設(shè)置連接超時,傳遞響應(yīng)超時
    hClient.getParams()
            .setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000)
            .setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000)
            .setParameter(ConnRouteParams.DEFAULT_PROXY, new HttpHost("121.31.71.63", 80));
    //發(fā)送請求
    HttpResponse response = hClient.execute(hget);
    //獲取網(wǎng)頁內(nèi)容
    String content = EntityUtils.toString(response.getEntity(), "utf-8");
    System.out.println(content);
}

4. Jsoup簡介

jsoup 是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文本內(nèi)容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于jQuery的操作方法來取出和操作數(shù)據(jù)

通常在寫爬蟲程序時,httpClient結(jié)合Jsoup共同使用即可實現(xiàn)完美的爬蟲系統(tǒng)。httpClient負責(zé)模擬瀏覽器發(fā)送請求,Jsoup負責(zé)解析httpClient請求返回的HTML頁面,解析獲取需要的數(shù)據(jù)

4.1 Jsoup獲取網(wǎng)頁流程

  1. 從一個 URL,文件或字符串中解析 HTML
  2. 使用 DOM 或 CSS 選擇器來查找、取出數(shù)據(jù)
  3. 可操作 HTML 元素、屬性、文本

4.2 Jsoup獲取網(wǎng)頁代碼

用Jsoup抓取傳智播客官網(wǎng)左側(cè)的數(shù)據(jù),如圖所示

Jsoup網(wǎng)絡(luò)爬蟲

用谷歌瀏覽器開發(fā)者工具(F12)打開查看源碼如下圖,從中可以看到ul標(biāo)簽的class選擇器為nav_txt

Jsoup網(wǎng)絡(luò)爬蟲
public class HttpClientJsoup {
    /***
     * 需求:使用httpClient爬取傳智播客官方網(wǎng)站數(shù)據(jù)
     * 
     * @param args
     * @throws Exception
     * @throws ClientProtocolException
     */
    public static void main(String[] args) throws Exception {

        // 創(chuàng)建HttpClient對象
        HttpClient hClient = new DefaultHttpClient();

        // 設(shè)置響應(yīng)時間,設(shè)置傳智源碼時間,設(shè)置代理服務(wù)器
        /*hClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000)
                .setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000)
                .setParameter(ConnRouteParams.DEFAULT_PROXY, new HttpHost("111.155.124.67", 8123));*/

        // 爬蟲URL大部分都是get請求,創(chuàng)建get請求對象
        HttpGet hget = new HttpGet("http://www.itcast.cn/");
        hget.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 " +
                "(KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36");
        // 向傳智播客官方網(wǎng)站發(fā)送請求,獲取網(wǎng)頁源碼
        HttpResponse response = hClient.execute(hget);
        // EntityUtils工具類把網(wǎng)頁實體轉(zhuǎn)換成字符串
        String content = EntityUtils.toString(response.getEntity(), "utf-8");
        // 使用Jsoup解析網(wǎng)頁內(nèi)容
        Document document = Jsoup.parse(content);
        // 獲取文檔標(biāo)題
        String title = document.title();
        System.out.println(title);
        
        Elements elements = document.select("ul.nav_txt a");
        System.out.println(elements);
        for(Element element : elements){
            System.out.println(element.text() + ":" + element.attr("href"));
        }
    }

}

解析結(jié)果

Jsoup網(wǎng)絡(luò)爬蟲

使用jsoup向服務(wù)器發(fā)送請求

public class MyJsoup {
    /*
     * 需求:使用Jsoup解析網(wǎng)頁源碼
     */
    public static void main(String[] args) throws Exception {
        // 使用jsoup向服務(wù)器發(fā)送請求
        Document doc = Jsoup.connect("http://www.itcast.cn").get();
        // Jsoup使用類型css,Jquery選擇器方式獲取元素節(jié)點
        // Elements elements = doc.getElementsByTag("a");
        // System.out.println(elements.text());
        Elements elements = doc.select("ul.nav_txt a");
        // 循環(huán)元素
        for (Element element : elements) {
            System.out.println(element.text() + ":" + element.attr("href"));
        }

    }

}

解析結(jié)果

Jsoup網(wǎng)絡(luò)爬蟲

5. 綜合應(yīng)用

解析下圖中紅色框的內(nèi)容,HttpClient發(fā)送請求,Jsoup解析結(jié)果

Jsoup網(wǎng)絡(luò)爬蟲

點擊開發(fā)者工具的第一個圖標(biāo),移動鼠標(biāo)到網(wǎng)頁的目標(biāo)位置,即可定位到該目標(biāo)的網(wǎng)頁源碼位置

Jsoup網(wǎng)絡(luò)爬蟲
package com.github.webcrawder;

import java.io.IOException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

public class CrawderDemo {
    public static void main(String[] args) throws ClientProtocolException, IOException {
        // 創(chuàng)建httpClient客戶端
        HttpClient hClient = new DefaultHttpClient();
        // 創(chuàng)建http發(fā)送請求對象,Httpget
        HttpGet hget = new HttpGet("http://www.itcast.cn");
        // 發(fā)送請求
        HttpResponse response = hClient.execute(hget);
        // 獲取網(wǎng)頁內(nèi)容
        String content = EntityUtils.toString(response.getEntity(), "utf-8");
        // 使用Jsoup解析網(wǎng)頁內(nèi)容
        Document document = Jsoup.parse(content);
        // 使用元素選擇器選擇網(wǎng)頁的內(nèi)容
        Elements elements = document.select("ul.nav_li a");
        System.out.println(elements.text());
        System.out.println(elements);

    }

}

解析結(jié)果

Jsoup網(wǎng)絡(luò)爬蟲
//使用jsoup加載遠程連接數(shù)據(jù)
@Test
public void myJsouptest() throws Exception {
    String userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like " +
            "Gecko) Chrome/44.0.2403.157 Safari/537.36";
    //準(zhǔn)備cookie信息
    Map<String, String> maps = new HashMap<String, String>();
    maps.put("TC-Ugrow-G0", "968b70b7bcdc28ac97c8130dd353b55e");
    maps.put("SUB", "2AkMvfeeDf8NhqwJRmP0dzGvhZY5yywvEieLBAH7sJRMxHRl-yT9jqmAHtRAgR4BQZgBIE" +
            "-Xz-jsqjVftcUdtrA..");
    maps.put("SUBP", "0033WrSXqPxfM72-Ws9jqgMF55529P9D9WhBu3bohh6dYkXbY_GUs5d8");
    //獲取網(wǎng)頁dom對象
    Document doc = Jsoup.connect("http://www.itcast.cn/")
            .userAgent(userAgent)
            .cookies(maps).get();
    //獲取文檔標(biāo)簽
    String title = doc.title();
    System.out.println(title);
    //獲取網(wǎng)頁元素
    Elements elements = doc.select("div.qrcode-text");
    System.out.println(elements.text());
}

6.爬蟲在電商網(wǎng)站應(yīng)用

代碼下載 http://download.csdn.net/detail/axi295309066/9782505

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • 要玩大數(shù)據(jù),沒有數(shù)據(jù)怎么玩?這里推薦一些33款開源爬蟲軟件給大家。 爬蟲,即網(wǎng)絡(luò)爬蟲,是一種自動獲取網(wǎng)頁內(nèi)容的程序...
    評評分分閱讀 8,137評論 2 121
  • 33款可用來抓數(shù)據(jù)的開源爬蟲軟件工具 要玩大數(shù)據(jù),沒有數(shù)據(jù)怎么玩?這里推薦一些33款開源爬蟲軟件給大家。 爬蟲,即...
    visiontry閱讀 7,688評論 1 99
  • 8.1:早,睡眠,上午尋找借的別人的自行車鑰匙,QQ聊天,午睡,下午,科一,QQ聊天,晚上,大招,讀書 8.2早上...
    葉鳥app閱讀 255評論 0 0
  • 連續(xù)練習(xí)了50天楷書,效果并不怎么顯著,但是漸漸開始享受這個過程。
    思渝州閱讀 405評論 4 3

友情鏈接更多精彩內(nèi)容