资源描述
武汉理工大学《java语言》课程设计
学 号:
课 程 设 计
题 目
网络爬虫搜索引擎
学 院
管理学院
专 业
信息管理与信息系统
班 级
姓 名
指导教师
王新
201
年
7
月
4
日
课程设计任务书
学生姓名:
指导教师: 王新 工作单位:信息管理与信息系统系
题 目: 网络爬虫搜索引擎
初始条件:
合理应用Java相关知识与编程技能,结合UML面向对象设计,解决信息管理领域的实际问题,如学生成绩管理、学籍管理、图书借阅管理、自动存取款机、通信录管理、商品销售管理、医院门诊管理、火车订票管理、影院自动售票、世界杯足球比赛管理、人力资源管理、酒店前台管理、房产中介管理、停车收费管理等。
要求完成的主要任务: (包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
1.进行需求分析,撰写需求文档,绘制用例图。
2.识别需求文档中的类,建模类,初步绘制类图(之后逐渐完善)。
3.确定、建模类的实例变量。
4.确定、建模类的方法。
5.若有需要,在系统中加入继承与多态。
6.将UML图转换成Java代码框架。
7.设计算法,若有复杂的数据结构需求,使用相应集合框架。
8.设计数据访问层,若有数据持久化需求,使用数据库/文件。
9.添加表示层,若程序运行在桌面,使用图形用户界面。
10.实现完整的系统,最终Java源代码至少在300行以上。
11.进行测试,并给出相应结果。
课程设计报告中要求详细描述思路、步骤、方法、实现、问题及解决过程、操作说明、测试及结果。
时间安排:
1.2014年6月23日 课程设计选题、查阅资料
2.2014年6月24日~25日 UML面向对象设计
3.2014年6月26日~7月1日 Java程序设计与代码调试
4.2014年7月2日 改进、完善、测试系统
5.2014年7月3日~7月4日上午 撰写、提交课程设计报告
6.2014年7月4日下午 课程设计答辩
指导教师签名: 年 月 日
系主任(或责任教师)签名: 年 月 日
网络爬虫搜索引擎
1项目介绍
1.1开发背景
该项目软件开发的意图是开发出一款网络爬虫软件。应用目标为搜集网络信息,便于查询使用。在如今的BIG DATA时代,网络信息庞大而又复杂,用户很难直接从中获得需要的信息。网络爬虫软件就是将这些信息收集并整理,当用户发起搜索请求时,该系统可将用户最需要的信息反馈给用户。
1.2用户的特点
本软件为免费软件,可供所有可使用互联网的用户使用。最终用户只需掌握基本的上网技术即可,操作人员的主要工作是启动和关闭服务器,只需掌握基本的电脑使用方法即可。维护人员需要专业的程序员,懂得Java的网络编程以及计算机网络基础,教育水平在专科以上。软件的预期工作时间为24h/日。
组织结构图及用户角色如图表1-1所示:
1.3需求分析
1.3.1各子模块功能的描述
本系统共分为三大模块:爬虫模块、数据库模块和搜索模块,也就是后台、前台和数据库。每一个模块有各自的分工,最后三大模块集合在一起构成一个完整的网络爬虫系统。各个子模块的详细功能如下:
1.3.2爬虫模块
第一个模块为爬虫模块。爬虫模块的主要任务是负责寻找网页,并将网页内的URL和关键字提取出来。此模块又详细分为两大模块:服务器模块和正则引擎模块,这两个模块分别负责上述的两个功能。
服务器模块向某个种子URL发送请求,或得其页面内容;正则引擎模块将服务器获取的页面用正则表达式对其进行分析,截取其中的URL和关键字,然后再将URL传递给服务器模块。系统按照这样的方式不断的抓取网页并进行分析,最后将结果存进数据库。
1.3.3搜索模块
第二个模块是搜索模块,用户在搜索界面输入关键字,然后系统在数据库中搜索对应的关键字,最后将结果返回给用户。
此模块又分为搜索界面和结果界面。搜索界面是首页,用户在此界面中输入想要搜索的关键词,这些关键词将被此页面记录下来传递到数据中进行搜素。结果页面是数据库结果的接受者,当数据库完成搜素后会将结果传递给次页面,然后结果页面会将结果呈现给用户。
1.3.4数据库模块
数据库模块在整个系统中起到存储和桥梁作用。爬虫模块将搜索的结果整理完成后存入数据库,搜索模块从数据库中获取需要的信息并呈现给用户。
1.4对非功能性的需求
1.4.1精度
该系统的输入为一个字符串,里面包含了一个或多个关键字,长度在38个汉字以内,超过的部分将被直接舍弃。输出的数据要求包括网站的URL和页面简介,按照页面内容与搜索内容的匹配程度来排序。
1.4.2时间特性要求
a) 响应时间≤0.01s
b) 更新处理时间≤0.1
c) 数据的转换和传送时间≤0.1s
1.4.3灵活性
该系统运用的主要语言是Java,由于Java是一门跨平台的语言,所以本系统的兼容性比较强,只要配置了Java环境就可以运行。当该系统与数据库MySQL的接口发生变化时,系统在重新加载了新的驱动后要能够正常运行。
1.4.4输人输出要求
输入:由用户输入搜索关键字,关键字类型为合法字符。
输出:显示结果列表或提示信息,包含页面地址、页面标题、页面描述的条目列表或字符串提示信息。
1.4.5故障处理要求
出错输出信息:根据不同的错误提供不同的错误提示信息。例如无网络连接、无法检索到结果。
出错处理对策:1)一般错误:显示错误信息,提示用户重新操作
2)严重错误:重新启动,必要时启用备份恢复数据
1.4.6其他专门要求
如用户单位对安全保密的要求,对使用方便的要求,对可维护性、可补充性、易读性、可靠性、运行环境可转换性的特殊要求等。
1) 健壮性:如果用户在发送搜索请求后与服务器连接中断,在用户重新连接后并重新请求时,系统应快速将信息反馈给用户。
2) 可维护性:新的管理员应该可以在10分钟以内掌握关闭和开启服务器等基本操作。
3)运行环境可转换行:任何装有浏览器的系统都应该可以访问服务器。当服务器更换操作系统时,在部署好Java环境后应可以马上运行。
2程序设计
2.1总体设计思想
本软件通过客户端浏览器,用户设置自己的爱好,并通过http传给服务器,服务器接收信息执行响应操作。
2.3程序设计总体框图
系统功能层次模块图如图1-2所示
图表1-1 系统层次模块图
2.4程序详细设计
(1)RecordDAOProxy类UML设计
(2)IRecordDAO类设计说明
(3)DatabaseConnection类设计说明
(4)RecordDAOImpl类设计说明
(5)Record类设计说明
(6)HtmlHelper类设计说明
(7)SpiderThread类设计说明
(8)DAOFactory类设计说明
(9)Page类UML设计
(10)测试类UML设计
(7)主体程序UML类图
源代码部分:
① RecordDAOProxy.java代码
import java.util.ArrayList;
import com.engine.dao.impl.RecordDAOProxy;
import com.engine.po.Record;
import com.engine.util.HtmlHelper;
/**
* @author
*/
public class ResultController {
private ResultController (){}
private static ResultController resultController;
/**
* @return ResultController
*/
Public static synchronized ResultController getResultController(){
if(resultController == null){
resultController = new ResultController();
}
return resultController;
}
/**
* @param keyWord
* @return Record
* @throws Exception
*/
public ArrayList<Record> queryResult(String keyWord) throws Exception {
String[] keyWords = keyWord.split("\\s");
ArrayList<Record> list = new ArrayList<Record>();
RecordDAOProxy recordDao =null;
for(int i=0; i<keyWords.length;++i){
keyWord = keyWords[i];
recordDao = new RecordDAOProxy();
list.addAll(recordDao.getRecord("WHERE recordTitle LIKE \'%" + keyWord + "%\'"));
recordDao = new RecordDAOProxy();
list.addAll(recordDao.getRecord("WHERE recordContent LIKE \'%" + keyWord + "%\'"));
}
return list;
}
}
②User.java代码
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 5612649006026227700L;
private String no;
private String name;
private Integer age;
private String sex;
private String phone;
private String imagePath;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
}
③BusinessObject.java代码
import java.util.List;
public class BusinessObject {
int currentPos;
User[] users;
PropertiesUtil proutil;
public BusinessObject(){
currentPos = 0;
proutil = new PropertiesUtil("config/telephone.dat");
users = getAllUsers();
}
public User[] getAllUsers() {
List <User> list = proutil.getUsers();
User[] users2 = new User[list.size()];
for(int i =0;i<list.size();i++){
users2[i]=list.get(i);
}
return users2;
}
public User first() {
currentPos =0;
return users[currentPos];
}
public User previous() {
if(currentPos >0){
currentPos --;
}
return users[currentPos];
}
public User next() {
if(currentPos < users.length - 1){
currentPos ++;
}
return users[currentPos];
}
public User last() {
currentPos = users.length - 1;
return users[currentPos];
}
public void saveUser(User user) {
proutil.save(user);
users = getAllUsers();
currentPos = Integer.parseInt(user.getNo()) - 1;
}
}
④PropertiesUtil.java代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
public class PropertiesUtil {
private ObjectInputStream ois = null;
private ObjectOutputStream oos = null;
private List<User> lstUsers = new ArrayList<User>();
private String fileName = null;
public PropertiesUtil(String fileName){
this.fileName = fileName;
}
@SuppressWarnings("unchecked")
public List<User> getUsers(){
try {
ois = new ObjectInputStream(new FileInputStream(fileName));
lstUsers = (ArrayList<User>)ois.readObject();
ois.close();
}catch(FileNotFoundException e){
intRecord();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return lstUsers;
}
public void save(User user){
try {
oos = new ObjectOutputStream(new FileOutputStream("config/telephone.dat"));
int i;
for( i = 0;i < lstUsers.size();i++){
if(user.getNo().equals(lstUsers.get(i).getNo())){
lstUsers.set(i, user);//修改
break;
}
}
if(i >= lstUsers.size()){
lstUsers.add(user);//新增
}
oos.writeObject(lstUsers);
oos.flush();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 若记录文件不存在,则初始化记录文件
*/
private void intRecord(){
//创建文件
File f = new File("config/telephone.dat");
try {
f.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
//新建一条记录
User u = new User();
u.setNo("1");
u.setName("");
u.setAge(0);
u.setSex("F");
u.setPhone("");
u.setImagePath("");
try {
oos = new ObjectOutputStream(new FileOutputStream("config/telephone.dat"));
lstUsers.add(u);
oos.writeObject(lstUsers);
oos.close();
JOptionPane.showMessageDialog(null, "请重启本程序");
System.exit(0);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
⑤Test.java代码
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class Test {
private ObjectOutputStream oos = null;
private List<User> lstUsers = new ArrayList<User>();
User u1 = null;
User u2 = null;
User u3 = null;
public Test() {
try {
oos = new ObjectOutputStream(new FileOutputStream("config/telephone.dat"));
u1 = new User();
u1.setNo("1");
u1.setName("人物1");
u1.setSex("M");
u1.setAge(11);
u1.setPhone("111");
u1.setImagePath("config/demo8.jpg");
lstUsers.add(u1);
u2 = new User();
u2.setNo("2");
u2.setName("人物2");
u2.setSex("F");
u2.setAge(22);
u2.setPhone("222");
u2.setImagePath("config/demo4.jpg");
lstUsers.add(u2);
u3 = new User();
u3.setNo("3");
u3.setName("人物3");
u3.setSex("F");
u3.setAge(33);
u3.setPhone("333");
u3.setImagePath("config/demo2.jpg");
lstUsers.add(u3);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Test t = new Test();
try {
t.oos.writeObject(t.lstUsers);
t.oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
⑥public class Result {
private String recordLink;
private String recordTitle;
private String recordAbstractContent;
private String keywordTimes;
public String getRecordLink() {
return recordLink;
}
public void setRecordLink(String recordLink) {
this.recordLink = recordLink;
}
public String getRecordTitle() {
return recordTitle;
}
public void setRecordTitle(String recordTitle) {
this.recordTitle = recordTitle;
}
public String getRecordAbstractContent() {
return recordAbstractContent;
}
public void setRecordAbstractContent(String recordAbstractContent) {
this.recordAbstractContent = recordAbstractContent;
}
public String getKeywordTimes() {
return keywordTimes;
}
public void setKeywordTimes(String keywordTimes) {
this.keywordTimes = keywordTimes;
}
}
⑦import java.sql.*;
public class DatabaseConnection {
private Connection con=null;
private static final String DRIVER="com.mysql.jdbc.Driver";
private static final String URL="jdbc:mysql://localhost:3306/webengine?useUnicode=true&characterEncoding=utf-8";
private static final String USER="root";
private static final String PASS="1234";
public DatabaseConnection() throws Exception{
Class.forName(DRIVER);
con=DriverManager.getConnection(URL, USER, PASS);
}
public Connection getConnection() throws Exception{
return con;
}
public void close() throws Exception{
if(con!=null){
con.close();
}
}
}
⑧import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SetCharacterEncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
this.encoding = filterConfig.getInitParameter("encoding");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
request.setCharacterEncoding(this.encoding);
chain.doFilter(request, response);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
this.encoding=null;
}
}
⑨import java.sql.*;
import java.util.*;
import com.engine.dao.IRecordDAO;
import com.engine.po.Record;
public class RecordDAOImpl implements IRecordDAO {
@SuppressWarnings("unused")
private Connection con = null;
@SuppressWarnings("unused")
private PreparedStatement stat = null;
public RecordDAOImpl(Connection con) { this.con = con;
}
@Override
public boolean insertRecord(Record record) throws Exception {
int i = 0;
String sql = "insert into Result(recordTitle,recordContent,recordLink) values(?,?,?)";
try {
PreparedStatement preStmt = con.prepareStatement(sql);
preStmt.setString(1, record.getRecordTitle());
preStmt.setString(2, record.getRecordContent());
preStmt.setString(3, record.getRecordLink());
i = preStmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
if (i == 1) {
return true;// } else {
return false;
}
}
@Override
public boolean clearAll() throws Exception {
Connection conn;
boolean flag = false;
String sql;
try {
conn = con;
sql = "delete * from Result";
flag = stat.execute(sql);
} catch (Exception ex) {
System.out.println("Error : " + ex.toString());
}
if (flag) {
return true;
} else {
return false;
}
}
@Override
public ArrayList<Record> getRecord(String condition) throws Exception {
ArrayList<Record> records = new ArrayList<Record>();
String sql = "select recordLink,recordTitle,recordContent from Result " + condition;
try{
ResultSet rs=con.createStatement().executeQuery(sql);
while(rs.next()){
Record record=new Record();
record.setRecordLink(rs.getString("recordLink"));
record.setRecordTitle(rs.getString("recordTitle"));
String content = rs.getString("recordContent");
if(content.length()>=400){
content = content.substring(0,400)+"...";
}
record.setRecordContent(content);
records.add(record);
}
}catch (SQLException e) {
e.printStackTrace();
}
return records;
}
public ArrayList<Record> getRecord(String where, int number)
throws Exception {
ArrayList<Record> records = new ArrayList<Record>();
String sql = "select recordLink,recordTitle,recordContent from Result where " +where +" limit " + Integer.toString(number);
try{
ResultSet rs=con.createStatement().executeQuery(sql);
while(rs.next()){
Record record=new Record();
record.setRecordLink(rs.getString("rec
展开阅读全文