【问题标题】:Get destination URLs of HTML elements programatically using JavaScript - Java - Selenium使用 JavaScript - Java - Selenium 以编程方式获取 HTML 元素的目标 URL
【发布时间】:2021-01-24 20:48:14
【问题描述】:

有一个页面有很多指向任何地方的链接,但我无法获取目标 URL,因为在代码中似乎没有网址:

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

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

有没有办法以编程方式获取元素的目标 URL,最好不用导航到链接?我正在尝试将 JavaScript / Selenium 与 Java 结合使用。

我在想,通过触发onclick 事件并在重定向之前的某个时间点获取 URL 可能是可能的。

【问题讨论】:

    标签: javascript java selenium


    【解决方案1】:

    我解决的问题如下:

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

    因为我用的是ChromeDriver,所以下面的例子是在谷歌浏览器上运行的

    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();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      • 2012-04-14
      • 2013-07-14
      • 2017-05-18
      相关资源
      最近更新 更多