我正在尝试创建一个获取特定页面的单词和链接的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);
}
}
}
如您所见,我只能将其分支到第二组链接。我希望它分支出来,直到没有任何链接没有被访问过。我只是不知道如何实现这一点。
答案 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 A
有Page 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
}
}