用多线程实现的Java爬虫程序

合集下载

java多线程实际应用案例

java多线程实际应用案例

java多线程实际应用案例Java多线程是一种并发编程的方式,可以使程序同时执行多个任务,提高程序的执行效率和响应速度。

下面列举了十个Java多线程实际应用案例。

1. 电商网站订单处理:在一个电商网站中,订单的处理是一个非常繁琐且耗时的工作,可以使用多线程实现订单的并发处理,提高订单处理的效率。

2. 聊天软件消息发送:在聊天软件中,用户发送消息是一个频繁的操作,可以使用多线程实现消息的并发发送,提高用户体验。

3. 数据库读写操作:在数据库的读写操作中,读操作可以使用多线程并发执行,提高数据的读取速度;写操作可以使用多线程并发执行,提高数据的写入速度。

4. 图像处理:在图像处理中,可以使用多线程实现图像的并行处理,提高图像处理的速度。

5. 视频编解码:在视频编解码中,可以使用多线程实现视频的并行编解码,提高视频的处理速度。

6. 网络爬虫:在网络爬虫中,可以使用多线程实现并发的爬取网页数据,提高爬虫的效率。

7. 游戏开发:在游戏开发中,可以使用多线程实现游戏的并行处理,提高游戏的运行速度和响应速度。

8. 大数据处理:在大数据处理中,可以使用多线程实现并发的数据处理,提高大数据处理的效率。

9. 并发服务器:在服务器开发中,可以使用多线程实现并发的请求处理,提高服务器的并发能力。

10. 并发任务调度:在任务调度中,可以使用多线程实现并发的任务执行,提高任务的执行效率。

在实际应用中,多线程不仅可以提高程序的执行效率和响应速度,还可以充分利用多核处理器的优势,实现并行计算和并发处理。

然而,多线程编程也面临着诸多挑战,如线程安全、死锁、资源竞争等问题,需要设计合理的线程同步和互斥机制,确保程序的正确性和稳定性。

因此,在使用多线程编程时,需要仔细考虑线程间的依赖关系和数据共享问题,合理规划线程的数量和调度策略,确保多线程程序的正确性和性能。

在JAVA中线程起到的作用

在JAVA中线程起到的作用

在JAVA中线程起到的作用在Java中,线程是一种轻量级的执行单元,它独立运行于程序的进程中,能够同时执行多个任务。

线程的作用非常重要,它在程序的并发和多任务处理中起到很大的作用。

下面将详细介绍Java中线程的作用。

1. 实现并发编程:线程是Java实现并发编程的基本单元。

通过使用多个线程,可以使程序实现并发执行,提高程序的执行效率和响应速度。

例如,在一个服务器程序中,可以使用多线程来处理多个客户端的请求,以提高处理能力和响应速度。

2.提高程序的运行效率:通过使用多线程,可以将程序的不同部分并行化执行,提高程序的执行效率。

例如,在一个图像处理程序中,可以将图片的加载、处理和保存操作分别放在不同的线程中执行,可以加快整体处理速度。

4.资源共享:多个线程可以共享同一个进程的资源,例如内存、文件等。

通过线程间的通信和同步机制,可以保证多个线程之间的数据正确共享和互斥访问。

例如,在一个账户管理程序中,多个线程可以并发执行取款或存款操作,但需要通过同步机制来保证账户数据的一致性。

5.充分利用多核处理器:在现代计算机中,多核处理器已经成为主流。

通过使用多线程,可以充分利用多核处理器的计算能力,提高程序的性能。

例如,在一个数据处理程序中,可以使用多线程将数据分成多个部分,每个线程处理其中一部分,以充分利用多核处理器的并行计算能力。

6. 实现定时任务:线程可以用于实现定时任务的功能。

通过使用Java提供的定时器类和线程,可以定期地执行一些任务或者事件。

例如,在一个网络爬虫程序中,可以使用定时线程定期地从网站上抓取最新的数据。

7.支持同步编程:线程在实现同步编程时起到重要的作用。

通过使用线程的等待、通知、锁等机制,可以进行线程的同步操作,保证多个线程之间的顺序和同步性。

