我有一个方法,允许我从页面获取所有URL(和可选 - 检查它是否有效)。 但它只适用于1页,我想查看所有的网站。需要进行递归。
private static FirefoxDriver driver;
public static void main(String[] args) throws Exception {
driver = new FirefoxDriver();
driver.get("https://example.com/");
List<WebElement> allURLs = findAllLinks(driver);
report(allURLs);
// here are my trials for recursion
for (WebElement element : allURLs) {
driver.get(element.getAttribute("href"));
List<WebElement> allUrls = findAllLinks(driver);
report(allUrls);
}
}
public static List findAllLinks(WebDriver driver)
{
List<WebElement> elementList = driver.findElements(By.tagName("a"));
elementList.addAll(driver.findElements(By.tagName("img")));
List finalList = new ArrayList();
for (WebElement element : elementList)
{
if(element.getAttribute("href") != null)
{
finalList.add(element);
}
}
return finalList;
}
public static void report(List<WebElement> allURLs) {
for(WebElement element : allURLs){
System.out.println("URL: " + element.getAttribute("href")+ " returned " + isLinkBroken(new URL(element.getAttribute("href"))));
}
}
参见评论&#34;这是我的递归试验&#34;。但它通过第一页,然后再通过第一页,这就是全部。
答案 0 :(得分:1)
您正在尝试编写网络抓取工具。我是代码重用的忠实粉丝。也就是说我总是环顾四周,看看我的项目是否已经写完,然后才花时间自己编写。并且有很多版本的网络抓取工具。一个由Marilena Panagiotidou编写pops up early in a google search。退出进口,她的基本版本看起来像这样。
public class BasicWebCrawler {
private HashSet<String> links;
public BasicWebCrawler() {
links = new HashSet<String>();
}
public void getPageLinks(String URL) {
//4. Check if you have already crawled the URLs
//(we are intentionally not checking for duplicate content in this example)
if (!links.contains(URL)) {
try {
//4. (i) If not add it to the index
if (links.add(URL)) {
System.out.println(URL);
}
//2. Fetch the HTML code
Document document = Jsoup.connect(URL).get();
//3. Parse the HTML to extract links to other URLs
Elements linksOnPage = document.select("a[href]");
//5. For each extracted URL... go back to Step 4.
for (Element page : linksOnPage) {
getPageLinks(page.attr("abs:href"));
}
} catch (IOException e) {
System.err.println("For '" + URL + "': " + e.getMessage());
}
}
}
public static void main(String[] args) {
//1. Pick a URL from the frontier
new BasicWebCrawler().getPageLinks("http://www.mkyong.com/");
}
}
这里要注意的最重要的事情可能是递归是如何工作的。递归方法是自称的方法。上面的例子不是递归。您有一个方法findAllLinks,您在页面上调用一次,然后对页面中找到的每个链接调用一次。请注意Marilena的getPageLinks方法如何为在给定URL的页面中找到的每个链接调用一次。在调用自身时,它会创建一个新的堆栈帧,并从页面生成一组新的链接,并为每个链接再次调用一次等等。
关于递归函数的另一个重要注意事项是它何时停止调用自身。在这种情况下,Marilena的递归函数一直在调用自己,直到它找不到任何新的链接。如果您要抓取的页面链接到其域外的页面,则此程序可能会运行很长时间。而且,顺便说一下,在这种情况下可能发生的事情是这个网站得到它的名字:StackOverflowError。
答案 1 :(得分:0)
确保您没有两次访问同一个网址。添加一些用于存储已访问过的URL的表。由于每个页面都可能以链接到主页的标题开头,因此您可能会一次又一次地访问它。