搜索引擎爬虫.docx
- 文档编号:12551092
- 上传时间:2023-06-06
- 格式:DOCX
- 页数:16
- 大小:20.70KB
搜索引擎爬虫.docx
《搜索引擎爬虫.docx》由会员分享,可在线阅读,更多相关《搜索引擎爬虫.docx(16页珍藏版)》请在冰点文库上搜索。
搜索引擎爬虫
生成数据库的脚本文件(sqlserver数据库)
createdatabaseSE
GO
useSE
CREATETABLE[WebPageInfo](
[DOCID][int]NOTNULL,
[URL][varchar](900)NULL,
[PAGETEXT][text]NULL,
[LENGTH][int]NULL,
[TITLE][varchar](200)NULL,
[DESCRIPTION][varchar](200)NULL,
[KEYWORDS][varchar](200)NULL,
[PR][float]NULLCONSTRAINT[DF_WebPageInfo_PR]DEFAULT(0),
CONSTRAINT[PK_WebPageInfo]PRIMARYKEYCLUSTERED
(
[DOCID]
)ON[PRIMARY]
)ON[PRIMARY]TEXTIMAGE_ON[PRIMARY]
GO
CREATETABLE[AnchorUrl](
[ANCHORID][int]IDENTITY(1,1)NOTNULL,
[DOCID][int]NULL,
[URL][varchar](900)NULL,
[ANCHORDOCID][int]NULL,
[ANCHORURL][varchar](900)NULL,
[ANCHORTEXT][varchar](200)NULL,
CONSTRAINT[PK_AnchorUrl]PRIMARYKEYCLUSTERED
(
[ANCHORID]
)ON[PRIMARY]
)ON[PRIMARY]
GO
代码
packagenetworkprocessing;
importjava.io.ByteArrayOutputStream;
importjava.io.InputStream;
import.URL;
import.URLConnection;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.Statement;
importjava.util.ArrayList;
importjava.util.Calendar;
importjava.util.Hashtable;
importjava.util.Vector;
publicclassSearchEngineSpiders{
/**
*本程序有两个特点:
(1)采用多线程处理,每个线程独立的抓取一个网页,这样能够大幅度提高抓取工作的执行效率。
为了防止同一个
*网页被抓取多次,所以程序定义了completePages哈希表,它保存所有已经被抓取的网页特征,以此来判断当前抓取网页是否已被
*抓过。
同时,抓取线程同时也负责对网页内容的解析,而解析过程中还会得到更多需要抓取网页的URL,因此需要建立waitingPages
*向量来保存所有需要被抓取的网页URL
(2)使用数据库来存储相关网页信息,其中WebPageInfo表负责存储网页的文本内容和一些特征
*信息,AnchorUrl表负责存储网页的链接关系信息。
*
*@paramargs
*/
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
//新建爬虫,最大线程数为10
Spidersp=newSpider("",10);
}
}
//爬虫类
classSpider{
//用于同步的对象标志变量
Objectlock=newObject();
//所有等待处理的URL队列,既增也减,用于标记需要处理的网页
VectorwaitingPages=newVector();
//所有正在等待处理和已经处理完毕的URL队列MD5值,只增不减,用于标记所有访问过的网页
HashtablecompletePages=newHashtable();
//连接数据库
Connectioncon;
//线程数量
intthreadCount=0;
//网页索引号
IntegerdocIDCount;
publicSpider(StringstartURL,intthreadCount){
//初始化内存存储向量
synchronized(lock){
//添加起始URL到所有等待处理的URL队列
waitingPages.addElement(startURL);
//得到起始URL的哈希值
StringbeginUrlMD5=MD5(startURL);
//添加起始URL到所有正在等待处理和已经处理完毕的URL队列
completePages.put(beginUrlMD5,beginUrlMD5);
}
try{
//加载SQLServer2008数据库
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
//对指定数据库建立连接,默认登录方式是独立认证
con=DriverManager.getConnection(
"jdbc:
sqlserver:
//localhost:
1433;DatabaseName=SE","sa",
"jocean");
}catch(Exceptione){
System.out.println(e.getMessage());
}
//设置线程开启数量
this.threadCount=threadCount;
//启动核心爬虫数
process();
}
publicvoidprocess(){
try{
//查询最大的网页索引号
Statementstm=con.createStatement();
ResultSetres=stm
.executeQuery("selectmax(docid)fromWebPageInfo");
res.next();
//System.out.println(res.getInt
(1));
//初始化网页索引号,它为现有DocID的最大值
intresdocid=res.getInt
(1);
//如果没有任何记录,则网页索引号默认为1,否则网页索引号加一
if(resdocid==0){
docIDCount=newInteger
(1);
}else{
docIDCount=newInteger(resdocid+1);
}
}catch(Exceptione){
System.out.println(e.getMessage());
}
//显示开始启动线程
System.out.println("Begin...");
//开启所有线程
for(inti=0;i //当前的线程号 finalintnum=i; //新建线程匿名类 Runnablespiderthread=newRunnable(){ //URL前缀长度 finalinthrefLen="href=\"".length(); //更新网页表 PreparedStatementpstmWebPageInfo; //更新锚信息表 PreparedStatementpstmAnchorUrl; //临时标准网页的内存字节数组输出流,长度自动增长 ByteArrayOutputStreambaos=newByteArrayOutputStream(); publicvoidrun(){ //TODOAuto-generatedmethodstub //输出正在处理的线程状态 //System.out.println("hrefLen="+hrefLen); System.out.println("Thread"+num+"begin..."); try{ //插入网页记录 pstmWebPageInfo=con .prepareStatement("insertintoWebPageInfo(docID,URL,PAGETEXT)values(? ? ? )"); //插入网页连接关系记录 pstmAnchorUrl=con .prepareStatement("insertintoAnchorUrl(DOCID,URL,ANCHORURL)values(? ? ? )"); }catch(Exceptione){ System.out.println(e.getMessage()); } //获取当前时间 longstartTime=Calendar.getInstance().getTimeInMillis(); //线程循环处理主体 while(true){ //如果线程空置的时间大于1分钟,则结束当前线程 longendTime=Calendar.getInstance().getTimeInMillis(); if(endTime-startTime>60000){ System.out .println(num+"********End*************"); break; } //获取下一个需要遍历的网页URL Stringurl=null; try{ //同步处理,防止线程冲突 synchronized(lock){ url=(String)waitingPages.firstElement(); waitingPages.remove(url); } }catch(Exceptione){ System.out.println(e.getMessage()); //System.out.println("JJ"); //如果出错,则继续获取下一个需要遍历的网页url continue; } //如果获取到的需要遍历的网页URL if(url! =null){ //输出正在处理的线程状态 System.out.println("Thread"+num+"workingat" +url); //打开网络连接 URLstartUrl; URLConnectionurlConnection; //获取网络输入流 InputStreamis=null; try{ //重置保存网页内容的内存字节数组输出流 baos.reset(); //创建网页连接 startUrl=newURL(url); urlConnection=startUrl.openConnection(); //获取网页的输入流 is=urlConnection.getInputStream(); //读取网页内容,保存在网页内容的内存字节数组输出流 intoneByte=is.read(); //System.out.println("oneByte="+oneByte); intreadflag=0; while(oneByte>0){ //忽略网页开头处的空格字符 if(readflag==0&&oneByte==32){ oneByte=is.read(); continue; } //如果网页不是文本网页(通过判断网页的第一个字符是不是“<"(编码为60),则退出 if(readflag==0&&oneByte! =60) break; else readflag=1; //将读取的网页字符内容写入内存字节数组输出流 baos.write(oneByte); //继续读下一个网页字符 oneByte=is.read(); } //如果是文本网页 if(readflag==1){ //获取网页文本内容 StringwebPageContent=baos.toString(); //存储网页文本到网页表 intdocID=writeToDatabase(url, webPageContent); //输出已经处理完毕的网页信息 System.out.println("done! docid="+docID +"url="+url); //分析和存储网页链出信息 analyzeAnchor(docID,url,webPageContent); } }catch(Exceptione){ } } } //System.out.println("完了"); } //存储网页到网页表,返回网页索引标识号 publicintwriteToDatabase(Stringurl,Stringcontent){ //生成新的网页索引标识号 intnewDocID=0; synchronized(docIDCount){ newDocID=docIDCount.intValue(); docIDCount=newInteger(newDocID+1); } //更新数据库表 try{ pstmWebPageInfo.setInt(1,newDocID); pstmWebPageInfo.setString(2,url); pstmWebPageInfo.setString(3,content); pstmWebPageInfo.executeUpdate(); }catch(Exceptione){ System.out.println(e.getMessage()); } returnnewDocID; } //分析网页链出信息 publicvoidanalyzeAnchor(intdocID,Stringurl,Stringcontent){ //解析网页文本所需的地址偏移量 intbeginPosition=0; intendPosition=0; //网页的动态数组 ArrayListotherAnchor=newArrayList(); //分析网页链出信息 try{ while(true){ //获取超链标签的文本位置 beginPosition=content.indexOf("href=\"", endPosition); endPosition=content.indexOf("\"",beginPosition +hrefLen); //如果不存在,则退出 if(beginPosition==-1||endPosition==-1) break; //得到链出的URL StringoneUrl=content.substring(beginPosition +hrefLen,endPosition); //最终得到有效的URL StringfinalStr=""; //判断URL是否以http开头 if(oneUrl.trim().startsWith("http",0)){ finalStr=oneUrl; } //确保不含有诸如mailto等其他类型的访问方式 elseif(oneUrl.indexOf(": //")==-1){ //处理直接根目录开头的URL if(oneUrl.trim().startsWith("/",0)){ //hrefLen+1为7,是http: //的长度 inttempEndPos=url.indexOf("/", hrefLen+1); finalStr=url.substring(0,tempEndPos) +oneUrl; } //处理其他类型的URL,如直接写文件名和子目录等,也包含..这种情况 else{ finalStr=url.substring(0, url.lastIndexOf("/")) +"/"+oneUrl; } } //消除/..的影响 while(true){ intpos=finalStr.indexOf("/../"); if(pos! =-1){ intprepos=finalStr.lastIndexOf("/", pos-1); finalStr=finalStr.substring(0,prepos) +finalStr.substring(pos+3); }else{ break; } } //存储得到的URL otherAnchor.add(finalStr); } }catch(Exceptione){ System.out.println(e.getMessage()); } //存储网页链出信息 storeAnchor(docID,url,otherAnchor); } //存储网页链出信息 publicvoidstoreAnchor(intdocID,Stringurl,ArrayListanchors){ for(inti=0;i StringanchorURL=(String)anchors.get(i); try{ pstmAnchorUrl.setInt(1,docID); pstmAnchorUrl.setString(2,url); pstmAnchorUrl.setString(3,anchorURL); pstmAnchorUrl.executeUpdate(); }catch(Exceptione){ System.out.println(e.getMessage()); } //在内存存储向量中添加需要处理的网页和已经处理的网页 try{ StringurlMd5=MD5(anchorURL); synchronized(lock){ if(! completePages.contains(urlMd5)){ waitingPages.addElement(urlMd5); completePages.put(urlMd5,urlMd5); } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 搜索引擎 爬虫