例如,在一个多线程的排序算法中,可以使用线程的等待和通知机制来实现多个线程之间的排序和合并。

总之,线程在Java中起到了非常重要的作用,它实现了程序的并发执行、提高了程序的运行效率、支持了异步编程、实现了资源共享、充分利用了多核处理器的计算能力,以及支持了定时任务和同步编程。

网络爬虫软件的研究与开发

网络爬虫软件的研究与开发

网络爬虫软件的研究与开发摘要:作为一种快捷、高效访问网络海量数据的工具,通用搜索引擎自诞生以来备受人们喜爱。

然而在设计上它却存在着很多不足,并且随着万维网的快速发展而日益不能满足人们的需求。

基于这种背景,用于对网页进行定向抓取的主题爬虫应运而生。

主题爬虫的设计理念是利用最少的资源,尽可能快而准确地抓取网络中用户关心的网页,目前已经有着非常广泛的应用。

首先,了解主题爬虫提出的历史背景及当前国内外的发展状况,分析与主题爬虫设计相关的技术知识,如HTTP协议、HTML解析、中文分词等。

其次,提出使用向量空间模型进行主题相关度计算。

为了能够充分利用网页中丰富的启发式信息,综合运用了网页内容分析和网页链接分析技术。

最后,基于对主题爬虫设计与实现方法的研究,使用Java开发一个多线程主题爬虫。

关键词:主题爬虫;向量空间模型;主题相关度;爬虫阻止协议1 背景及发展状况万维网诞生以来,其独特的魅力极大地激发了人类创作的积极性,短短十几年便发展成为了目前世界上规模最大的公共数据源。

然而人类的接受能力却是十分有限的,因此便产生了一种能够高效访问网络资源的需求。

在这种背景下,通用搜索引擎应运而生,如比较知名的Baidu、Google。

爬虫(Crawler),又称蜘蛛(Spider)或者机器人(Robot),是一种能够高效抓取网络资源的程序。

通用搜索引擎设计中用于抓取网络资源的爬虫被称为通用爬虫,这种爬虫的设计目标是尽可能快而多地抓取网络中的各种资源,具有很强的通用性。

但是,随着万维网的不断发展及人类的进步,通用爬虫的应用暴露出了很大的局限性。

比如大量不相关网络资源被抓取、严重浪费网络带宽、不能够支持语义查询等等。

为解决所面临的问题,用于定向抓取网络资源的主题爬虫被提上了研究日程。

最佳优先爬虫是一种简单、高效的主题爬虫。

在页面主题相关度评价上,它采用了经典的向量空间模型;而在对页面中所含链接进行主题相关度预测打分时则充分考虑了链接锚文本、链接所在页面的主题相关度、兄弟链接等等各种启发式信息。

Java 多线程 爬虫程序(spider)设计与实现

Java 多线程 爬虫程序(spider)设计与实现

Java 多线程爬虫程序(spider)设计与实现2009年04月15日星期三19:01转自:《福建电脑》吴小竹当spider程序访问到一个网页,必须进行以下几项基本处理:抽取网页中包含的文本;抽取网页中包含的URL,并将其区分为网页中包含的文本;抽取网页中包含的URL,并将其区分为网站内URL或网站外URL。

2.2各主要功能模块(类)设计2.2.1 spider类该类为主类,继承自线程类。

它本事并不做获取网页的具体工作,而是协调其他各类共同完成任务。

其主要类成员及方法如下:2.2.2 spiderworker类该类继承线程类,进行获取网页,抽取文本,URL等实际工作。

2.2.3 urlmanager类该类管理所获得的各种URL,利用四种URL队列来管理。

等待队列:等待刚问的URL队列,队列中的URL一经访问完便进入完成队列或不可达URL队列。

运行队列:正在访问的URL队列;完成队列:已访问过的URL队列;不可达队列:不可达的URL队列,即该URL对应的文件不可访问。

2.2.4 spiderwatcher类该类用来监视各线程的运行情况数,能确定实时的活动线程数。

2.3 SPIDER 工作过程a 给spider程序赋予一个初始URL,加入URL等待队列。

b根据需要确定线程池大小,启动n个线程。

