如何使用Selenium WebDriver(Java)获取网站全页面所有链接?
使用Selenium WebDriver (Java) 爬取全站所有链接
要实现全站链接爬取,核心是用**广度优先搜索(BFS)**遍历页面,配合已访问链接集合去重,避免重复爬取和循环跳转。以下是具体实现方案:
核心逻辑
- 维护一个待爬队列和已访问链接集合,从起始URL开始
- 逐个处理队列中的URL,提取页面所有
<a>标签链接 - 过滤无效、外部及已访问的链接,将符合条件的链接加入队列
- 循环直到队列空,即完成全站遍历
Java代码实现
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import java.net.URI; import java.net.URISyntaxException; import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; import java.util.Set; public class FullSiteLinkScraper { public static void main(String[] args) { // 配置ChromeDriver路径,替换为你的实际路径 System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); // 优化Chrome配置:无头模式(不显示浏览器窗口)、禁用图片加载提升速度 ChromeOptions options = new ChromeOptions(); options.addArguments("--headless=new"); options.addArguments("--disable-images"); // 避免被网站检测为自动化工具 options.addArguments("--disable-blink-features=AutomationControlled"); options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"); WebDriver driver = new ChromeDriver(options); // 目标网站起始URL和域名 String startUrl = "https://example.com"; String targetDomain = extractDomain(startUrl); Queue<String> crawlQueue = new LinkedList<>(); Set<String> visitedLinks = new HashSet<>(); // 初始化队列和已访问集合 crawlQueue.add(startUrl); visitedLinks.add(startUrl); while (!crawlQueue.isEmpty()) { String currentUrl = crawlQueue.poll(); try { driver.get(currentUrl); // 显式等待页面加载完成(可选,根据页面结构调整等待条件) // WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); // wait.until(ExpectedConditions.visibilityOfElementLocated(By.tagName("body"))); // 遍历页面所有<a>标签 for (WebElement linkElement : driver.findElements(By.tagName("a"))) { String href = linkElement.getAttribute("href"); if (href == null || href.trim().isEmpty()) { continue; } // 转换相对路径为绝对URL if (!href.startsWith("http")) { href = driver.getCurrentUrl() + href; // 修复URL拼接时的重复斜杠问题 href = href.replaceAll("(?<!http:)//", "/"); } // 过滤无效链接(javascript、mailto等)和外部链接 if (href.startsWith("javascript:") || href.startsWith("mailto:") || !extractDomain(href).equals(targetDomain)) { continue; } // 未访问过的链接加入队列和已访问集合 if (!visitedLinks.contains(href)) { visitedLinks.add(href); crawlQueue.add(href); System.out.println("新增链接:" + href); } } } catch (Exception e) { System.err.println("处理链接 " + currentUrl + " 失败:" + e.getMessage()); } } // 输出结果 System.out.println("\n全站共爬取到 " + visitedLinks.size() + " 个链接:"); visitedLinks.forEach(System.out::println); driver.quit(); } // 提取URL的域名,用于过滤外部链接 private static String extractDomain(String url) { try { URI uri = new URI(url); return uri.getHost(); } catch (URISyntaxException e) { return ""; } } }
关键注意事项
- 去重机制:用
HashSet存储已访问链接,确保每个页面只爬取一次 - 性能优化:启用无头模式、禁用媒体加载,减少资源占用;可设置页面加载超时
- 反爬规避:配置真实的User-Agent,禁用自动化标识,必要时加入随机等待(
Thread.sleep(new Random().nextInt(2000) + 1000)) - 异常处理:捕获页面加载失败、元素查找失败等异常,避免程序中断
- 相对路径处理:将相对路径转换为绝对URL,避免无效链接
内容的提问来源于stack exchange,提问作者Chinmay Agrawal
相关产品推荐
相关产品推荐

