网络爬虫_网络爬虫简介

2020-02-27 其他范文 下载本文

网络爬虫由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“网络爬虫简介”。

查看文章

Java 搜索引擎的实现—— 网络爬虫(1)2011年01月04日 星期二 14:43Java 搜索引擎的实现—— 网络爬虫

【IT168 技术】自己动手写一个搜索引擎,想想这有多 cool:在界面上输入关键词,点击搜索,得到自己想要的结果;那么它还可以做什么呢?也许是自己的网站需要一个站内搜索功能,抑或是对于硬盘中文档的搜索 —— 最重要的是,是不是觉得众多 IT 公司都在向你招手呢?如果你心动了,那么,Let's Go!

这里首先要说明使用 Java 语言而不是 C/C++ 等其它语言的原因,因为 Java 中提供了对于网络编程众多的基础包和类,比如 URL 类、InetAddre 类、正则表达式,这为我们的搜索引擎实现提供了良好的基础,使我们可以专注于搜索引擎本身的实现,而不需要因为这些基础类的实现而分心。

这个分三部分的系列将逐步说明如何设计和实现一个搜索引擎。在第一部分中,您将首先学习搜索引擎的工作原理,同时了解其体系结构,之后将讲解如何实现搜索引擎的第一部分,网络爬虫模块,即完成网页搜集功能。在系列的第二部分中,将介绍预处理模块,即如何处理收集来的网页,整理、分词以及索引的建立都在这 部分之中。在系列的第三部分中,将介绍信息查询服务的实现,主要是查询界面的建立、查询结果的返回以及快照的实现。

dySE 的整体结构

在开始学习搜索引擎的模块实现之前,您需要了解 dySE 的整体结构以及数据传输的流程。事实上,搜索引擎的三个部分是相互独立的,三个部分分别工作,主要的关系体现在前一部分得到的数据结果为后一部分提供原始数据。三者的关系如下图所示:

图 1.搜索引擎三段式工作流程

在介绍搜索引擎的整体结构之前,我们借鉴《计算机网络——自顶向下的方法描述因特网特色》一书的叙事方法,从普通用户使用搜索引擎的角度来介绍搜索引擎的具体工作流程。

自顶向下的方法描述搜索引擎执行过程:

用户通过浏览器提交查询的词或者短语 P,搜索引擎根据用户的查询返回匹配的网页信息列表 L;

上述过程涉及到两个问题,如何匹配用户的查询以及网页信息列表从何而来,根据什么而排序?用户的查询 P 经过分词器被切割成小词组 并被剔除停用词(的、了、啊等字),根据系统维护的一个倒排索引可以查询某个词 pi 在哪些网页中出现过,匹配那些 都出现的网页集即可作为初始结果,更进一步,返回的初始网页集通过计算与查询词的相关度从而得到网页排名,即 Page Rank,按照网页的排名顺序即可得到最终的网页列表;

假设分词器和网页排名的计算公式都是既定的,那么倒排索引以及原始网页集从何而来?原始网页集在之前的数据流程的介绍中,可以得知是由爬虫 spider 爬取网页并且保存在本地的,而倒排索引,即词组到网页的映射表是建立在正排索引的基础上的,后者是分析了网页的内容并对其内容进行分词后,得到的网页到词组的映射表,将正排索引倒置即可得到倒排索引;

网页的分析具体做什么呢?由于爬虫收集来的原始网页中包含很多信息,比如 html 表单以及一些垃圾信息比如广告,网页分析去除这些信息,并抽取其中的正文信息作为后续的基础数据。

在有了上述的分析之后,我们可以得到搜索引擎的整体结构如下图:

图 2.搜索引擎整体结构

爬虫从 Internet 中爬取众多的网页作为原始网页库存储于本地,然后网页分析器抽取网页中的主题内容交给分词器进行分词,得到的结果用索引器建立正排和倒排索引,这样就得到了索引数据库,用户查询时,在通过分词器切割输入的查询词组并通过检索器在索引数据库中进行查询,得到的结果返回给用户。

无论搜索引擎的规模大小,其主要结构都是由这几部分构成的,并没有大的差别,搜索引擎的好坏主要是决定于各部分的内部实现。

有了上述的对与搜索引擎的整体了解,我们来学习 dySE 中爬虫模块的具体设计和实现。

Spider 的设计

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

图 3.Spider 工作流程

Spider 的具体实现

网页收集器 Gather

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

清单 1.网页数据抓取

URL url = new URL(“http://”);

URLConnection conn = url.openConnection();

BufferedReader reader = new BufferedReader(newInputStreamReader(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 urlDetector(String htmlDoc){

final String patternString = “]*s*>)”;

Pattern pattern =Pattern.compile(patternString,Pattern.CASE_INSENSITIVE);

ArrayList allURLs = newArrayList();

Matcher matcher = pattern.matcher(htmlDoc);

String tempURL;

//初次匹配到的url是形如://为此,需要进行下一步的处理,把真正的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;

}

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

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

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

读取: BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(File file), “UTF-8”));

写入: BufferedWriter bw = new BufferedWriter(new

OutputStreamWriter(new FileOutputStream(File file), “UTF-8”));

不包BufferedWriter和BufferedReader一层,也可以达到解决中文乱码问题的目的.参考下面J2SE6中关于 InputStreamReader 和 OutputStreamWriter 的解析

*************************************************************public cla OutputStreamWriterextends Writer

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

每次调用 write()方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write()方法的字符没有缓冲。

为了获得最高效率,可考虑将 OutputStreamWriter 包装到

BufferedWriter 中,以避免频繁调用转换器。例如:

Writer out

= new BufferedWriter(new OutputStreamWriter(System.out));

代理对 是一个字符,它由两个 char 值序列表示:高 代理项的范围为 'uD800' 到 'uDBFF',后跟范围为 'uDC00' 到 'uDFFF' 的低 代理项。错误代理元素 指的是后面不跟低代理项的高代理项,或前面没有高代理项的低代理项。

此类总是使用字符集的默认替代序列 替代错误代理元素和不可映射的字符序列。如果需要更多地控制编码过程,则应该使用 CharsetEncoder 类。

*******************************************************************public cla InputStreamReaderextends Reader

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

每次调用 InputStreamReader 中的一个 read()方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

为了达到最高效率,可要考虑在 BufferedReader 内包装

InputStreamReader。例如:

BufferedReader in

= new BufferedReader(new InputStreamReader(System.in));

《网络爬虫.docx》
将本文的Word文档下载,方便收藏和打印
推荐度:
网络爬虫
点击下载文档
相关专题 网络爬虫简介 爬虫 网络 网络爬虫简介 爬虫 网络
[其他范文]相关推荐
    [其他范文]热门文章
      下载全文