Selenium webdriver系统无效强制转换异常

本文关键字:转换 异常 无效 webdriver 系统 Selenium | 更新日期: 2023-09-27 17:50:32

为了在c#中为神经网络收集一些测试数据,我想使用Selenium来抓取一些动态生成的数据WSJ。Selenium站点上有一个示例实现,它似乎正好满足了我的需求:查找页面上每个标签的所有输入元素。这个例子在TagName上搜索,我在ClassName上搜索,但除此之外,我认为它们是相同的。然而,当我运行这段代码时,用IWebElements创建IList可以工作,但是下面的IJavaScriptExecutor抛出了一个Invalid Cast异常:

无法强制转换类型的对象System.Collections.ObjectModel.ReadOnlyCollection 1(系统。对象)输入System.Collections.Generic.IList 1 (OpenQA.Selenium.IWebElement)

这里是一小段代码,这是"text",我对"num"做同样的事情:

    // Find elements by class name
    IList<IWebElement> labels = driver.FindElements(By.ClassName("text"));
    // get all input elements for every class label
    IList<IWebElement> labVals = (IList<IWebElement>)((IJavaScriptExecutor)driver).ExecuteScript(
        "var labels = arguments[0], labVals = []; for (var i=0; i < labels.length; i++){" +
        "labVals.push(document.getElementById(labels[i].getAttribute('for'))); } return labVals;", labels);

我已经看过这个问题Selenium Web Driver c# InvalidCastException,它可能指向相同的问题,但我不知道所提供的答案如何帮助我。

一个选项可能是将IJavaScriptExecutor语句分解为"离散"代码,但我不知道如何做到这一点。

一旦我在List结构中有了文本标签和数据值,我应该能够找到我需要的数字。

Selenium webdriver系统无效强制转换异常

这不是使用javascript,但它将工作。我会使用CssSelector方法,通过参数接收您需要的列/行,然后您将使用循环调用此方法以从页面获取所有信息。

检查页面的css这是我从第一列/行

得到的结果
table.mdcTable > tbody > tr:nth-of-type(3) > td:nth-of-type(1)

因此,数字"3"与第一行有关,"1"是第一列。所以我们可以创建一个方法来返回你想要的元素:

public IWebElement test(int line, int row)
    {
        return driver.FindElement(By.CssSelector(string.Format("table.mdcTable > tbody > tr:nth-of-type({}) > td:nth-of-type({})", line + 2, row)));
    }

调用此方法将返回包含文本的元素,因此您只需使用'element '即可。将Text'替换为'cell'的值,或者让方法直接返回文本。

public String test(int line, int row)
    {
        return driver.FindElement(By.CssSelector(string.Format("table.mdcTable > tbody > tr:nth-of-type({}) > td:nth-of-type({})", line + 2, row))).Text;
    }

唯一的问题是"Latest"列,因为它们不仅包含数字,还包含一个栏。您必须创建一个方法来只处理这些列。

结果会是这样的:

            try
            {
                int line = 1;
                int column = 1;
                while(column <= 7)
                    valueOfTheCell = test(line, column);
                getLatestGreen(line); //string.Format("tbody > tr:nth-of-type({0}) > td:nth-of-type(9) > span.text", line)
                getLatestRed(line);  //string.Format("tbody > tr:nth-of-type({0}) > td:nth-of-type(8) > span.text > b", line)
            }
            catch (NoSuchElementException)
            {
                //Exception will be thrown when the code reaches the end of the list
            }

我不会说这是最优的,但它是一个选择。如果你想这样做,我可以帮助你解决任何关于如何使用选择器的问题。

转换错误发生,因为IJavascriptExecutor输出一般的System.Object类MSDN,然后我尝试转换为IWebElement。这可能在某些情况下起作用,但在这种情况下不起作用。将接收IList更改为IList<Object>可以解决强制转换异常。用这个代码运行,然后我用调试器发现所有数据都是用Labels列表中的代码的第一部分捕获的。IJavaScriptExecutor只返回空项。所以在我的例子中不需要第二步。