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

来源:互联网 发布:搜狗大数据 编辑:程序博客网 时间:2024/05/22 11:49

        在我的上一篇博客中,通过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.htm4:jgsz.htm5:http://rsc.its.csu.edu.cn/6:jyjx.htm......32:http://news.its.csu.edu.cn/readnewsarticle?atcid=2014040111305185333:http://news.its.csu.edu.cn/readnewsarticle?atcid=2014040208441541834:http://news.its.csu.edu.cn/readnewsarticle?atcid=2014040115060587235:

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

7 0