1. 目的
用五筆時,如果碰到不會拆的字,只好換回拼音。但這樣做治標不治本,於是到網上找五筆反查工具。最後發現一個不錯的網站——不僅有每個字對應的五筆碼,還有其字根圖。可惜的是,這是一個網站。換句說,就是每次查的時候都要上網。很自然的,會想到將這個網站上的五筆碼以及對應的字根圖儲存到本地上,再寫個查詢程式做成本地版的>_<
2. 準備工作——網頁特點分析
網站(http://www.wb86.com/wbcx)提供了兩種查詢方式:一種是輸入要查詢的字;另外一種是一頁接著一頁地查看。由於懶得找字型檔,就選擇了第二種方式。在此方式下,第一頁的URL是http://www.wb86.com/wbcx/index5.asp?page=1,第二頁的URL是http://www.wb86.com/wbcx/index5.asp?page=2,第三頁的URL是http://www.wb86.com/wbcx/index5.asp?page=3。通過前三個頁的URL,有理由相信第X頁的URL是http://www.wb86.com/wbcx/index5.asp?page=X。
解決URL問題後,就要分析如何從單個網頁得到所需要的資源。查看第一頁的原始碼發現“86五筆編碼”只出現過一次,而且其後面就是想要的五筆碼。因此得到伺服器發回的內容後,再定位到“86五筆編碼”就能得到相應的五筆碼。字根圖的URL地址出現在五筆碼之後,而且都是以“http://www.wb86.com/GIF-82”開頭的。因此在“86五筆編碼”之後的內容中,找到第一個以“http://www.wb86.com/GIF-82”開頭的URL,就是需要的圖片地址了。
3. 演算法流程
for( 第一頁到最後一頁 ) {
擷取這一頁的原始碼
從原始碼中提取五筆碼,字根圖的URL
擷取字根圖
}
4. 原始碼
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
public class Clawler {
private static final int END_PAGE = 6764;
private static final String PREFIX = "http://www.wb86.com/wbcx/index5.asp?page=";
private static final String CODE_SAVE_PATH = "D:\\Wubi\\WubiCode.txt";
private static final String IMG_SAVE_PATH_PREFIX = "D:\\Wubi\\img\\";
private static LinkedList queue = new LinkedList();
private static String m_imguri;
public static void main(String[] args) throws IOException {
HttpClient httpClient = new DefaultHttpClient();
FileWriter fw = null;
fw = new FileWriter(CODE_SAVE_PATH);
for(int i = 1; i <= END_PAGE; ++i) {
HttpUriRequest request = new HttpGet(PREFIX + i);
try {
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
StringBuilder builder = new StringBuilder();
if( entity != null ) {
InputStream is = entity.getContent();
byte[] tmp = new byte[2048];
while( is.read(tmp) != -1 ) {
builder.append(new String(tmp));
}
fw.write( getWubiCode(builder.toString(), i) );
downloadImg(m_imguri, IMG_SAVE_PATH_PREFIX + i + ".gif", i);
}
}
catch( Exception e ) {
queue.addLast((Integer)i);
e.printStackTrace();
}
if( i%100==0 ) {
fw.flush();
}
}
System.out.println("\n missing Code");
while( !queue.isEmpty() ) { //下載失敗的頁面
System.out.println(queue.element());
queue.removeFirst();
}
System.out.print("all done");
fw.close();
httpClient.getConnectionManager().shutdown();
}
public static String getWubiCode(String page, int number) { //提取五筆碼,字根圖的URL
StringBuilder save = new StringBuilder();
page = page.substring(page.indexOf("86五筆編碼"));
int index = 7;
while( page.charAt(index)!= '<' ) save.append(page.charAt(index++));
save.append(System.getProperty("line.separator"));
index = 0;
StringBuilder imgpath = new StringBuilder();
page = page.substring(page.indexOf("http://www.wb86.com/GIF-82"));
while( page.charAt(index) != '\"' ) imgpath.append(page.charAt(index++));
m_imguri = imgpath.toString();
save.insert(0, imgpath.charAt(imgpath.length() - 5));
save.insert(1, ' ');
return save.toString();
}
public static void downloadImg(String url, String path, int number) { //下載圖片
try {
File out = new File(path);
BufferedImage buffer = ImageIO.read(new URL(url));
if( buffer == null ) {
queue.addLast(number);
System.out.println(number + " " + url);
}
else {
ImageIO.write(buffer, "gif", out);
}
}
catch( IOException e ) {
queue.addLast(number);
System.out.println(url);
System.out.println(e.getMessage());
}
}
}
5. 參考資料
a. httpClient4.1入門教程(中文版)
http://wenku.baidu.com/view/0a027c5e804d2b160b4ec029.html
b. 論壇圖片爬蟲的一種實現
http://www.iteye.com/topic/1044289
c. 最簡單的搜尋引擎思路
http://www.iteye.com/topic/1055424