1. 程式人生 > >網路爬蟲系列之二:對下載頁面進行連結解析

網路爬蟲系列之二:對下載頁面進行連結解析

        在我的上一篇部落格中,通過URL就已經成功下載了第一個頁面。然後我第二步的工作就是要通過這個已經下載好的頁面得到更多的URL。

        在這篇部落格中主要完成了對頁面中的連結進行解析,並將它們拼成可以訪問的樣子。更多細緻的工作需要在後面進行完善。

        事實上,這個步驟並不一定需要依靠程式來完成。或許我們可以通過人工來完成這個步驟。甚至通過人工操作,我們可以得到更加相關的連結。但這對於我這樣的程式設計師而言確實是太麻煩了,所以,我想我需要一個程式來幫我完成第二部分,就是從已經下載好的頁面中獲得新的URL連結。

        完成這個步驟之後,就可以從上一篇部落格的例子中進行頁面的下載,並將下載後的頁面讀取之後進行頁面內連結的提取,再下載,再提取,照這樣下去,理論上來說就擁有了整個網際網路上的所有頁面了。

        顯而易見,下一步,也就是下一篇部落格的內容就是講這兩個步驟整合到一個體系中,讓它自己完成爬取工作了。

一、部分程式碼解析

1、使用正則表示式來匹配需要的連結

