Java 網絡爬蟲具備很好的擴展性可伸縮性,其是目前搜索引擎開發的重要組成部分。例如,著名的網絡爬蟲工具 Nutch 即是採用 Java 開發,該工具以 Apache Hadoop 數據結構爲依託,提供了良好的批處理支持。前端
Java 網絡爬蟲涉及到 Java 的不少知識。本篇中將會介紹網絡爬蟲中須要瞭解的 Java 知識以及這些知識主要用於網絡爬蟲的哪一部分,具體包括如下內容:java
Maven 是由 Apache 軟件基金會所提供一款工具,用於項目管理及自動構建。咱們知道在構建一個 Java 工程時,須要使用到不少 Jar 包,例如操做數據庫須要使用到 mysql-connector-java 以及其相關依賴的 Jar 包。而 Maven 工具即可以很方便的對咱們在項目中使用到的開源 Jar 包,進行很好的管理,好比下載某 Java 工程須要的 Jar 包及相關依賴 Java 包。mysql
Maven 使用項目對象模型(Project Object Model,POM)來配置,項目對象模型存儲在名爲 pom.xml 的文件中。以 Java 爲例,咱們能夠在 Eclipse 中建立一個 Maven 工程。其中,Maven Dependencies 便存放着由 Maven 管理的 Jar 包正則表達式
正如前面所說,構建一個 Java 工程須要使用不少 Jar 包,好比,在 Java 網絡爬蟲中,咱們須要用到數據庫鏈接、請求網頁內容、解析網頁內容的相關 Jar 包時,咱們能夠在上圖所示的 pom 文件中添加以下語句:算法
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.35</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version> 1.8.2</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient </artifactId> <version> 4.2.3</version> </dependency>
以後,咱們會驚訝地發現,工程的 Maven Dependencies 中自動下載了相關 Jar 包以及其依賴的 Jar 包。sql
讀者能夠在 Maven Repository 網站中檢索本身想要的 Jar 包,以及 Maven 操做語句。數據庫
log4j 是一個基於 Java 的日誌記錄工具,曾是 Apache 軟件基金會的一個項目。目前,日誌是應用軟件中不可或缺的部分。apache
1. 使用 Maven 下載 log4j 的 Jar 包,代碼以下:編程
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
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 中,常用 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<String>
存儲待爬的 URL 列表。例如:
//List集合的建立 List<String> urllist = new ArrayList<String>(); 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<urllist.size(); i++ ){ System.out.println(i+":"+urllist.get(i)); } //第三種遍歷方式 Iterator<String> it = urllist.iterator(); while ( it.hasNext() ){ System.out.println(it.next()); }
同時咱們也可使用上面 List<JdInfoModel>
來封裝具體的實例,即爬蟲所採集到的數據。Set 集合的使用與 List 集合相似,這裏就不過多講解了。
Map 是一種把鍵對象和值對象進行映射的集合,它的每個元素都包含一對鍵對象和值對象,其中鍵對象不能夠重複。Map 不只在網絡爬蟲中經常使用,也常在文本挖掘算法的編寫中使用。在網絡爬蟲中,可使用 Map 過濾一些重複數據,但並建議使用 Map 對大規模數據去重過濾,緣由是 Map 有空間大小的限制。好比,使用網絡爬蟲爬取帖子時,可能遇到置頂帖,而置頂帖可能會與下面的帖子重複出現。如下程序爲 Map 的使用案例:
//Map的建立 Map<String,Integer> map = new HashMap<String,Integer>(); //值的添加,這裏假設是爬蟲中的產品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<Entry<String, Integer>> entries = map.entrySet().iterator(); while (entries.hasNext()) { Entry<String, Integer> entry = entries.next(); System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } //第三種方法遍歷 for (Entry<String, Integer> entry : map.entrySet()) { System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue()); }
隊列(Queue)使用鏈表結構存儲數據,是一種特殊的線性表,它只容許在表的前端進行刪除操做,而在表的後端進行插入操做。LinkedList 類實現了 Queue 接口,所以咱們能夠把 LinkedList 當成 Queue 來用。Queue 經常使用來存待爬 URL 隊列。
Queue<String> queue = new LinkedList<String>(); //添加元素 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):
<a href="//i.autohome.com.cn/75975500" target="_blank" class="linkblack">尊少來自瀋陽</a>
後面,我會介紹解析工具 jsoup,其能夠解析得到「//http://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 中一些經常使用的基本正則表達式。
正則表達式寫法含義\d表明0-9的任意數字\D表明任何非數字字符\s表明空格類字符\S表明非空格類字符\p{Lower}表明小寫字母[a-z]\p{Upper}表明大寫字母[A-Z]\p{Alpha}表明字母\p{Blank}表明空格或製表符
當瀏覽者訪問一個網頁時,瀏覽者的瀏覽器會向網頁所在服務器發出請求。當瀏覽器接收並顯示網頁前,此網頁所在的服務器會返回一個包含 HTTP 狀態碼的信息頭(Server Header)用以響應瀏覽器的請求。在網絡爬蟲向後臺請求一個 URL 地址時,便會返回狀態碼,該狀態碼中包含豐富的信息。例如,200表示請求成功,成功獲取到了後臺傳的數據(HTML 或 JSON 等);301資源(網頁等)被永久轉移到其它 URL;404請求的資源(網頁等)不存在等。如下是 HTTP 狀態碼的分類。
分類描述1**信息,服務器收到請求,須要請求者繼續執行操做。2**成功,操做被成功接收並處理。3**重定向,須要進一步的操做以完成請求。4**客戶端錯誤,請求包含語法錯誤或沒法完成請求。5**服務器錯誤,服務器在處理請求的過程當中發生了錯誤。
詳細的 HTTP 狀態碼列表,讀者能夠參考這個地址。
另外,網絡爬蟲還涉及到其餘方面的 Java 知識,好比說Java 輸入輸出流、Java 操做數據庫、Java 多線程操做、Java 對日期的處理、Java 中的接口與繼承。因此,以網絡爬蟲,入門 Java 編程是很是好的方式。
PS: 獲取更多Java知識加QQ架構羣: 811013226