天天看点

网络爬虫系列之二:对下载页面进行链接解析

        在我的上一篇博客中,通过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" target="_blank" rel="external nofollow" >"中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