Pattern p = Pattern.compile("<a\\s+href\\s*=\\s*\"?(.*?)[\"|>]",Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(pageContents.toString());

        通過上面這一小段程式碼可以將頁面中"<a href="xxx.xxx">"中xxx.xxx匹配出來。

        比如說,匹配http://www.csu.edu.cn/,可以得到如下結果:總計35條

... ...
3:xxgk.htm
4:jgsz.htm
5:http://rsc.its.csu.edu.cn/
6:jyjx.htm
......
32:http://news.its.csu.edu.cn/readnewsarticle?atcid=20140401113051853
33:http://news.its.csu.edu.cn/readnewsarticle?atcid=20140402084415418
34:http://news.its.csu.edu.cn/readnewsarticle?atcid=20140401150605872
35:

2、可以看到結果中存在空的連結和重複的連結等可能是不需要的連結(如:第35條),所以還必須在程式碼中進行判斷。(篩選後剩下32條)

3、並且其中有一部分連結地址是相對連結,是不能夠直接訪問到資源的,如:jgsz.htm,這樣的連結必須在前面加上域名、埠等。。

二、程式原始碼

package csdnBlog;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 此類用於解析頁面中存在的連結
 * 
 * @author <span style="color:blue"><b>胡徵南</b></span>
 * 
 */
public class RetrieveLinks {

	public static void main(String[] args) {
		String urlString = "http://www.csu.edu.cn/";
		List<String> links = retrieveLinks(urlString);
		for (int i = 0; i < links.size(); i++) {
			System.out.println(i + 1 + ":" + links.get(i));
		}
	}

	/**
	 * 解析連結
	 * 
	 * @param urlString
	 * @return
	 */
	public static ArrayList<String> retrieveLinks(String urlString) {
		URL url = null;
		try {
			url = new URL(urlString);
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		}

		// 判斷連結是否已經存在
		HashSet<String> crawledList = new HashSet<String>();

		StringBuffer pageContents = new StringBuffer();
		try {
			String fileName = "download.html";
			FileInputStream fis = new FileInputStream(fileName);
			byte[] buffer = new byte[1204];
			while (fis.read(buffer) != -1) {
				String temp = new String(buffer, "utf-8");
				pageContents.append(temp);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// 正則表示式校驗
		Pattern p = Pattern.compile("<a\\s+href\\s*=\\s*\"?(.*?)[\"|>]",
				Pattern.CASE_INSENSITIVE);

		Matcher m = p.matcher(pageContents.toString());

		// 用於儲存查詢到的連結
		ArrayList<String> linkList = new ArrayList<String>();
		while (m.find()) {
			String link = m.group(1).trim();

			// 判斷連結是否合法
			if (link.length() < 1) {
				continue;
			}

			if (link.charAt(0) == '#') {
				continue;
			}

			// 判斷連結是否已經存在
			if (crawledList.contains(link)) {
				continue;
			}
			crawledList.add(link);

			// 將相對地址新增完整
			if (link.indexOf("://") == -1) {
				link = "http://" + url.getHost()
						+ (url.getPort() == -1 ? "" : ":" + url.getPort())
						+ "/" + link;
			}
			linkList.add(link);
		}
		return linkList;
	}
}

三、執行截圖


圖1. 控制檯執行截圖


圖2. 工程目錄截圖

        通過這種方式,就可以從已經下載好的頁面中獲得更多的連結了。

-------------------------------------------------------------------分割線,2014年4月16日更新--------------------------------------------------------------------------

1、將判斷絕對地址的方式改為了使用正則表示式判斷

更新程式碼如下:

package csdnBlog;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 此類用於解析頁面中存在的連結
 * 
 * @author <span style="color:blue"><b>胡徵南</b></span>
 * 
 */

public class RetrieveLinks {

	public static void main(String[] args) {
		String urlString = "http://www.163.com/";
		List<String> links = retrieveLinks(urlString);
		for (int i = 0; i < links.size(); i++) {
			System.out.println(i + 1 + ":" + links.get(i));
		}
	}

	/**
	 * 解析連結
	 * 
	 * @param urlString
	 * @return
	 */
	public static ArrayList<String> retrieveLinks(String urlString) {
		URL url = null;
		try {
			url = new URL(urlString);
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		}

		// 判斷連結是否已經存在
		HashSet<String> crawledList = new HashSet<String>();

		StringBuffer pageContents = new StringBuffer();
		try {
			String fileName = Utils.urlToFileName(urlString);
			FileInputStream fis = new FileInputStream(fileName);
			byte[] buffer = new byte[1204];
			while (fis.read(buffer) != -1) {
				String temp = new String(buffer, "utf-8");
				pageContents.append(temp);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// 正則表示式校驗
		Pattern p = Pattern.compile("<a\\s+href\\s*=\\s*\"?(.*?)[\"|>]",
				Pattern.CASE_INSENSITIVE);

		Matcher m = p.matcher(pageContents.toString());

		// 用於儲存查詢到的連結
		ArrayList<String> linkList = new ArrayList<String>();
		while (m.find()) {
			String link = m.group(1).trim();

			// 判斷連結是否合法
			if (link.length() < 1) {
				continue;
			}

			if (link.charAt(0) == '#') {
				continue;
			}

			// 判斷連結是否已經存在
			if (crawledList.contains(link)) {
				continue;
			}
			crawledList.add(link);

			// 將相對地址新增完整
			// (\w+\.){2}\w+
			Pattern p2 = Pattern.compile("(\\w+\\.){2}\\w+");
			Matcher m2 = p2.matcher(link);
			if (!m2.find()) {
				link = "http://" + url.getHost()
						+ (url.getPort() == -1 ? "" : ":" + url.getPort())
						+ link;
			}

			if (link.indexOf("http://") == -1 && link.indexOf("https://") == -1) {
				link = "http://" + link;
			}
			linkList.add(link);
		}
		return linkList;
	}
}

其中使用到的工具類可以在第一篇部落格中找到。。點此返回上一篇部落格。。

相關程式碼資源下載地址:http://download.csdn.net/detail/huzhengnan/7203185

相關推薦

網路爬蟲系列下載頁面進行連結解析

        在我的上一篇部落格中,通過URL就已經成功下載了第一個頁面。然後我第二步的工作就是要通過這個已經下載好的頁面得到更多的URL。         在這篇部落格中主要完成了對頁面中的連結進行解析,並將它們拼成可以訪問的樣子。更多細緻的工作需要在後面進行完善。  

【只怕沒有幾個人能說清楚】系列Unity中的特殊文件夾

物體 avi ebp time 編輯模式 tro hive 預覽 打包 參考:http://www.manew.com/thread-99292-1-1.html 1. 隱藏文件夾 以.開頭的文件夾會被忽略。在這種文件夾中的資源不會被導入,腳本不會被編譯。也不會出現

緩存系列CDN與其他層面緩存

級別 spl pecl apache 分布式緩存 -o 真實ip har 分享 緩存系列之二:CDN與其他層面緩存 一:內容分發網絡(Content Delivery Network),通過將服務內容分發至全網加速節點,利用全球調度系統使用戶能夠就近獲取,有效降低訪問延遲,

數據庫面試系列視圖

名稱 獨立 建立 數據庫 有用 圖的定義 適合 場景 多個 視圖的定義:視圖是一個或者多個基本表(或者視圖)導出的表。 視圖是一張虛表,視圖的數據並不實際存儲 視圖的優點: 1.視圖可以簡化用戶的操作 2.視圖可以讓用戶從多個角度來看待同一數據 3.視圖提供一定的數據邏輯獨

.Neter玩轉Linux系列Linux下的文件目錄及文件目錄的權限

pac linux 在那 用戶 目錄結構 重要 bsp 樹狀 hub 一、Linux下的文件目錄 簡介:linux的文件系統是采用級層式的樹狀目錄結構,在此 結構中的最上層是根目錄“/”,然後在此目錄下再創建 其他的目錄。深刻理解linux文件目錄是

SDS趨勢象存儲將替代文件存儲

sds 對象存儲 首先什麽是對象存儲?對象存儲(Object Storage)是綜合了NAS和SAN的優點,同時具有SAN的高速直接訪問和NAS的數據共享等優勢,提供了高可靠性、跨平臺性以及安全的數據共享的存儲體系結構。典型應用:網盤、雲存儲。上篇文章也講到了隨著科技的發展和網絡技術的進步,計算機存儲

Https系列https的SSL證書在服務器端的部署,基於tomcat,spring boot

onf 基於 分享 height 轉化 自簽名 size class ont 一:本文的主要內容介紹 CA證書的下載及相應文件的介紹 CA證書在tomcat的部署 CA證書在spring boot的部署 自簽名證書的部署 二:一些內容的回顧 在Https系列之一中已介

Exchange 2013系列AD部署

Windows Exchange Microsoft 打開網絡和共享中心,右鍵網卡選擇屬性;選擇IPV4,點擊屬性;輸入IP地址、子網掩碼、網關及DNS,點擊確定;打開服務器管理器,點擊計算機名;點擊更改;輸入計算機名後點擊確定;重啟電腦;重啟完畢後,打開服務器管理器,在管理菜單中選擇添加角色和功

Kylin系列原理介紹

集群 盡心 idt 理解 數據存儲 tableau 定時 hadoop 探索 Kylin系列之二:原理介紹 2018年4月15日 15:52 因何而生 Kylin和hive的區別 1. hive主要是離線分析平臺,適用於已經有成熟的報表體系,每天只要定時運行即可。 2. K

CMake系列入門案例-單個源文件

bubuko 源文件 註釋 http 編寫 AD 源碼 power 比較 編寫一個源碼文件 如下 1 #include<stdio.h> 2 #include<stdlib.h> 3 4 double power(double

Aways on故障系列從數據庫中有一臺無法同步

系列 意思 ip地址 pin 啟動服務 阿裏雲服務 無法連接 聯通 狀態 服務器用的阿裏雲服務器,自己做的非域Aways On主從同步。 故障描述:某臺從數據庫無法同步主數據庫的數據,查看Aways On的服務器狀態,該服務器已離線。 故障排查:     1.檢查同步面板,

分析系列jstack生成的Thread Dump日誌結構解析

上一篇文章講述瞭如何使用jstack生成日誌檔案,這篇文章首先對Thread Dump日誌檔案的結構進行分析。 目錄 [隱藏] 1 第一部分:Full thread dump identifier 2 第二部分:Java EE middleware, third party &a

“陶華碧”該不該融資系列坐莊的方程式,錯誤的市值管理是怎樣毀滅創業者的

http://www.eeo.com.cn/2018/1121/341590.shtml “陶華碧”該不該融資系列之二:坐莊的方程式,錯誤的市值管理是怎樣毀滅創業者的 2018-11-21     經濟觀察網   鄒衛國/文    近日

Docker入門系列使用dockerfile製作包含指定web應用的映象

實現題目描述的這個需求有很多種辦法,作為入門,讓我們從最簡單的辦法開始。 首先使用命令docker ps確保當前沒有正在執行的Docker例項。 執行命令docker run -it nginx: 然後我們另外開一個終端,用docker ps命令檢視這個執行起來的容器例項,Status的Up 54 s

「數據治理那點事」系列手握數據「戶口本」,數據治理肯定穩!

物理 系列 數據對比 概念 決策者 等等 ges mode 架構 這篇文章主要從數據治理的基礎和核心之一:元數據 入手,從以下幾個角度展開具體講解: 元數據概念元數據的分布和采集元數據的一些實際應用場景. 1.元數據到底是個啥? 如果我說:元數據(Meta Data),就是

前端安全系列如何防止CSRF攻擊?

背景 隨著網際網路的高速發展,資訊保安問題已經成為企業最為關注的焦點之一,而前端又是引發企業安全問題的高危據點。在移動網際網路時代,前端人員除了傳統的 XSS、CSRF 等安全問題之外,又時常遭遇網路劫持、非法呼叫 Hybrid API 等新型安全問題。當然,

skyfans每天一個Liunx命令系列uptime

此係列針對於初學者能夠更好的學習linux來編寫的內容,為了方便學習,文章裡會詳細的介紹每一個命令,當然,都是實際工作中常用的命令。 今天我們繼續來學習SYSTEM INFORMATION(系統資訊命令),今天學習的是什麼命令呢,那就是uptime。 針對於初學

Docker系列Docker 入門

啟動和停止Docker 服務 sudo service docker stop systemctl stop docker.service sudo service docker start systemctl start docker.service 檢視docker

三叔學FPGA系列Cyclone V中的POR、配置、初始化,以及復位

對於FPGA內部的復位,之前一直比較迷,這兩天仔細研究官方資料手冊,解開了心中的諸多疑惑,感覺自己又進步了呢.....  一、關於POR(Power-On Reset ) FPGA在上電工作時,會先進入復位模式,將所有RAM位清除,並通過內部弱上拉電阻將使用者I/O置為三態。接著依次完成 配置、初始化工

輕鬆上雲系列其他雲資料遷移至阿里雲

本文件圍繞如何將您其他雲廠商上的資料遷移到阿里雲,提供了多個場景的實踐方案。 文件合集 AWS 資料遷移至阿里雲 Amazon S3資料遷移到OSS 從AWS RDS遷移MySQL到阿里雲RDS AWS S3遷移到OSS(線上遷移服務) Azure資料遷移至阿里