制作蜘蛛爬行网站

时间:2015-11-09 20:08:47

标签: java web webpage

我正在尝试创建一个获取特定页面的单词和链接的java类。我们说该页面是stackoverflow.com。我希望班级首先检查并存储该页面上的所有链接。在它存储并检查了该页面上的所有链接后,我希望它分支到第一页中的每个页面,然后再次检查所有链接,直到它完全分支并检查所有链接。我只设法将它分支到第二组链接。这是代码:

  public void spiderLeg(String webAdress){
  public HashSet < String > getLink = new HashSet <String>();
    a = new Reader(webAdress);
    a.run();
    System.out.println("CRAWLING");
    for(String s : a.getLinks()){
        getLink.add(s);
        a = new Reader(s);
        a.run();

        for(String v : a.getLinks()){
            getLink.add(v);
            a = new Reader(v);
            a.run();
        }
        for(String h : l.getLinks()){
            getLink.add(h);
        }

    }


}

如您所见,我只能将其分支到第二组链接。我希望它分支出来,直到没有任何链接没有被访问过。我只是不知道如何实现这一点。

1 个答案:

答案 0 :(得分:0)

您所描述的是递归操作,而不是循环操作。

如果s是一个地址,就像最初传递给该方法的地址一样,那么递归调用s方法。像这样:

public void spiderLeg(String webAdress){
    public HashSet < String > getLink = new HashSet <String>();
    a = new Reader(webAdress);
    a.run();
    System.out.println("CRAWLING");
    for(String s : a.getLinks()){
        getLink.add(s);
        a = new WebPageReader(s);
        a.run();

        spiderLeg(s); // <-- here
    }
}

这样你就不必知道或控制如何深入&#34;一系列的链接得到。每个页面都会在&#34; next&#34;上调用相同的方法。一组链接。

请注意,您肯定会想要为此代码添加更多条件。对所有找到的链接进行盲目递归会带来无限递归的巨大风险。考虑当Page APage B链接时会发生什么,而Page B又有Page A的链接。它甚至可能不那么明显,中间可能有几页。链接可能不完全相同。

作为思考练习,请考虑一个页面,其中包含可以来回分页的记录表。每个&#34;页面&#34;将会有前一页和下一页的链接,以及它们之间的几个编号页面。所以在所有页面之间会有很多链接来回。那些链接可能不是是相同的字符串,它们可以将各种查询字符串参数相互传递。

一般情况下,您可能会有一些尝试和错误来回答问题&#34;我是否已经在此过程中访问过此页面?&#34;你甚至可能想要添加一个&#34;最大深度&#34;到递归以避免无限递归。它基本上是该方法的另一个参数,它每次递增并与常数进行比较。它可能就像这样简单:

public void spiderLeg(String webAdress, int depth){

    // check against a "max depth constant"
    if (depth > 10){
        return;
    }

    public HashSet < String > getLink = new HashSet <String>();
    a = new Reader(webAdress);
    a.run();
    System.out.println("CRAWLING");
    for(String s : a.getLinks()){
        getLink.add(s);
        a = new WebPageReader(s);
        a.run();

        spiderLeg(s, depth + 1); // increment the depth
    }
}

修改:您的getLink变量似乎也需要移动到更高的范围。这是因为对此方法的每次递归调用都将拥有自己的变量副本,因此每个调用都将在HashSet中具有完全一个元素。相反,使它成为一个类级别的成员。像这样:

private HashSet < String > getLink = new HashSet <String>();

public void spiderLeg(String webAdress, int depth){

    // check against a "max depth constant"
    if (depth > 10){
        return;
    }

    a = new Reader(webAdress);
    a.run();
    System.out.println("CRAWLING");
    for(String s : a.getLinks()){
        getLink.add(s);
        a = new WebPageReader(s);
        a.run();

        spiderLeg(s, depth + 1); // increment the depth
    }
}

这样,对方法的每次递归调用都会添加到同一个HashSet,而不是创建自己的。{/ p>

编辑:根据正在进行的评论,看起来需要进一步简化。也许是这样的事情?:

private HashSet < String > getLink = new HashSet <String>();

public void spiderLeg(String webAdress, int depth){

    // recursion terminating condition, check for maximum depth
    if (depth > 10){
        return;
    }

    // perform operation on this node
    getLink.add(webAdress);
    a = new Reader(webAdress);
    a.run();
    System.out.println("CRAWLING");

    // recurse on next nodes
    for(String s : a.getLinks()){
        spiderLeg(s, depth + 1); // increment the depth
    }
}