0
1 .Fetch all contents from a Webpage
2. fetch hyperlinks from the webpage.
3. Repeat the 1 & 2 from the fetched hyperlink
4. repeat the process untill 200 hyperlinks regietered or no more hyperlink to fetch.

サンプルプログラムを書いたのですが、再帰の理解が不十分でループが無限ループになってしまいました。期待に一致するコードを解決することを提案してください。

import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Content
{
    private static final String HTML_A_HREF_TAG_PATTERN = 
        "\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))";
    Pattern pattern;
    public Content ()
    {
        pattern = Pattern.compile(HTML_A_HREF_TAG_PATTERN);
    }

    private void fetchContentFromURL(String strLink) {
        String content = null;
        URLConnection connection = null;
        try {
          connection =  new URL(strLink).openConnection();
          Scanner scanner = new Scanner(connection.getInputStream());
          scanner.useDelimiter("\\Z");
          content = scanner.next();
        }catch ( Exception ex ) {
            ex.printStackTrace();
            return;
        }
        fetchURL(content);
    }

    private void fetchURL ( String content )
    {
        Matcher matcher = pattern.matcher( content );
        while(matcher.find()) {
            String group = matcher.group();
            if(group.toLowerCase().contains( "http" ) || group.toLowerCase().contains( "https" )) {
            group = group.substring( group.indexOf( "=" )+1 );
            group = group.replaceAll( "'", "" );
            group = group.replaceAll( "\"", "" );
            System.out.println("lINK "+group);
            fetchContentFromURL(group);
            }
        }
        System.out.println("DONE");
    }

    /**
     * @param args
     */
    public static void main ( String[] args )
    {

        new Content().fetchContentFromURL( "http://www.google.co.in" );
    }

}

私は他のソリューションにもオープンですが、サードパーティではなくコア Java Api のみに固執したいと考えています。

4

3 に答える 3

2

ここで考えられるオプションの 1 つは、巡回パスを回避するために、訪問したすべてのリンクを記憶することです。既にアクセスしたリンク用に追加の Set ストレージを使用してアーカイブする方法は次のとおりです。

public class Content {
private static final String HTML_A_HREF_TAG_PATTERN =
        "\\s*(?i)href\\s*=\\s*(\"([^\"]*\")|'[^']*'|([^'\">\\s]+))";
private Pattern pattern;
private Set<String> visitedUrls = new HashSet<String>();

public Content() {
    pattern = Pattern.compile(HTML_A_HREF_TAG_PATTERN);
}

private void fetchContentFromURL(String strLink) {
    String content = null;
    URLConnection connection = null;
    try {
        connection = new URL(strLink).openConnection();
        Scanner scanner = new Scanner(connection.getInputStream());
        scanner.useDelimiter("\\Z");
        if (scanner.hasNext()) {
            content = scanner.next();
            visitedUrls.add(strLink);
            fetchURL(content);
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

private void fetchURL(String content) {
    Matcher matcher = pattern.matcher(content);
    while (matcher.find()) {
        String group = matcher.group();
        if (group.toLowerCase().contains("http") || group.toLowerCase().contains("https")) {
            group = group.substring(group.indexOf("=") + 1);
            group = group.replaceAll("'", "");
            group = group.replaceAll("\"", "");
            System.out.println("lINK " + group);
            if (!visitedUrls.contains(group) && visitedUrls.size() < 200) {
                fetchContentFromURL(group);
            }
        }
    }
    System.out.println("DONE");
}

/**
 * @param args
 */
public static void main(String[] args) {
    new Content().fetchContentFromURL("http://www.google.co.in");
}

}

また、ロジックのフェッチに関するその他の問題も修正し、期待どおりに動作するようになりました。

于 2013-10-31T05:45:39.090 に答える
1

JK1 の回答に加えて、質問のターゲット 4 を達成するために、ハイパーリンクの数をインスタンス変数として維持したい場合があります。大まかな疑似コードは次のようになります (正確な数を調整できます。また、HashSet の長さを使用して、プログラムがこれまでに解析したハイパーリンクの数を知ることもできます):

if (!visitedUrls.contains(group) && noOfHyperlinksVisited++ < 200) {
            fetchContentFromURL(group);
}

ただし、合計 200 個のハイパーリンクが必要なのか、それとも開始ページから 200 個のリンクの深さまでトラバースしたいのか、私にはわかりませんでした。それが遅い場合は、Breadth First Searchを探索することをお勧めします。これにより、ターゲットの深さに到達したときに通知されます。

于 2013-10-31T05:56:52.870 に答える
1

fetchContentFromURL メソッド内で、現在フェッチしている URL を記録し、その URL が既にフェッチされている場合はスキップします。そうしないと、相互にリンクポイントを持つ2つのページA、Bがコードをフェッチし続けます。

于 2013-10-31T05:38:17.273 に答える