找不到元素Selenium C#

时间:2018-08-17 12:22:37

标签: c# selenium selenium-webdriver webdriver phantomjs

URL:http://bcmprod.brill.com/rsuite-cms/

我正在尝试自动从上述客户端站点下载手稿。我在C#中使用硒phantomjs。

我有用户凭据。但是构成登录表单的元素(例如用户名,密码)在页面源中不存在,但是当您在浏览器中检查这些元素时就存在。

这些是我用来从“检查元素”中定位它们的xpath(动态分配了ID,这就是为什么我不使用它们的原因):

string xpathUsername = ".//input[@name='user']";
string xpathPassword = ".//input[@name='pass']";
string xpathBtnLogin = ".//button[@type='submit'][@aria-label='Log In']";

当驱动程序返回的源没有登录元素从而无法找到但在浏览器中检查它们存在时,如何成功登录?

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.IO;
using OpenQA.Selenium;
using OpenQA.Selenium.PhantomJS;
using OpenQA.Selenium.Support.UI;
using WebCrawler.Helper;

namespace WebCrawler.Webcodes
{
    class RSuite : IWebcode
    {
        List<string> errors = new List<string>();
        string xpathUsername = ".//input[@name='user']";
        string xpathPassword = ".//input[@name='pass']";
        string xpathBtnLogin = ".//button[@type='submit'][@aria-label='Log In']";

        public RSuite()
        { }

        public List<Record> GetRecords()
        {
            Console.WriteLine(string.Format("Crawling:  {0}", Config.Url));
            List<Record> recordList = new List<Record>();
            try
            {
                PhantomJSDriverService service = PhantomJSDriverService.CreateDefaultService();
                service.HideCommandPromptWindow = true;

                using (IWebDriver driver = new PhantomJSDriver(service))
                {
                    driver.Navigate().GoToUrl(Config.Url);
                    Console.WriteLine("\nChecking elements availability ...");

                    // code exception here: I couldn't get all these elements
                    IWebElement username = Element("User ID", GetElement(driver, xpathUsername));
                    IWebElement password = Element("Password", GetElement(driver, xpathPassword));
                    IWebElement btnlogin = Element("Login Button", GetElement(driver, xpathBtnLogin));

                    // input credentials
                    Console.WriteLine("\nAttempting to login ...");
                    if (username != null && password != null && btnlogin != null)
                    {
                        username.Clear();
                        username.SendKeys(Config.Username);
                        password.Clear();
                        password.SendKeys(Config.Password);

                        // is button clicked & loaded a new page? (If true, login is successful)
                        if (IsPageLoaded(driver, btnlogin))
                        {
                            Console.WriteLine("Logged in successfully.");
                            // do some action
                            // download files
                        }
                        else
                        { ErrorHandler("Login failed."); }
                    }
                    else
                    { ErrorHandler("Login failed."); }
                }
                // release
                service.Dispose();
            }
            catch (Exception err)
            { ErrorHandler(err.GetBaseException().ToString()); }

            // generate report for caught errors, if any
            if (errors.Count() > 0)
                Config.ErrorReport(this.GetType().Name.Trim().ToUpper(), string.Join("\n\n", errors));

            return recordList;
        }


        private IWebElement GetElement(IWebDriver driver, string xPath)
        {
            IWebElement element = null;
            try
            {
                // wait for elements to load
                WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
                Func<IWebDriver, IWebElement> waitForElement = new Func<IWebDriver, IWebElement>((IWebDriver d) =>
                {
                    element = d.FindElement(By.XPath(xPath));
                    if (element != null)
                    { return element; }
                    return null;
                });
                return wait.Until(waitForElement);
            }
            catch (Exception err)
            {
                ErrorHandler(err.GetBaseException().ToString());
                return null;
            }
        }


        private IWebElement Element(string label, IWebElement element)
        {
            if (element != null)
            { Console.WriteLine(string.Format("{0}:  Yes", label)); }
            else
            { Console.WriteLine(string.Format("{0}:  No", label)); }
            return element;
        }


        private bool IsPageLoaded(IWebDriver driver, IWebElement element)
        {
            try
            {
                // page redirected? Or is the element still attached to the DOM?
                WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
                element.Click();
                return wait.Until(ExpectedConditions.StalenessOf(element));
            }
            catch (Exception err)
            {
                ErrorHandler(err.GetBaseException().ToString());
                return false;
            }
        }

        private void ErrorHandler(string error)
        {
            Console.WriteLine(error);
            errors.Add(error);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

根据您的问题, url http://bcmprod.brill.com/rsuite-cms/基于Ember.js,因此您必须将 WebDriverWait ExpectedConditions结合使用方法ElementToBeClickable(),当您寻找元素时。

用于标识所需文件的Locator Strategies如下:

  • User ID

    string username = "//input[@class='ember-view ember-text-field finput text-field component' and @name='user']";
    
  • Password

    string password = "//input[@class='ember-view ember-text-field finput text-field component' and @name='pass']";
    
  • Log In

    string loginbtn = "//label[@class='ui-button-text']";