【问题标题】:Struggling with Reusable Functions to Handle Frames努力使用可重用的函数来处理帧
【发布时间】:2015-10-15 10:10:57
【问题描述】:

我正在创建一个可重用的函数来处理帧,并且想点击 Fantasy11 网站上的“我不是机器人”复选框。它抛出异常 - 。 请帮忙。

我尝试了很多,但都在努力获得正确的结果。

import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class section9frames {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        WebDriver driver=new FirefoxDriver();
        driver.get("https://fantasycricket.dream11.com/IN/");
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        int number=findframenumber(driver,By.xpath(".//*[@id='recaptcha-anchor']/div[5]"));
        driver.switchTo().frame(number);
        driver.findElement(By.xpath(".//*[@id='recaptcha-anchor']/div[5]")).click();
        driver.switchTo().defaultContent();
        int number1=findframenumber(driver,By.xpath(".//*[@id='recaptcha-verify-button']"));
        driver.switchTo().frame(number1);
        driver.findElement(By.xpath(".//*[@id='recaptcha-verify-button']")).click();

    }

    public static int findframenumber(WebDriver driver,By by) {
        int i;
        int framecount=driver.findElements(By.tagName("iframe")).size();

        for (i=0;i<framecount;i++) {
            driver.switchTo().frame(i);
            int count=driver.findElements(by).size();
            if(count>0) {
                break;
            } else{

            }
        }
        driver.switchTo().defaultContent();
        return i;
    }
}

Please have a look into the image

【问题讨论】:

  • 有什么异常?
  • 线程“主”org.openqa.selenium.NoSuchFrameException 中的异常:无法定位框架:1
  • 所以你正在编写代码来创建一个机器人来绕过试图阻止机器人的功能......不要那样做。

标签: java selenium xpath selenium-webdriver webdriver


【解决方案1】:

我一直在为常见的 WebElement 交互开发自己的 API 包装器。我通过使用 java.lang.reflect.Proxy 类的装饰器模式解决了这个问题。

  public void exampleUse() {
        WebDriver driver = new FirefoxDriver();
        int frameIdInt = 1;
        String frameId ="someFrame";
        WebElement frameRef = driver.findElement(By.id(frameId));
        WebElement inFrameByIntId = frameSafeElement(driver, frameIdInt, By.id("element"));
        WebElement inFrameByStringId = frameSafeElement(driver, frameId, By.id("element"));
        WebElement inFrameByReference = frameSafeElement(driver, frameRef, By.id("element"));

        // Now you should be able to do anything you want with the WebElement through the WebElement API. All
        // invocations will go through the Proxy instance below which will switch to the frame, resolve the WebElement
        // reference in context of the frame, perform the desired function against the resolved WebElement, switch back
        // to default context, and return the results from the delegate invocation.
    }

    private final WebElement frameSafeElement(final WebDriver driver, final String frameId, final By lookup) {
        return (WebElement) java.lang.reflect.Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[]{WebElement.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try {
                    driver.switchTo().frame(frameId);
                    WebElement element = driver.findElement(lookup);
                    return method.invoke(element, args);
                } finally {
                    driver.switchTo().defaultContent();
                }
            }
        }) ;
    }
    private final WebElement frameSafeElement(final WebDriver driver, final int frameId,  final By lookup) {
        return (WebElement) java.lang.reflect.Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[]{WebElement.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try {
                    driver.switchTo().frame(frameId);
                    WebElement element = driver.findElement(lookup);
                    return method.invoke(element, args);
                } finally {
                    driver.switchTo().defaultContent();
                }
            }
        }) ;
    }
    private final WebElement frameSafeElement(final WebDriver driver, final WebElement frameReference,  final By lookup) {
        return (WebElement) java.lang.reflect.Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[]{WebElement.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try {                    
                    driver.switchTo().frame(frameReference);
                    WebElement element = driver.findElement(lookup);
                    return method.invoke(element, args);
                } finally {
                    driver.switchTo().defaultContent();
                }
            }
        }) ;
    }

对于上面的示例,您需要将实用程序方法设为静态以从您的 main 中引用它们,但它看起来像这样:

public static void main(String[] args) {
    WebDriver driver=new FirefoxDriver();
    driver.get("https://fantasycricket.dream11.com/IN/");
    driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

    int number=findframenumber(driver,By.xpath(".//*[@id='recaptcha-anchor']/div[5]"));
    WebElement firstFrameObject = frameSafeElement(driver, number, By.xpath(".//*[@id='recaptcha-anchor']/div[5]"));
    firstFrameObject.click();

    int number1=findframenumber(driver,By.xpath(".//*[@id='recaptcha-verify-button']"));
    WebElement secondFrameObject = frameSafeElement(driver, number, By.xpath(".//*[@id='recaptcha-verify-button']"));
    secondFrameObject.click()
 }

希望有帮助!

【讨论】:

  • 感谢 Jeremiah 的快速解决方案...如果您能帮助我更正 findframenumber(WebDriver driver,By by),那就太好了
  • 我认为,如果您将 findframenumber 的问题带到另一篇文章中,这将符合 StackOverflow 的精神,因为这超出了您对可重用 iframe 方法的原始查询的范围。请注意其他人留下的 cmets,并提供有关问题的更多详细信息以及您要实现的目标。您对问题越具体,人们就越容易理解问题并提供帮助。我会尽量留意那个线程并提供我能提供的帮助,但这种特别的努力有点超出我的驾驶室。祝你好运
  • 我只想创建一个可重用的函数,该函数将遍历每一帧并尝试通过使用 size() 方法检查元素可用性来定位元素列表界面。函数应该返回索引。我知道如果我们考虑性能,这不是有效的方法。我只是想以不同的方式执行框架查找。
  • 不过,这种一般逻辑存在问题。看起来您正在尝试动态查找每个框架,但是当您使用它们时,您正在搜索与该框架相关的特定内容。根据您的实现,您想要 div[5] 的第一帧和想要按钮的第二帧。在没有更多抽象的情况下,你不能在同一个实现中不可知和具体。即使这样,我也不确定从我所拥有的上下文中是否可能。我强烈建议您尝试重新评估您正在寻找的内容,并确保您正确地进行。
猜你喜欢
  • 2020-06-06
  • 1970-01-01
  • 2014-05-11
  • 2018-01-03
  • 1970-01-01
  • 2021-05-01
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
相关资源
最近更新 更多