此搜索引擎适于在一个中等规模的局域网中使用由于找到的网页存在数据库中不仅可以索静态的HTML页面可以搜索phpasp等动态页面对于一个拥有万个网页的系统(使用PII作为服务器)搜索响应时间在秒左右完全可以满足要求由于JavaMySQLPHP都是跨平台的软件所以此搜索引擎不仅可以工作在Windows服务器上而且也可以工作在Linux等其他系统中
一建立搜索引擎需要的数据库和数据表
首先建立数据库
c:\mysql\bin\> mysqladmin uroot pmypasswd create Spider
然后建立数据库中的表结构
c:\mysql\bin\> mysql uroot pmypasswd Spider < Spidermysql
其中Spidermysql为一个文本文件其内容如下
CREATE TABLE link (
Id int() unsigned NOT NULL auto_increment
Url varchar() NOT NULL
Class tinyint() unsigned NOT NULL default
IsSearchLink tinyint() unsigned default
PRIMARY KEY (Url)
UNIQUE Id (Id)
KEY Url (Url)
KEY Class (Class)
);
# 本局域网的初始主页地址搜索蜘蛛从此网址开始搜索所有其他网页
INSERT INTO link VALUES( HTTP:/// );
# 数据表 webpagelocal 用来存放下载的所有的网页
CREATE TABLE webpagelocal (
Id int() unsigned NOT NULL auto_increment
Url varchar() NOT NULL
Content text NOT NULL
PRIMARY KEY (Url)
UNIQUE Id (Id)
KEY Url (Url)
);
# 数据表 webpagefindfast
# 用MakeFastphp从表webpagelocal中提取字节的检索信息存放其中
CREATE TABLE webpagefindfast (
Id int() unsigned NOT NULL
Url varchar() NOT NULL
Title varchar()
Content blob
PRIMARY KEY (Url)
KEY Url (Url)
KEY Title (Title)
);
二以下为搜索网页和下载网页至本地数据库的Java程序LinkToDBjava它也是此搜索引擎的核心和基础
/***************************** LinkToDBjava ***********************************
*
* 对URL中的http链接进行分析将相对路径转换为绝对路径排序方式输出结果到数据库
*
* 如果分析得到的URL是Link表中唯一的就将其内容下载到表 WebPageLocal 中
*
********************************************************************************
/
import javaio*;
import javautil*;
import *;
import javalangString;
import javasql*;
import javatext*;
class Counter {
private int i = ;
int read() { return i; }
void increment() { i++; }
}
public class LinkToDB {
String UrlHost = ;
String UrlFile = ;
String UrlPath = ;
static String StartWith = null;
boolean outsideTag = true; //判断是否在标记之中
static char[] buffer = new char[]; // 缓沖区:用于保存从 URL 读的数据
InputStreamReader read = null;
BufferedReader reader = null;
URLConnection uc = null;
private URL url = null;
private StreamTokenizer st;
private TreeMap counts = new TreeMap();//以排序方式保存找到的链接
LinkToDB(String myurlString StartOnly){
try {
StartWith = StartOnly;
if(StartOnly!=null) { if(!myurlstartsWith(StartOnly)) return; }//只搜索此网站
url = new URL(myurl);
UrlHost = urlgetHost();
UrlHost = UrlHosttoUpperCase();
UrlFile = urlgetFile();
int v=UrlFilelastIndexOf(/);
if(v!=) UrlPath = UrlFilesubstring(v);
Systemoutprintln(分析文件+myurl);
int uclength=;
int ucError=;
try{
uc = urlopenConnection();
ucsetUseCaches(false);
nnect();
}
catch(IOException io) { ucError=; Systemoutprintln(打不开待分析网页:+myu
rl); }
if(ucError!=){
uclength = ucgetContentLength();
if (uclength<) {
try{ read = new InputStreamReader(urlopenStream()); }
catch(IOException io) {Systemoutprintln(流打开错误:+myurl);}
}
else Systemoutprintln(文件太大不分析);
}
if(read!=null){
reader=new BufferedReader(read);
if(reader!=null){
st = new StreamTokenizer(reader);
stresetSyntax(); // 重置语法表
stwordChars(); // 令牌范围为全部字符
stordinaryChar(<); // HTML标记两边的分割符
stordinaryChar(>);
}
}
}
catch(MalformedURLException e){ Systemoutprintln(Malformed URL String!);}
}
void cleanup() {
try { readclose(); }
catch(IOException e) { Systemoutprintln(流关闭错误); }
}
void countWords() {
try {
while(stnextToken()!=StreamTokenizerTT_EOF) {
String s=;
String s_NoCase=;
switch(ype) {
case <: //入标记字段
outsideTag=false;
continue; //countWords();
case >: //出标记字段
outsideTag=true;
continue; //countWords();
case StreamTokenizerTT_EOL: s = new String(EOL); break;
case StreamTokenizerTT_WORD: if(!outsideTag) s = stsval; /*已经是字符
串*/ break;
default: s = ;// s = StringvalueOf((char)ype);/*单一字符*/
}
if(outsideTag) continue;//出了标记区域(<a >)
String s = ;
s_NoCase = strim();
s=s_NoCasetoUpperCase();
if(sstartsWith(A )||sstartsWith(AREA )||sstartsWith(FRAME )||ss
tartsWith(IFRAME )){ //以这些开始的都是超级链接
int HREF_POS = ;
if(sstartsWith(FRAME )||sstartsWith(IFRAME )) {
HREF_POS = sindexOf(SRC=);
s = ssubstring(HREF_POS+)trim();
s_NoCase=s_NoCasesubstring(HREF_POS+)trim();
}
else {
HREF_POS=sindexOf(HREF=);
s=ssubstring(HREF_POS+)trim();
s_NoCase=s_NoCasesubstring(HREF_POS+)trim();
}
if(HREF_POS!=) {
if(sstartsWith(\))
{s=ssubstring();s_NoCase=s_NoCasesubstring();}
int QUOTE=sindexOf(\);
if(QUOTE!=)
{s=ssubstring(QUOTE)trim();s_NoCase=s_NoCasesubstring(QUOTE)trim
();}
int SPACE=sindexOf( );
if(SPACE!=)
{s=ssubstring(SPACE)trim();s_NoCase=s_NoCasesubstring(SPACE)trim
();}
if(sendsWith(\))
{s=ssubstring(slength());s_NoCase=s_NoCasesubstring(s_NoCasel
ength());}
if(sindexOf()!=||sindexOf(JAVASCRIPT:)!=||sindexOf()!=
)
{s=;s_NoCase=;} //有这些符号认为非合法链接两点表示上一目录而我
只想向下级查找
if ( !sstartsWith(FTP://) &&//以下后缀或前缀通常非网页格式
!sstartsWith(FTP://) &&
!sstartsWith(MAILTO:) &&
!sendsWith(SWF) &&
!sstartsWith(/)) //因/表示上一目录通常只需考虑本级和下N级目录
s=s;
if (!sstartsWith(HTTP://)&&!sequals()) {s=UrlHost+UrlPath+/+s;s_No
Case=UrlHost+UrlPath+/+s_NoCase;}
else if(sstartsWith(/)) {s=UrlHost+s;s_NoCase=UrlHost+s_NoCase;}
if(sstartsWith(HTTP://)) {s=ssubstring();s_NoCase=s_NoCasesubstring(
);}
int JinHao=sindexOf(#); //如果含有#号表示有效的链接是此前的部分
if(JinHao!=) {s=ssubstring(JinHao)trim();s_NoCase=s_NoCasesubstring(
JinHao)trim();}
int H=; //以下将//转换为/
for(int m=;m<;m++){
H=sindexOf(//);
if(H!=) {s=ssubstring(H)+ssubstring(H+);s_NoCase=s_NoCasesubstring
(H)+s_NoCasesubstring(H+);}
}
int TwoXG=; //以下将//转换为/
for(int m=;m<;m++){
TwoXG=sindexOf(//);
if(TwoXG!=) {s=ssubstring(TwoXG)+ssubstring(TwoXG+);s_NoCase=s_NoCa
sesubstring(TwoXG)+s_NoCasesubstring(TwoXG+);}
}
int OneXG=sindexOf(/);
if(OneXG==) {s=s+/;s_NoCase+=/;} //将xxxxxxxxx转换为xxxxxxxxx/的
标准形式