Java網絡爬蟲基礎知識

引言

Java 網絡爬蟲具有很好的擴展性可伸縮性,其是目前搜索引擎開發的重要組成部分。例如,著名的網絡爬蟲工具 Nutch 便是採用 Java 開發,該工具以 Apache Hadoop 數據結構爲依託,提供了良好的批處理支持。

Java 網絡爬蟲涉及到 Java 的很多知識。本篇中將會介紹網絡爬蟲中需要了解的 Java 知識以及這些知識主要用於網絡爬蟲的哪一部分,具體包括以下內容:

  • Maven 的使用;
  • log4j 的使用;
  • 對象的創建;
  • 集合的使用;
  • 正則表達式的使用;
  • HTTP 狀態碼;
  • 其他。

Maven 的使用

Maven 是什麼

Maven 是由 Apache 軟件基金會所提供一款工具,用於項目管理及自動構建。我們知道在構建一個 Java 工程時,需要使用到很多 Jar 包,例如操作數據庫需要使用到 mysql-connector-java 以及其相關依賴的 Jar 包。而 Maven 工具便可以很方便的對我們在項目中使用到的開源 Jar 包,進行很好的管理,比如下載某 Java 工程需要的 Jar 包及相關依賴 Java 包。

Maven 如何使用

Maven 使用項目對象模型(Project Object Model,POM)來配置,項目對象模型存儲在名爲 pom.xml 的文件中。以 Java 爲例,我們可以在 Eclipse 中創建一個 Maven 工程。其中,Maven Dependencies 便存放着由 Maven 管理的 Jar 包。

Java網絡爬蟲基礎知識

正如前面所說,構建一個 Java 工程需要使用很多 Jar 包,比如,在 Java 網絡爬蟲中,我們需要用到數據庫連接、請求網頁內容、解析網頁內容的相關 Jar 包時,我們可以在上圖所示的 pom 文件中添加如下語句:

mysql

mysql-connector-java

5.1.35

org.jsoup

jsoup

1.8.2

org.apache.httpcomponents

httpclient

4.2.3

之後,我們會驚訝地發現,工程的 Maven Dependencies 中自動下載了相關 Jar 包以及其依賴的 Jar 包。

Java網絡爬蟲基礎知識

讀者可以在 Maven Repository 網站中檢索自己想要的 Jar 包,以及 Maven 操作語句。

Java網絡爬蟲基礎知識

log4j 的使用

log4j 是什麼

log4j 是一個基於 Java 的日誌記錄工具,曾是 Apache 軟件基金會的一個項目。目前,日誌是應用軟件中不可或缺的部分。

log4j 怎麼使用

1. 使用 Maven 下載 log4j 的 Jar 包,代碼如下:

log4j

log4j

1.2.17

2. 在 src 目錄下創建 log4j.properties 文本文件,並做相關配置(關於每個配置的具體含義,讀者可參考博文 《詳細的 Log4j 使用教程》):

### 設置###

log4j.rootLogger = debug,stdout,D,E

### 輸出信息到控制擡 ###

log4j.appender.stdout = org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target = System.out

log4j.appender.stdout.layout = org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 輸出DEBUG 級別以上的日誌到=error.log ###

log4j.appender.D = org.apache.log4j.DailyRollingFileAppender

log4j.appender.D.File = E://logs/log.log

log4j.appender.D.Append = true

log4j.appender.D.Threshold = DEBUG

log4j.appender.D.layout = org.apache.log4j.PatternLayout

log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

### 輸出ERROR 級別以上的日誌到=error.log ###

log4j.appender.E = org.apache.log4j.DailyRollingFileAppender

log4j.appender.E.File =E://logs/error.log

log4j.appender.E.Append = true

log4j.appender.E.Threshold = ERROR

log4j.appender.E.layout = org.apache.log4j.PatternLayout

log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

3. 實例程序,如下所示:

package log4j;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class Test {

static final Log logger = LogFactory.getLog(Test.class);

public static void main(String[] args) {

System.out.println("hello");

logger.info("hello world");

logger.debug("This is debug message.");

logger.warn("This is warn message.");

logger.error("This is error message.");

}

}

基於此程序,我們就可以看到在我們工程的根目錄下會產生一個日誌文件 error.log 和 log.log。

Java網絡爬蟲基礎知識

在網絡爬蟲中,我們可以使用日誌記錄程序可能出錯的地方,監控程序的運行狀態。

對象的創建

在 Java 中,經常使用 new 關鍵字來創建一個對象。例如,在爬取京東商品的id、product_name(商品名稱)、price(價格)時,我們需要將每個商品的信息封裝到對象裏。

JdInfoModel jingdongproduct = new JdInfoModel();

在爬蟲中,我們要操作 JdInfoModel 類中的變量(即id、product_name、price),可以使用 private 變量定義的方式。並且,使用 set() 與 get() 方法對數據進行設置(爬取數據的封裝)和獲取使用(爬取數據的存儲)。下面的代碼爲 JdInfoModel 類:

package model;

public class JdInfoModel {

private int id;

private String product_name;

private double price;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getProduct_name() {

return product_name;

}

public void setProduct_name(String product_name) {

this.product_name = product_name;

}

public double getPrice() {

return price;

}

public void setPrice(double price) {

this.price = price;

}

}

集合的使用

