技术开发 频道

Java 搜索引擎的实现—— 网络爬虫

  Spider 的设计

  网页收集的过程如同图的遍历,其中网页就作为图中的节点,而网页中的超链接则作为图中的边,通过某网页的超链接 得到其他网页的地址,从而可以进一步的进行网页收集;图的遍历分为广度优先和深度优先两种方法,网页的收集过程也是如此。综上,Spider 收集网页的过程如下:从初始 URL 集合获得目标网页地址,通过网络连接接收网页数据,将获得的网页数据添加到网页库中并且分析该网页中的其他 URL 链接,放入未访问 URL 集合用于网页收集。下图表示了这个过程:

  图 3. Spider 工作流程

  Spider 的具体实现

  网页收集器 Gather

  网页收集器通过一个 URL 来获取该 URL 对应的网页数据,其实现主要是利用 Java 中的 URLConnection 类来打开 URL 对应页面的网络连接,然后通过 I/O 流读取其中的数据,BufferedReader 提供读取数据的缓冲区提高数据读取的效率以及其下定义的 readLine() 行读取函数。代码如下 ( 省略了异常处理部分 ):

  清单 1. 网页数据抓取

URL url = new URL(“http://www.xxx.com”);
URLConnection conn
= url.openConnection();
BufferedReader reader
= new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while((line = reader.readLine()) != null)
    document.append(line
+ "\n");

  使用 Java 语言的好处是不需要自己处理底层的连接操作,喜欢或者精通 Java 网络编程的读者也可以不用上述的方法,自己实现 URL 类及相关操作,这也是一种很好的锻炼。

  网页处理

  收集到的单个网页,需要进行两种不同的处理,一种是放入网页库,作为后续处理的原始数据;另一种是被分析之后,抽取其中的 URL 连接,放入 URL 池等待对应网页的收集。

  网页的保存需要按照一定的格式,以便以后数据的批量处理。这里介绍一种存储数据格式,该格式从北大天网的存储格式简化而来:

  网页库由若干记录组成,每个记录包含一条网页数据信息,记录的存放为顺序添加;

  一条记录由数据头、数据、空行组成,顺序为:头部 + 空行 + 数据 + 空行;

  头部由若干属性组成,有:版本号,日期,IP 地址,数据长度,按照属性名和属性值的方式排列,中间加冒号,每个属性占用一行;

  数据即为网页数据。

  需要说明的是,添加数据收集日期的原因,由于许多网站的内容都是动态变化的,比如一些大型门户网站的首页内容,这就意味着如果不是当天爬取的网页数据,很可能发生数据过期的问题,所以需要添加日期信息加以识别。

  URL 的提取分为两步,第一步是 URL 识别,第二步再进行 URL 的整理,分两步走主要是因为有些网站的链接是采用相对路径,如果不整理会产生错误。URL 的识别主要是通过正则表达式来匹配,过程首先设定一个字符串作为匹配的字符串模式,然后在 Pattern 中编译后即可使用 Matcher 类来进行相应字符串的匹配。实现代码如下:

  清单 2. URL 识别

public ArrayList<URL> urlDetector(String htmlDoc){
    final
String patternString = "<[a|A]\\s+href=([^>]*\\s*>)";          
    Pattern pattern
= Pattern.compile(patternString,Pattern.CASE_INSENSITIVE);  
    ArrayList
<URL> allURLs = new ArrayList<URL>();
    Matcher matcher
= pattern.matcher(htmlDoc);
    
String tempURL;
    
//初次匹配到的url是形如:<a href="http://bbs.life.xxx.com.cn/" target="_blank">
    
//为此,需要进行下一步的处理,把真正的url抽取出来,
    
//可以对于前两个"之间的部分进行记录得到url
    while(matcher.find()){
        try {
            tempURL
= matcher.group();            
            tempURL
= tempURL.substring(tempURL.indexOf("\"")+1);        
            if(!tempURL.contains("\""))
                continue;
            tempURL
= tempURL.substring(0, tempURL.indexOf("\""));        
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
    return allURLs;    
}

         按照“<[a|A]\\s+href=([^>]*\\s*>)”这个正则表达式可以匹配出 URL 所在的整个标签,形如“”,所以在循环获得整个标签之后,需要进一步提取出真正的 URL,我们可以通过截取标签中前两个引号中间的内容来获得这段内容。如此之后,我们可以得到一个初步的属于该网页的 URL 集合。

  接下来我们进行第二步操作,URL 的整理,即对之前获得的整个页面中 URL 集合进行筛选和整合。整合主要是针对网页地址是相对链接的部分,由于我们可以很容易的获得当前网页的 URL,所以,相对链接只需要在当前网页的 URL 上添加相对链接的字段即可组成完整的 URL,从而完成整合。另一方面,在页面中包含的全面 URL 中,有一些网页比如广告网页是我们不想爬取的,或者不重要的,这里我们主要针对于页面中的广告进行一个简单处理。一般网站的广告连接都有相应的显示表达,比如连接中含有“ad”等表达时,可以将该链接的优先级降低,这样就可以一定程度的避免广告链接的爬取。

  经过这两步操作时候,可以把该网页的收集到的 URL 放入 URL 池中,接下来我们处理爬虫的 URL 的派分问题。

0
相关文章