c查询等待队列中是否有URL,若没有,且无其他活动线程序,线程结束;若有转d。

d从URL等待队列中取出一个URL,并移入运行对流,根据该URL去访问,并进行网页下载,抽取文本,抽取链接等工作。

若网页中包含URL,则把这些URL加入等待队列;吧访问过的URL加入完成队列,转c3.1 java中线程的生命周期java的线程从产生到消失,可分为四个状态:a 新建状态:线程在已被创建但尚未执行这段时间内,处于新建状态。

此时,线程对象已被分配内存空间,起私有数据已被初始化,但没有给其分配系统资源且线程未被调度。

处于此状态的线程,可以通过调用start()或stop()函数来开始线程或终止线程。

java 通用多线程工具类代码

java 通用多线程工具类代码

1. 概述在面向对象编程中,多线程技术是一项重要的技能。

而 Java 作为一种流行的编程语言,也提供了丰富的多线程工具类来帮助开发者处理并发编程。

本文将介绍一些 Java 中通用的多线程工具类及其代码示例,以帮助读者更好地理解和应用多线程技术。

2. 线程池(ThreadPool)线程池是一种重要的多线程工具类,它可以有效地管理和复用线程,提高程序的性能和响应速度。

以下是一个简单的线程池代码示例:```javaimport java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadPoolExample {public static void m本人n(String[] args) {// 创建固定大小的线程池ExecutorService pool = Executors.newFixedThreadPool(5);// 提交任务for (int i = 0; i < 10; i++) {pool.execute(new Task());}// 关闭线程池pool.shutdown();}}class Task implements Runnable {public void run() {System.out.println("Thread name: " +Thread.currentThread().getName());}}```在上面的代码示例中,我们使用 Executors 类的newFixedThreadPool 方法创建一个固定大小的线程池,然后提交了10 个任务给线程池处理。

最后调用 shutdown 方法关闭线程池。

3. 信号量(Semaphore)信号量是用来控制同时访问特定资源的线程数量的类,它可以防止由于线程的过多导致的资源不足。

java爬虫框架有哪些,各有什么特点

java爬虫框架有哪些,各有什么特点

java爬虫框架有哪些,各有什么特点目前主流的Java爬虫框架主要有Nutch、Crawler4j、WebMagic、scrapy、WebCollector等,各有各的特点,大家可以根据自己的需求选择使用,下面为大家详细介绍常见的java爬虫框架有哪些?各有什么特点?常见的java爬虫框架有哪些1、NutchNutch是一个基于Lucene,类似Google的完整网络搜索引擎解决方案,基于Hadoop的分布式处理模型保证了系统的性能,类似Eclipse 的插件机制保证了系统的可客户化,而且很容易集成到自己的应用之中。

总体上Nutch可以分为2个部分:抓取部分和搜索部分。

抓取程序抓取页面并把抓取回来的数据做成反向索引,搜索程序则对反向索引搜索回答用户的请求。

抓取程序和搜索程序的接口是索引,两者都使用索引中的字段。

抓取程序和搜索程序可以分别位于不同的机器上。

下面详细介绍一下抓取部分。

Nutch抓取部分:抓取程序是被Nutch的抓取工具驱动的。

这是一组工具,用来建立和维护几个不同的数据结构:web database,a set of segments,and the index。

下面逐个解释这三个不同的数据结构:1、The web database,或者WebDB。

这是一个特殊存储数据结构,用来映像被抓取网站数据的结构和属性的集合。

WebDB 用来存储从抓取开始(包括重新抓取)的所有网站结构数据和属性。

WebDB 只是被抓取程序使用,搜索程序并不使用它。

WebDB 存储2种实体:页面和链接。

页面表示网络上的一个网页,这个网页的Url作为标示被索引,同时建立一个对网页内容的MD5 哈希签名。

跟网页相关的其它内容也被存储,包括:页面中的链接数量(外链接),页面抓取信息(在页面被重复抓取的情况下),还有表示页面级别的分数score 。

链接表示从一个网页的链接到其它网页的链接。

因此WebDB 可以说是一个网络图,节点是页面,链接是边。

java面试常用项目