網絡爬蟲離不開對集合的操作,這裏涉及到 List、Set、Queue、Map 等集合的操作。

List 和 Set 集合的使用

List 的特徵是其元素以線性方式存儲,集合中可以存放重複對象。對比而言,Set 集合中的對象不按特定的方式排序,並且沒有重複對象。在網絡爬蟲中,可以使用 List 存儲待爬的 URL 列表。例如:

//List集合的創建

List urllist = new ArrayList();

urllist.add("https://movie.douban.com/subject/27608425");

urllist.add("https://movie.douban.com/subject/26968024");

//第一種遍歷方式

for( String url : urllist ){

System.out.println(url);

}

//第二種遍歷方式

for( int i=0; i

System.out.println(i+":"+urllist.get(i));

}

//第三種遍歷方式

Iterator it = urllist.iterator();

while ( it.hasNext() ){

System.out.println(it.next());

}

同時我們也可以使用上面 List 來封裝具體的實例,即爬蟲所採集到的數據。Set 集合的使用與 List 集合類似,這裏就不過多講解了。

Map 的使用

Map 是一種把鍵對象和值對象進行映射的集合,它的每一個元素都包含一對鍵對象和值對象,其中鍵對象不可以重複。Map 不僅在網絡爬蟲中常用,也常在文本挖掘算法的編寫中使用。在網絡爬蟲中,可以使用 Map 過濾一些重複數據,但並建議使用 Map 對大規模數據去重過濾,原因是 Map 有空間大小的限制。比如,使用網絡爬蟲爬取帖子時,可能遇到置頂帖,而置頂帖可能會與下面的帖子重複出現。以下程序爲 Map 的使用案例:

//Map的創建

Map map = new HashMap();

//值的添加,這裏假設是爬蟲中的產品id以及每個產品id對應的銷售量

map.put("jd1515", 100);

map.put("jd1516", 300);

map.put("jd1515", 100);

map.put("jd1517", 200);

map.put("jd1518", 100);

//第一種方法遍歷

for (String key : map.keySet()) {

Integer value = map.get(key);

System.out.println("Key = " + key + ", Value = " + value);

}

//第二種方法遍歷

Iterator> entries = map.entrySet().iterator();

while (entries.hasNext()) {

Entry entry = entries.next();

System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());

}

//第三種方法遍歷

for (Entry entry : map.entrySet()) {

System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());

}

Queue 的使用

隊列(Queue)使用鏈表結構存儲數據,是一種特殊的線性表,它只允許在表的前端進行刪除操作,而在表的後端進行插入操作。LinkedList 類實現了 Queue 接口,因此我們可以把 LinkedList 當成 Queue 來用。Queue 常用來存待爬 URL 隊列。

Queue queue = new LinkedList();

//添加元素

queue.offer("https://www.douban.com/people/46077896/likes/topic/");

queue.offer("https://www.douban.com/people/1475408/likes/topic");

queue.offer("https://www.douban.com/people/3853295/likes/topic/");

boolean t = true;

while (t) {

//如果Url隊列爲空,停止執行程序,否則請求Url

if( queue.isEmpty() ){

t = false;

}else {

//請求的url

String url = queue.poll();

System.out.println(url);

//這裏要寫請求數據,獲取相應狀態碼,如果狀態碼爲200,則解析數據;如果爲404,url移除隊列;否則該url重新如列

}

正則表達式的使用

正則表達式,是在解析數據(HTML 或 JSON 等)時,常用的方法。舉個列子,我想從下面的語句中提取用戶的 id(75975500):

尊少來自瀋陽

後面,我會介紹解析工具 jsoup,其可以解析獲得“//i.autohome.com.cn/75975500”。接着,便可以使用正則表達式提取 75975500。

String url = "//i.autohome.com.cn/75975500";

String user_id = url.replaceAll("\\D", ""); //取代所有的非數字字符

System.out.println(user_id); //輸出的結果即爲75975500

如下表所示,是 Java 中一些常用的基本正則表達式。

Java網絡爬蟲基礎知識

HTTP 狀態碼

當瀏覽者訪問一個網頁時,瀏覽者的瀏覽器會向網頁所在服務器發出請求。當瀏覽器接收並顯示網頁前,此網頁所在的服務器會返回一個包含 HTTP 狀態碼的信息頭(Server Header)用以響應瀏覽器的請求。在網絡爬蟲向後臺請求一個 URL 地址時,便會返回狀態碼,該狀態碼中包含豐富的信息。例如,200表示請求成功,成功獲取到了後臺傳的數據(HTML 或 JSON 等);301資源(網頁等)被永久轉移到其它 URL;404請求的資源(網頁等)不存在等。以下是 HTTP 狀態碼的分類。

分類描述1**信息,服務器收到請求,需要請求者繼續執行操作。2**成功,操作被成功接收並處理。3**重定向,需要進一步的操作以完成請求。4**客戶端錯誤,請求包含語法錯誤或無法完成請求。5**服務器錯誤,服務器在處理請求的過程中發生了錯誤。

詳細的 HTTP 狀態碼列表,讀者可以參考這個地址。

其他

另外,網絡爬蟲還涉及到其他方面的 Java 知識,比如說Java 輸入輸出流、Java 操作數據庫、Java 多線程操作、Java 對日期的處理、Java 中的接口與繼承。所以,以網絡爬蟲,入門 Java 編程是非常好的方式。

相关文章