如何在网站上递归地查找所有URL - java



我有一个方法,允许我从页面获取所有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"))));
}
}

请参阅评论"这是我的递归试验"。但是它通过第一页,然后再次通过第一页,仅此而已。

您正在尝试编写网络爬虫。我是代码重用的忠实粉丝。 也就是说,在我花时间自己写之前,我总是环顾四周,看看我的项目是否已经写好了。并且有许多版本的网络爬虫。Marilena Panagiotidou写的一篇在谷歌搜索中很早就弹出了。撇开导入,她的基本版本看起来像这样。

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。

确保您没有两次访问同一个 URL。添加一些表,用于存储已访问的 URL。例如,由于每个页面都可能以链接到主页的标题开头,因此您最终可能会一遍又一遍地访问它。

最新更新