java面试常用项目在Java面试中,面试官通常会询问你在项目中的经验和技能。

以下是一些常见的Java面试项目:1. 学生成绩管理系统:这是一个基本的学生成绩管理系统,可以实现学生信息的录入、成绩的录入和查询、成绩的统计等功能。

你可以讨论如何设计和实现这个系统,包括数据库的设计与使用、前端界面的开发等方面。

2. 在线购物系统:这是一个模拟的在线购物系统,用户可以浏览商品、添加商品到购物车、提交订单等。

你可以讨论如何设计和实现这个系统,包括数据库的设计与使用、前端界面的开发、后端的逻辑处理等方面。

3. 多线程爬虫:这是一个用多线程方式实现的爬虫程序,可以从网页上获取数据。

你可以讨论如何设计和实现这个爬虫程序,包括多线程的并发控制、网络请求的处理、数据的解析与存储等方面。

4. 银行系统:这是一个模拟的银行系统,用户可以进行存款、取款、转账等操作。

你可以讨论如何设计和实现这个系统,包括数据库的设计与使用、业务逻辑的处理、交易的安全性等方面。

5. 聊天应用程序:这是一个基于网络的即时通讯应用程序,用户可以通过该应用程序进行文本、图片或者文件的传输。

你可以讨论如何使用Socket或者WebSocket实现实时通讯、如何设计传输协议、如何处理大规模用户同时在线等方面。

在面试中,除了讨论你在这些项目中的实践经验,还可以强调你在项目中遇到的挑战和解决方法,展示你在项目中的贡献和技术能力。

还可以提供项目的GitHub链接或者演示代码来证明你的实际能力。

当然,以上只是一些常见的Java面试项目示例,具体的项目要根据面试的岗位和要求来确定。

在准备面试之前,建议你对这些项目有一定的了解并准备好相应的答案。

网页源码爬取

