Posted on 2008-12-21 20:38
山泉彎延 閱讀(3391)
評論(0) 編輯 收藏 引用 所屬分類:
TCP/IP 協議 review all the time
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class scraber implements Runnable


{
private String ss;
private String url;

/** *//**
*
* 該函數爬取網絡上跟所需查詢單詞想通的語句,并存取
* @param ss 流
* @param url 超鏈接
*/
public scraber(String ss,String url)

{
this.ss=ss;
this.url=url;

}
public void run()

{
String s=new String("不錯");
if(ss.contains(s))

{

/** *//**
* 需要對字符串進行一些必要裁剪,使得字符串更加簡單,醒目
*/
int begin=ss.indexOf(s);
ss = ss.substring(begin);
int end = 30 < ss.length()? 30:ss.length();
ss=ss.substring(0, end);
System.out.println(url+" "+"begin:"+ss);
}
}
}

/** *//**
* @author Administrator
* 在廣度遍歷的每一個枝點安放一個機器人線程,該線程負責該枝點一下的搜索
*/
class irobot implements Runnable


{
private String ss;
public irobot(String ss)

{
this.ss=ss;
}
public void run()

{
MySearch ms=new MySearch();

/** *//**
* 線程獨立啟動對該URL內容的檢索
*/
try

{
ms.checkURL(ss);
}
catch(IOException e)

{
}
}
}

class MySearch
{

/** *//**
* 使用線程池來進行大批量線程的管理,這里規定當前最多線程數為10.可重用的線程
* 不斷嘗試著和newCachedThreadPool() 進行比較,發現newCachedThreadPool() 比較容易崩潰,但是速度非常快
* 適合于快速的查詢,但是要對查詢的深度進行嚴格限制。使用newFixedThreadPool(10)適度相對慢一些,但是查詢穩定,因為
* 查詢已經限制好了在10個線程的范圍內,但是到一定程度也會崩潰,這個程度比前面深,最主要是由于內存不足,算法本身對內存的需求很大。
*/
ExecutorService exec = Executors.newFixedThreadPool(10);

/** *//**由于多線程公用該變量,直接設置它為靜態變量
* 使用hashMap使得對URL的重復性查詢檢索效率倍增
*/
static HashMap<String,Integer> hashList = new HashMap<String,Integer>();

/** *//**由于多線程公用該變量,直接設置它為靜態變量
* URL記錄在該文件中
*/
static File store=new File("d://link.txt");

/** *//**由于多線程公用該變量,直接設置它為靜態變量
* 文件流
*/
static FileWriter writeFile;
public void checkURL(String uu)throws IOException

{
if(uu.endsWith("/"))

{
uu=uu.substring(0,uu.length()-1);
}

try
{
URL u = new URL(uu);
InputStream inn =u.openStream();
if(hashList.containsKey(uu))

{
Integer numLink=hashList.get(uu);
hashList.put(uu, ++numLink);
return;
}
hashList.put(uu, 1);
writeFile.append(uu+"\n");
BufferedReader in = new BufferedReader(new InputStreamReader(inn,"ISO-8859-1"));
String ss;
ArrayList<String> tempList=new ArrayList<String>();
int sureOfCharset = 0;

/** *//**
* 當前所搜索的文檔,查詢一遍,查找所需要查找的句子
* 并做超鏈接提取工作,存放到臨時鏈接隊列中。
*/
while((ss=in.readLine())!=null)

{

/** *//**
* 注意對文檔的字符編碼進行轉換,一般是轉換成UTF-8格式
*/
ss= ss.trim();
if(sureOfCharset == 0)

{

/** *//**
* 用正則表達式匹配更加精準,效率更好
*/
if(ss.contains("charset"))

{
String pattern1="(utf-8|UTF-8)";
String pattern2="(gbk|GBK)";
String pattern3="(gb2312|GB2312)";
Pattern p1=Pattern.compile(pattern1);
Pattern p2=Pattern.compile(pattern2);
Pattern p3=Pattern.compile(pattern3);
Matcher m1=p1.matcher(ss);
Matcher m2=p2.matcher(ss);
Matcher m3=p3.matcher(ss);

/** *//**
* 匹配模式一成功,即文檔為utf8編碼方式
*/
if(m1.find())

{
sureOfCharset =1;
}

/** *//**
* 匹配模式二成功,即文檔為GBK編碼方式
*/
else if(m2.find())

{
sureOfCharset =2;
}

/** *//**
* 匹配模式三成功,即文檔為gb312編碼方式
*/
else if(m3.find())

{
sureOfCharset =3;
}

/** *//**
* 匹配模式失敗
*/
else

{
sureOfCharset = 4;
}
}
}
switch(sureOfCharset)

{

case 0:
{
ss = new String(ss.getBytes("ISO-8859-1"),"utf-8");
break;
}

case 1:
{
ss = new String(ss.getBytes("ISO-8859-1"),"utf-8");
break;
}

case 2:
{
ss = new String(ss.getBytes("ISO-8859-1"),"gbk");
break;
}

case 3:
{
ss= new String(ss.getBytes("ISO-8859-1"),"gb2312");
break;
}

default:
{
ss = new String(ss.getBytes("ISO-8859-1"),"utf-8");
break;
}
}

/** *//**
* 開啟爬蟲線程抓取和“***”有關的語句
*/
scraber buger=new scraber(ss,uu);
exec.execute(buger);

/** *//**
* 提取超鏈接
*/
check(ss,tempList);
}

/** *//**
* 對臨時超鏈接隊列進行處理
*/
Iterator<String> it=tempList.iterator();

/** *//**
* 提取出臨時超鏈接隊列中的每一個鏈接
*/
while(it.hasNext())

{
String ref = (String)it.next();

/** *//**
* 啟動一個機器人線程,處理該超鏈接
*/
irobot ir=new irobot(ref);
Thread robThread= new Thread(ir);
robThread.start();
}

/** *//**
* 清空臨時隊列
*/
tempList.clear();

/** *//**
* 關閉線程池
*/
exec.shutdown();
}
catch(IOException e)

{

/** *//**
* 無法連接
*
*/
}
}

/** *//**
* 從該行中提取出超鏈接
* @param s 該行字符串
* @param tempList 臨時超鏈接隊列
*
*/
void check(String s,ArrayList<String> tempList)

{
int i=s.indexOf("href=\"");
if(i>0)

{
String news=s.substring(i+6);
int j1= news.indexOf("\"");
if(j1>0)

{
String ref = news.substring(0,j1);
tempList.add(ref);
}
}

}

public static void main(String args[])throws IOException

{
MySearch t= new MySearch();
System.out.println("%searching start%");
t.go("http://www.shnenglu.com/");
}


void go(String uu)

{

try
{
writeFile= new FileWriter(store);
checkURL(uu);
writeFile.close();
}catch(IOException e)

{
}
}
}
