java爬虫抓取网页数据(Spider的设计网页收集的过程(一)_光明网)
优采云 发布时间: 2022-03-04 09:18java爬虫抓取网页数据(Spider的设计网页收集的过程(一)_光明网)
蜘蛛的设计
网页采集的过程就像遍历一个图,其中网页作为图中的节点,网页中的超链接作为图中的边。通过网页的超链接可以获取其他网页的地址,从而可以进行进一步的网页采集。; 图遍历分为广度优先和深度优先方法,网页的采集过程也是如此。综上所述,蜘蛛采集网页的过程如下:从初始URL集合中获取目标网页地址,通过网络连接接收网页数据,将获取的网页数据添加到网页库,分析其他网页中的 URL 链接,放在未访问的 URL 集合中,用于网页采集。下图表示此过程:
图3. 蜘蛛工作流
Spider的具体实现
网络采集器采集
网页采集器通过URL获取该URL对应的网页数据。它的实现主要是利用Java中的URLConnection类打开URL对应的页面的网络连接,然后通过I/O流读取数据。BufferedReader 提供读取数据缓冲区,提高数据读取效率,其下定义的 readLine() 行读取函数。代码如下(异常处理部分省略):
列表1.网页抓取
网址 url=newURL("");
URLConnection conn=url.openConnection();
BufferedReader reader=newBufferedReader(newInputStreamReader(conn.getInputStream()));Stringline=null;while((line=reader.readLine()) !=null)
document.append(line+"\n");
使用Java语言的好处是不需要自己去处理底层的连接操作。喜欢或精通Java网络编程的读者,不用上述方法也能实现URL类及相关操作,也是一个很好的练习。
网页处理
采集到的单个网页需要以两种不同的方式进行处理。一是将其作为原创数据放入网页库中进行后续处理;另一种是解析后提取URL连接,放入URL池等待对应的网页。采集。
网页需要以一定的格式保存,以便以后可以批量处理数据。这里是一种存储数据格式,是从北大天网的存储格式简化而来的:
网页库由多条记录组成,每条记录收录一条网页数据信息,记录存储以便添加;
一条记录由数据头、数据和空行组成,顺序为:表头+空行+数据+空行;
头部由几个属性组成,包括:版本号、日期、IP地址、数据长度,以属性名和属性值的方式排列,中间加一个冒号,每个属性占一行;
数据是网页数据。
需要注意的是,之所以加上数据采集日期,是因为很多网站的内容是动态变化的,比如一些大型门户网站的首页内容网站,也就是说如果不爬取同日 对于网页数据,很可能会出现数据过期的问题,所以需要添加日期信息来识别。
URL的提取分为两步。第一步是识别URL,第二步是组织URL。这两个步骤主要是因为 网站 的一些链接使用了相对路径。如果它们没有排序,就会出现错误。. URL的标识主要是通过正则表达式来匹配的。该过程首先将一个字符串设置为匹配字符串模式,然后在Pattern中编译后使用Matcher类匹配对应的字符串。实现代码如下:
列表2. URL 识别
publicArrayListurlDetector(StringhtmlDoc){
finalStringpatternString="]*\s*>)";
模式 pattern=pile(patternString,Pattern.CASE_INSENSITIVE);
ArrayListallURLs=newArrayList();
Matcher matcher=pattern.matcher(htmlDoc);StringtempURL;//第一次匹配的url格式为://为此需要进行下一步处理提取真实的url,//可以使用对于前两个 " 中间的部分被记录下来得到 urlwhile(matcher.find()){
尝试 {
tempURL=matcher.group();
tempURL=tempURL.substring(tempURL.indexOf(""")+1);if(!tempURL.contains("""))继续;
tempURL=tempURL.substring(0, tempURL.indexOf("""));} catch (MalformedURLException e) {
e.printStackTrace();
}
}
返回所有网址;
}
根据正则表达式“]*\s*>)”可以匹配到URL所在的整个标签,形式为“”,所以在循环获取整个标签后,我们需要进一步提取真实网址。我们可以截取标签中前两个引号之间的内容来得到这个内容。在此之后,我们可以得到属于该网页的一组初步 URL。
接下来我们进行第二步,URL的排序,也就是对之前获取的整个页面中的URL集合进行过滤和整合。集成主要针对网页地址为相对链接的部分。由于我们可以很方便的获取当前网页的URL,所以相对链接只需要在当前网页的URL上加上一个相对链接字段就可以形成一个完整的URL,从而完成整合。另一方面,在页面所收录的综合URL中,也有一些我们不想抓取或者不重要的网页,比如广告网页。这里我们主要关注页面中广告的简单处理。一般网站的广告链接都有相应的展示表达方式。例如,当链接收录诸如“
完成这两步之后,就可以将采集到的网页URL放入URL池中,然后我们来处理爬虫URL的分配。
调度员调度员
分配器管理URL,负责保存URL池,在Gather拿到某个网页后调度新的URL,同时也避免了网页的重复采集。分配器在设计模式中以单例模式编码,负责提供新的 URL 给 Gather。因为涉及到多线程重写,所以单例模式尤为重要。
重复采集是指物理上存在的网页,被Gather重复访问而不更新,造成资源浪费。因此,Dispatcher 维护两个列表,“已访问表”和“未访问表”。爬取每个URL对应的页面后,将URL放入visited表,将页面提取的URL放入unvisited表;当 Gather 从 Dispatcher 请求一个 URL 时,它首先验证 URL 是否在 Visited 表中,然后再给 Gather 工作。
Spider 启动多个 Gather 线程
现在互联网上的网页数以亿计,通过单一的Gather来采集网页显然是低效的,所以我们需要使用多线程的方式来提高效率。Gather的功能是采集网页,我们可以通过Spider类开启多个Gather线程,从而达到多线程的目的。代码显示如下:
/***启动线程采集,然后开始采集网页数据*/publicvoid start() {
调度程序 disp=newDispatcher.getInstance();for(inti=0; i
线程聚集=newThread(newGather(disp));
采集.start();
}
}
线程启动后,网页采集器启动作业的运行,一个作业完成后,向Dispatcher申请下一个作业。因为有一个多线程的Gather,为了避免线程不安全,需要对Dispatcher进行互斥访问。在其函数中添加同步 关键词 以实现线程安全访问。
概括
Spider是整个搜索引擎的基础,为后续的操作提供原创网页数据,所以了解Spider的编写和网页库的组成,为后续的预处理模块打下基础。同时,Spider也可以单独使用,稍微修改后采集某些特定的信息,比如抓取某个网站的图片。