⽹页源码爬取java实现⽹络爬⾍爬取单⼀页⾯package liuwenwu.test;import java.io.*;import .*;public class UrlDemo {public static void main(String[] args) {//确定爬取的⽹页地址String strurl="/?key=%BB%FA%D0%B5%B1%ED&act=input";//建⽴url爬取核⼼对象try {URL url = new URL(strurl);//通过url建⽴与⽹页的连接URLConnection conn = url.openConnection();//通过链接取得⽹页返回的数据InputStream is=conn.getInputStream();System.out.println(conn.getContentEncoding());//⼀般按⾏读取⽹页数据,并进⾏内容分析//因此⽤BufferedReader和InputStreamReader把字节流转化为字符流的缓冲流//进⾏转换时,需要处理编码格式问题BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));//按⾏读取并打印String line=null;while((line=br.readLine())!=null) {System.out.println(line);}br.close();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}}结果:下⾯尝试将这个⽹页的源代码保存成为本地的⼀个⽂本⽂件,以便后续做离线分析。

将爬取到时数据保存到F:/papapa/⽬录下package liuwenwu.test;import java.io.*;import .*;import java.util.*;import java.util.regex.*;/*** 读取当当⽹下⾸页图书的数据,并进⾏分析* 爬取深度为2* 爬去数据存储到F:/papapa/⽬录下,需⾃⾏创建* @author ASUS**/public class UrlDemo2 {//提取的数据存放到该⽬录下private static String savepath="F:/papapa/";//等待爬取的urlprivate static List<String> allwaiturl=new ArrayList<>();//爬取过得urlprivate static Set<String> alloverurl=new HashSet<>();//记录所有url的深度进⾏爬取判断private static Map<String, Integer> allurldepth=new HashMap<>();//爬取的深度private static int maxdepth=2;public static void main(String[] args) {//确定爬取的⽹址String strurl="/";workurl(strurl, 1);}public static void workurl(String strurl,int depth) {//判断当前url是否爬取过if(!(alloverurl.contains(strurl)||depth>maxdepth)) {//建⽴url爬取核⼼对象try {URL url = new URL(strurl);//通过url建⽴与⽹页的连接URLConnection conn = url.openConnection();//通过链接取得⽹页返回的数据InputStream is=conn.getInputStream();System.out.println(conn.getContentEncoding());//⼀般按⾏读取⽹页数据,并进⾏内容分析//因此⽤BufferedReader和InputStreamReader把字节流转化为字符流的缓冲流//进⾏转换时,需要处理编码格式问题BufferedReader br=new BufferedReader(new InputStreamReader(is,"GB2312"));//按⾏读取并打印String line=null;//正则表达式的匹配规则提取该⽹页的链接Pattern p=pile("<a .*href=.+</a>");//建⽴⼀个输出流,⽤于保存⽂件,⽂件名为执⾏时间,以防重复PrintWriter pw=new PrintWriter(new File(savepath+System.currentTimeMillis()+".txt"));while((line=br.readLine())!=null) {//编写正则,匹配超链接地址pw.println(line);Matcher m=p.matcher(line);while(m.find()) {String href=m.group();//找到超链接地址并截取字符串//有⽆引号href=href.substring(href.indexOf("href="));if(href.charAt(5)=='\"') {href=href.substring(6);}else {href=href.substring(5);}//截取到引号或者空格或者到">"结束try {href=href.substring(0,href.indexOf("\""));} catch (Exception e) {try {href=href.substring(0,href.indexOf(""));} catch (Exception e2) {href=href.substring(0,href.indexOf(">"));}}if(href.startsWith("http:")||href.startsWith("https:")){//将url地址放到队列中allwaiturl.add(href);allurldepth.put(href,depth+1);}}}pw.close();br.close();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}//将当前url归列到alloverurl中alloverurl.add(strurl);System.out.println(strurl+"⽹页爬取完成,以爬取数量:"+alloverurl.size()+",剩余爬取数量:"+allwaiturl.size()); }//⽤递归的⽅法继续爬取其他链接String nexturl=allwaiturl.get(0);allwaiturl.remove(0);workurl(nexturl, allurldepth.get(nexturl));}}控制台:本地⽬录如果想提⾼爬⾍性能,那么我们就需要使⽤多线程来处理,例如:准备好5个线程来同时进⾏爬⾍操作。

(精品)网络爬虫的设计与实现毕业论文

摘要网络爬虫是一种自动搜集互联网信息的程序。

通过网络爬虫不仅能够为搜索引擎采集网络信息,而且可以作为定向信息采集器,定向采集某些网站下的特定信息,如招聘信息,租房信息等。

本文通过JAVA实现了一个基于广度优先算法的多线程爬虫程序。

本论文阐述了网络爬虫实现中一些主要问题:为何使用广度优先的爬行策略,以及如何实现广度优先爬行;为何要使用多线程,以及如何实现多线程;系统实现过程中的数据存储;网页信息解析等。

通过实现这一爬虫程序,可以搜集某一站点的URLs,并将搜集到的URLs 存入数据库。

【关键字】网络爬虫;JAVA;广度优先;多线程。

ABSTRACTSPIDER is a program which can auto collect informations from internet. SPIDER can collect data for search engines, also can be a Directional information collector, collects specifically informations from some web sites, such as HR informations, this paper, use JAVA implements a breadth-first algorithm multi-thread SPDIER. This paper expatiates some major problems of SPIDER: why to use breadth-first crawling strategy, and collect URLs from one web site, and store URLs into database.【KEY WORD】SPIDER; JA V A; Breadth First Search; multi-threads.目录第一章引言 (1)第二章相关技术介绍 (2)2.1JAVA线程 (2)2.1.1 线程概述 (2)2.1.2 JAVA线程模型 (2)2.1.3 创建线程 (3)2.1.4 JAVA中的线程的生命周期 (4)2.1.5 JAVA线程的结束方式 (4)2.1.6 多线程同步 (5)2.2URL消重 (5)2.2.1 URL消重的意义 (5)2.2.2 网络爬虫URL去重储存库设计 (5)2.2.3 LRU算法实现URL消重 (7)2.3URL类访问网络 (8)2.4爬行策略浅析 (8)2.4.1宽度或深度优先搜索策略 (8)2.4.2 聚焦搜索策略 (9)2.4.3基于内容评价的搜索策略 (9)2.4.4 基于链接结构评价的搜索策略 (10)2.4.5 基于巩固学习的聚焦搜索 (11)2.4.6 基于语境图的聚焦搜索 (11)第三章系统需求分析及模块设计 (13)3.1系统需求分析 (13)3.2SPIDER体系结构 (13)3.3各主要功能模块(类)设计 (14)3.4SPIDER工作过程 (14)第四章系统分析与设计 (16)4.1SPIDER构造分析 (16)4.2爬行策略分析 (17)4.3URL抽取,解析和保存 (18)4.3.1 URL抽取 (18)4.3.2 URL解析 (19)4.3.3 URL保存 (19)第五章系统实现 (21)5.1实现工具 (21)5.2爬虫工作 (21)5.3URL解析 (22)5.4URL队列管理 (24)5.4.1 URL消重处理 (24)5.4.2 URL等待队列维护 (26)5.4.3 数据库设计 (27)第六章系统测试 (29)第七章结论 (32)参考文献 (33)致谢 (34)外文资料原文 (35)译文 (51)第一章引言随着互联网的飞速发展,网络上的信息呈爆炸式增长。

爬虫的四个步骤

爬虫的四个步骤爬虫技术是指利用程序自动化地浏览很多网页,并抓取它们的信息的过程。

爬虫技术在信息爬取、搜索引擎、商业竞争等领域应用广泛。

想要实现一个高效的爬虫程序,需要遵循一定的规范和流程,本文将介绍爬虫的四个步骤,它们是页面抓取、数据提取、数据存储和数据呈现。

第一步:页面抓取页面抓取是爬虫技术的第一步。

抓取的目标是将网站上的所有内容下载到本地,这些内容包括网页、图片、音频和视频等。

页面抓取是爬虫程序中最基本的过程之一,爬虫程序第一次访问目标网站时,会向目标服务器发送请求。

在拿到响应内容后,需要从中解析出有意义的信息,包括HTML源码、页面中的图片、JS文件、CSS文件等。

获取到这些信息后,需要判断响应状态码是否正常,是否符合预期,如果出现错误需要做出相应的处理。

在实现页面抓取过程中,可以使用多种语言和框架。

常用的语言有Python、Java、Node.js,常用的框架有Requests、Scrapy、Puppeteer等。

无论使用什么语言和框架,都需要注意以下几个问题:1. 多线程和协程在进行页面抓取时,需要考虑到性能和效率,如果使用单线程,无法充分利用网络资源,导致程序运行效率低下。

因此,需要采用多线程或协程的方式来处理比较复杂的任务。

多线程可以利用CPU资源,充分发挥计算机的性能。

协程可以利用异步非阻塞技术,充分利用网络资源。

2. 反爬机制在进行页面抓取时,需要考虑到反爬机制。

目标网站可能会采取一些反爬措施,如IP封禁、验证码验证等。

为了克服这些问题,需要采用相应的技术和策略,如IP代理、验证码识别等。

3. 容错处理在进行页面抓取时,需要考虑到容错处理。

爬虫程序可能会因为网络连接问题或者目标网站的异常情况导致程序运行出现异常。

因此,需要实现一些错误处理机制,如重试机制、异常捕获处理机制等。

第二步:数据提取数据提取是爬虫过程中比较重要的一步。

在页面抓取完成之后,需要将页面中有意义的信息提取出来。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

以下是一个Java爬虫程序,它能从指定主页开始,按照指定的深度抓取该站点域名下的网页并维护简单索引。

参数:private static int webDepth = 2;//爬虫深度。

主页的深度为1,设置深度后超过该深度的网页不会抓取。

private int intThreadNum = 10;//线程数。

开启的线程数。

抓取时也会在程序源文件目录下生成一个report.txt文件记录爬虫的运行情况,并在抓取结束后生成一个fileindex.txt文件维护网页文件索引。

本程序用到了多线程(静态变量和同步),泛型,文件操作,URL类和连接,Hashtable类关联数组,正则表达式及其相关类。

运行时需使用命令行参数,第一个参数应使用http://开头的有效URL字符串作为爬虫的主页,第二个参数(可选)应输入可转换为int型的字符串(用Integer.parseInt(String s)静态方法可以转换的字符串,如3)作为爬虫深度,如果没有,则默认深度为2。

本程序的不足之处是:只考虑了href= href=' href="后加绝对url的这三种情况(由于url地址在网页源文件中情况比较复杂,有时处理也会出现错误),还有相对url和window.open('的情况没有考虑。

异常处理程序也只是简单处理。

如果读者有改进办法可以把源代码帖出,不胜感激。

附上源代码如下(保存名为GetWeb.java):import java.io.File;import java.io.BufferedReader;import java.io.FileOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import .URL;import .URLConnection;import java.util.ArrayList;import java.util.regex.Matcher;import java.util.regex.Pattern;import java.util.Hashtable;public class GetWeb {private int webDepth = 2;//爬虫深度private int intThreadNum = 10;//线程数private String strHomePage = "";//主页地址private String myDomain;//域名private String fPath = "web";//储存网页文件的目录名private ArrayList<String> arrUrls = new ArrayList<String>();//存储未处理URLprivate ArrayList<String> arrUrl = new ArrayList<String>();//存储所有URL供建立索引private Hashtable<String,Integer> allUrls = new Hashtable<String,Integer>();//存储所有URL的网页号 private Hashtable<String,Integer> deepUrls = new Hashtable<String,Integer>();//存储所有URL深度 private int intWebIndex = 0;//网页对应文件下标,从0开始private String charset = "GB2312";private String report = "";private long startTime;private int webSuccessed = 0;private int webFailed = 0;public GetWeb(String s){this.strHomePage = s;}public GetWeb(String s,int i){this.strHomePage = s;this.webDepth = i;}public synchronized void addWebSuccessed(){webSuccessed++;}public synchronized void addWebFailed(){webFailed++;}public synchronized void addReport(String s){try{report += s;PrintWriter pwReport = new PrintWriter(new FileOutputStream("report.txt"));pwReport.println(report);pwReport.close();}catch(Exception e){System.out.println("生成报告文件失败!");}}public synchronized String getAUrl(){String tmpAUrl = arrUrls.get(0);arrUrls.remove(0);return tmpAUrl;}public synchronized String getUrl(){String tmpUrl = arrUrl.get(0);arrUrl.remove(0);return tmpUrl;}public synchronized Integer getIntWebIndex() {intWebIndex++;return intWebIndex;}/*** @param args*/public static void main(String[] args){if (args.length == 0 || args[0].equals("")){System.out.println("No input!");System.exit(1);}else if(args.length == 1){GetWeb gw = new GetWeb(args[0]);gw.getWebByHomePage();}else{GetWeb gw = new GetWeb(args[0],Integer.parseInt(args[1])); gw.getWebByHomePage();}}public void getWebByHomePage(){startTime = System.currentTimeMillis();this.myDomain = getDomain();if (myDomain == null){System.out.println("Wrong input!");//System.exit(1);return;}System.out.println("Homepage = " + strHomePage);addReport("Homepage = " + strHomePage + "!\n");System.out.println("Domain = " + myDomain);addReport("Domain = " + myDomain + "!\n");arrUrls.add(strHomePage);arrUrl.add(strHomePage);allUrls.put(strHomePage,0);deepUrls.put(strHomePage,1);File fDir = new File(fPath);if(!fDir.exists()){fDir.mkdir();}System.out.println("Start!");this.addReport("Start!\n");String tmp = getAUrl();this.getWebByUrl(tmp,charset,allUrls.get(tmp)+"");int i = 0;for (i=0;i<intThreadNum;i++){new Thread(new Processer(this)).start();}while (true){if(arrUrls.isEmpty() && Thread.activeCount() == 1){long finishTime = System.currentTimeMillis();long costTime = finishTime-startTime;System.out.println("\n\n\n\n\nFinished!");addReport("\n\n\n\n\nFinished!\n");System.out.println("Start time = " + startTime + " " + "Finish time = " + finishTime + " " + "Cost time = " + costTime + "ms");addReport("Start time = " + startTime + " " + "Finish time = " + finishTime + " " + "Cost time = " + costTime + "ms" + "\n");System.out.println("Total url number = " + (webSuccessed+webFailed) + " Successed: " + webSuccessed + " Failed: " + webFailed);addReport("Total url number = " + (webSuccessed+webFailed) + " Successed: " + webSuccessed + " Failed: " + webFailed + "\n");String strIndex = "";String tmpUrl = "";while (!arrUrl.isEmpty()){tmpUrl = getUrl();strIndex += "Web depth:" + deepUrls.get(tmpUrl) + " Filepath: " + fPath + "/web" + allUrls.get(tmpUrl) + ".htm" + " url:" + tmpUrl + "\n\n";}System.out.println(strIndex);try{PrintWriter pwIndex = new PrintWriter(new FileOutputStream("fileindex.txt")); pwIndex.println(strIndex);pwIndex.close();}catch(Exception e){System.out.println("生成索引文件失败!");}break;}}}public void getWebByUrl(String strUrl,String charset,String fileIndex){try{//if(charset==null||"".equals(charset))charset="utf-8";System.out.println("Getting web by url: " + strUrl);addReport("Getting web by url: " + strUrl + "\n");URL url = new URL(strUrl);URLConnection conn = url.openConnection();conn.setDoOutput(true);InputStream is = null;is = url.openStream();String filePath = fPath + "/web" + fileIndex + ".htm";PrintWriter pw = null;FileOutputStream fos = new FileOutputStream(filePath);OutputStreamWriter writer = new OutputStreamWriter(fos);pw = new PrintWriter(writer);BufferedReader bReader = new BufferedReader(new InputStreamReader(is)); StringBuffer sb = new StringBuffer();String rLine = null;String tmp_rLine = null;while ( (rLine = bReader.readLine()) != null){tmp_rLine = rLine;int str_len = tmp_rLine.length();if (str_len > 0){sb.append("\n" + tmp_rLine);pw.println(tmp_rLine);pw.flush();if (deepUrls.get(strUrl) < webDepth)getUrlByString(tmp_rLine,strUrl);}tmp_rLine = null;}is.close();pw.close();System.out.println("Get web successfully! " + strUrl);addReport("Get web successfully! " + strUrl + "\n");addWebSuccessed();}catch (Exception e){System.out.println("Get web failed! " + strUrl);addReport("Get web failed! " + strUrl + "\n");addWebFailed();}}public String getDomain(){String reg = "(?<=http\\://[a-zA-Z0-9]{0,100}[.]{0,1})[^.\\s]*?\\.(com|cn|net|org|biz|info|cc|tv)"; Pattern p = pile(reg,Pattern.CASE_INSENSITIVE);Matcher m = p.matcher(strHomePage);boolean blnp = m.find();if (blnp == true){return m.group(0);}return null;}public void getUrlByString(String inputArgs,String strUrl){String tmpStr = inputArgs;String regUrl = "(?<=(href=)[\"]?[\']?)[http://][^\\s\"\'\\?]*(" + myDomain + ")[^\\s\"\'>]*"; Pattern p = pile(regUrl,Pattern.CASE_INSENSITIVE);Matcher m = p.matcher(tmpStr);boolean blnp = m.find();//int i = 0;while (blnp == true){if (!allUrls.containsKey(m.group(0))){System.out.println("Find a new url,depth:" + (deepUrls.get(strUrl)+1) + " "+ m.group(0));addReport("Find a new url,depth:" + (deepUrls.get(strUrl)+1) + " "+ m.group(0) + "\n");arrUrls.add(m.group(0));arrUrl.add(m.group(0));allUrls.put(m.group(0),getIntWebIndex());deepUrls.put(m.group(0),(deepUrls.get(strUrl)+1));}tmpStr = tmpStr.substring(m.end(),tmpStr.length());m = p.matcher(tmpStr);blnp = m.find();}}class Processer implements Runnable{GetWeb gw;public Processer(GetWeb g){this.gw = g;}public void run(){//Thread.sleep(5000);while (!arrUrls.isEmpty()){String tmp = getAUrl();getWebByUrl(tmp,charset,allUrls.get(tmp)+"");}}}}。

相关文档
最新文档