[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[jfriends] UrlRetriever.java
サイトマップ作成ツールですが、試したものにはソースが付いていませんでした。
いろいろカスタマイズしたいと思ったので、勉強がてら自分で書いてみました。
まだ途中ですが、いちおう動いているので投稿します。
UrlRetriever.java
================================================================
import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.tree.*;
public class UrlRetriever {
private String base = null; // 他のサイトを再帰探査の対象にしないためのもの
private TreeSet treeset = new TreeSet(); //一度探索したnodeを再帰探索しないため
private MutableTreeNode top = null; //いちばん上のノード
public MutableTreeNode getTop() { return top; }
public void retrieve(String urlspec, DefaultMutableTreeNode parent) {
int BUFFER_LENGTH = 1024;
byte[] buffer = new byte[BUFFER_LENGTH + 1];
int pos = 0;
boolean is_append = false;
String protocol = "";
String host = "";
String file = "";
String path = "";
String exform = "";
DefaultMutableTreeNode node = null;
try {
URL url = new URL(urlspec);
URLConnection conn = url.openConnection();
URL u = conn.getURL(); // url とまったく同じ?
protocol = u.getProtocol();
host = u.getHost();
file = u.getFile();
path = this.getPath(file);
//exform = u.toExternalForm();
if (protocol.equals("mailto")) {
exform = protocol + ":" + host + file;
} else {
exform = protocol + "://" + host + file;
}
System.out.println(exform); // DEBUG
node = new DefaultMutableTreeNode(exform);
if (parent == null) {
//parent=null のとき base をセット
top = node;
base = url.getHost();
} else {
//parent=null でなければ url.toExternalForm() を 親ノードに add
parent.add(node);
}
//ヘッダーを解析して、text でなければ return
String type = conn.getContentType();
//System.out.println("CONTENT_TYPE=" + type); // DEBUG
if (type.indexOf("text") == -1) return;
//Base URL が異なるものは再帰探索しない
if (!host.equals(base)) { return; }
if (!treeset.contains(exform)) {
//今まで探索していないものだけ
treeset.add(exform); //TreeSetに登録
} else {
return; //すでに探索した
}
InputStreamReader is = new InputStreamReader(conn.getInputStream());
int c;
while ((c = is.read()) != -1) {
// タグ開始?////////////////////
if ((char)c == '<') {
is_append = true;
pos = 0;
Arrays.fill(buffer, (byte)'\0');// JDK 1.2 Only
}
//タグの中?/////////////////////
if (is_append) {
// バッファーに追加/////////////////////////
pos++;
if (pos < BUFFER_LENGTH) {
buffer[pos] = (byte)c;
}
}
// タグ終了?/////////////////////
if ((char)c == '>') {
is_append = false;
String s = new String(buffer, 0, pos + 1);
String link = null;
if ((link = this.getLink(s)) != null) {
link = this.getUrlspeck(link, protocol, host, path);
//再帰探索///////////////////////////////////////////////////
this.retrieve(link, node);
}
}
}
}
catch (IOException e) {
}
catch (Exception e) {
}
}
// URL#getFile() のうちのパス名を解析
public String getPath(String file) {
int slash = file.lastIndexOf('/');
if (slash > -1) {
// '/' 記号がある
if (slash == file.length() - 1) {
// '/' 記号で終わっている
return new String(file);
} else {
// '/' 記号で終わっていない
int dot = file.lastIndexOf('.');
if ( dot > slash + 1 && dot < file.length() - 1) {
// '/' 記号の後ろに '.' 記号がある
return file.substring(0, slash + 1);
} else {
// '/' 記号の後ろに '.' 記号は無い
return new String(file + "/"); // 危険かなあ...
}
}
} else {
// '/' 記号が無い (たぶんありえない)
return "/"; // これでいいのか?
}
}
//プロトコル名、相対リンクなどの補完
public String getUrlspeck( String link,
String protocol, String host, String path)
{
// プロトコル名がある?( "://" を含む?)
int collon = -1;
boolean b = false;
if ((collon = link.indexOf(':')) > 0) {
// プロトコル名なのか?( : の手前が [a-z] ?)
b = true;
for (int i = 0; i < collon; i++) {
char ci = link.charAt(i);
if (ci < 'a' || ci > 'z') {
b = false;
break;
}
}
}
if (!b) {
//プロトコル名を含まない
if (link.startsWith("/")) {
// Document Root からのリンク
// protocol, host, path を補完
link = protocol + "://" + host + link;
} else {
// このページからの相対リンク
// protocol, host, path を補完
link = protocol + "://" + host + path + link;
}
}
return new String(link);
}
// tag 中の HREF=, SRC= を取得
public String getLink(String tag) {
if (tag.startsWith("</")) { return null; }
String utag = (tag.toUpperCase()).trim(); // 検査対象を大文字化
String link = ""; // リンクの先頭部分
if (utag.startsWith("<A ")) { link = "HREF"; } // <A HREF
else if (utag.startsWith("<FRAME ")) { link = "SRC"; } // <FRAME SRC
else { return null; } // 上記以外調べない
int pos = -1;
if ((pos = utag.indexOf(link)) != -1) { // HREF または SRC の探索
int start = pos + link.length() + 1; // HREF または SRC の次の文字位置
String stag = tag.substring( start, // HREF または SRC を除去
tag.length());
stag = stag.replace('"', ' '); // " 記号を空白にしてしまう
stag = stag.replace('>', ' '); // > 記号を空白にしてしまう
stag = stag.trim(); // 前後の空白を除去
if (!stag.startsWith("=")) { return null; } // 先頭に = 記号が無い
stag = stag.substring(1, stag.length()); // = 記号の除去
StringTokenizer tk = //トークン取り出し開始
new StringTokenizer(stag);
if (!tk.hasMoreTokens()) { return null; } //リンクが空
return tk.nextToken(); //最初のトークンだけ返す
} else {
return null; //リンクではない
}
}
public static void main(String[] args) {
UrlRetriever me = new UrlRetriever();
me.retrieve(args[0], null);
}
}
------------------------------------------------------------------
遠藤靖之 (えんどう やすゆき) <yasuyuki@xxxxxxxxxx>
http://www.freepage.total.co.jp/jfriends/ (Java互助会ホームページ)
株式会社タイムインターメディア 情報通信サービス部 TEL 03-5362-9009
〒162-0065 新宿区住吉町3-11 新宿スパイアビル8F FAX 03-5362-9008