使用JavaScript - Java - Selenium以编程方式获取HTML元素的目标url



有一个页面到处都是链接但我无法获得目标url因为代码中似乎没有网址这是这样的:

<li>
<a href="javascript:void(0)">
<span title="Text">Text</span>
</a>
</li>

有大量混淆的代码。我最好的猜测是,它可能是从一个微服务动态加载url。

是否有一种方法可以编程地获得元素的目标url,最好没有导航到链接?我正在尝试使用JavaScript/Selenium与Java。

我认为触发onclick事件并在重定向之前的某个时刻获得URL可能是可能的。

我是这样解决这个问题的:

  1. 使用JavaScript代码片段,重新定义了浏览器的window对象的open()方法来获取目标URL,并将其存储在全局上下文中,防止重定向。这个问题可能有用。
  2. 触发点击HTML链接元素运行底层XMLHttpRequest调用。
  3. 使用JavaScript的clearInterval()和Java的executeAsyncScript()方法,观察一个全局变量,直到它的值被设置(值由window.open()方法在元素被点击后设置)。

因为我使用的是ChromeDriver,下面的例子是在Google Chrome上运行

import java.io.IOException;
import org.openqa.selenium.By;
import org.openqa.selenium.ElementNotInteractableException;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class DeadLinkTest {
private static WebDriver driver;
private static WebDriverWait wait;
private static JavascriptExecutor js;

private static String driverAbsolutePath = "/chromedriver.exe";
private static String profileDirectory = "/myprofile";
//Look for a webpage that actually has elements like <a href='javascript:void(0);'> that causes redirection
private static String starterUrl = "https://www.google.com/";
//XPath for an element like <a href='javascript:void(0);'> 
private static final String DEAD_LINKS_XPATH = "//a[starts-with(translate(normalize-space(@href),' ',''),'javascript:void')]";
private static final String CLICK_ELEMENT_JS_CODE = "arguments[0].click();";
private static final String DOCUMENT_READY_JS_CODE = "return document.readyState;";
private static final String LINK_RESOURCE_URL_VAR_NAME = "window.redirectionUrl"; //global variable name
private static final String PREPARE_BROWSER_FOR_URL_EXTRACTION_JS_CODE =
"window.windowOpen = window.open;" + //backup original function
"window.isRedirectionEnabled = false;" + //turn on/off redirection via global variable
LINK_RESOURCE_URL_VAR_NAME + " = null;" + 
"window.open = function() {" + //redifine open() method
"    " + LINK_RESOURCE_URL_VAR_NAME + " = arguments[0];" + //put link's url into global variable
"    if(window.isRedirectionEnabled) {" + 
"        windowOpen.apply(this, arguments);" + 
"    }" + 
"};";
private static final String GET_LINK_RESOURCE_URL_JS_CODE =
"(function(seleniumCallback){" + //IIFE that recieves selenium's callback function from executeAsyncScript() method
"    let intervalId = setInterval(function(){" + 
"        if(" + LINK_RESOURCE_URL_VAR_NAME + ") {" + //check if global variable is still null
"            clearInterval(intervalId);" + 
"            let urlString = " + LINK_RESOURCE_URL_VAR_NAME + ";" + 
"            " + LINK_RESOURCE_URL_VAR_NAME + " = null;" + //set global variable to default state
"            seleniumCallback(urlString);" + //Send back the url to Java
"        }" + 
"    },0);" + 
"}(arguments[0]));";
public static ChromeDriver createChromeDriver() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--user-data-dir=" + profileDirectory + "/AppData/Local/Google/Chrome/User Data/Profile 2");
//options.addArguments("--profile-directory=Profile 2");
options.addArguments("--start-maximized");
//options.addArguments("--disable-extensions");
//options.addArguments("--no-sandbox");
System.setProperty("webdriver.chrome.driver", driverAbsolutePath);
return new ChromeDriver(options);
}
public static void main(String[] args) throws IOException {
driver = createChromeDriver();
wait = new WebDriverWait(driver, 30);
js = (JavascriptExecutor) driver;
try {
driver.manage().window().maximize();
driver.get(starterUrl);
wait.until(webDriver -> js.executeScript(DOCUMENT_READY_JS_CODE).toString().equals("complete")); //Checks that page is loaded

js.executeScript(PREPARE_BROWSER_FOR_URL_EXTRACTION_JS_CODE); //Avoids redirection and prepares global variable
WebElement deadLink = driver.findElement(By.xpath(DEAD_LINKS_XPATH));
try {
deadLink.click(); //Puts the link url into browser's global variable. See PREPARE_BROWSER_FOR_URL_EXTRACTION_JS_CODE
} catch (ElementNotInteractableException e) {
js.executeScript(CLICK_ELEMENT_JS_CODE, deadLink); //In case element is not clickable
}
String linkUrl = (String) js.executeAsyncScript(GET_LINK_RESOURCE_URL_JS_CODE);
System.out.println(String.format("TARGET URL: %s", linkUrl));
} catch (Exception e) {
e.printStackTrace();
} finally {
//driver.quit();
}
}
}

最新更新