[robot]selenium常用的語法

  • 1374
  • 0
  • 2020-08-07

[robot]selenium常用的語法

以下是常用的UI control控制喔:(Selenium version 3.4)

//找出某textbox並設定text文字
IWebElement userName = _driver.FindElement(By.CssSelector("input[type='text'].form-control"));
userName.SendKeys("myaccount");
//清空textbox
userName.Clear();
//確認有輸入查詢條件
for (int i = 0; i < 3; i++)
{
	if (userName.GetAttribute("value") != eventCode)
	{
		//如果輸入查詢條件失敗
		//就再輸入一次
		userName.Clear();
		userName.SendKeys(eventCode);
		SpinWait.SpinUntil(() => false, 1000);
	}
	else
	{
		//如果已經成功輸入查詢條件
		//就跳出迴圈
		break;
	}

}

if (userName.GetAttribute("value") != eventCode)
{
	//如果輸入查詢條件還是失敗, 就結束程式
	//讓Thread自動ThreadMonitor()被復活囉
	string errMsg = "輸入查詢條件textbox的過程中發生錯誤!";
	//寫log
	ThrowAndLog(errMsg);
	//throw new Exception(errMsg);

}
//取得textbox的value
string inputText = inputQuery.GetAttribute("value");
//設定textbox的value
IWebElement password = _driver.FindElement(By.CssSelector("input[type='password'].form-control"));
password.SendKeys("mypassword");
//找出某button並按下按鈕
IWebElement submit = _driver.FindElement(By.CssSelector("input[type='submit']"));
submit.Click();

//等候幾秒讓瀏覽器載入完畢
SpinWait.SpinUntil(() => false, 3000);
Application.DoEvents();

//選擇下拉式選單
using OpenQA.Selenium.Support.UI;
IWebElement iSelectQuery = _driver.FindElement(By.CssSelector("#selectId"));
SelectElement selectQuery = new SelectElement(iSelectQuery);
selectQuery.SelectByText("This is option Text");
selectQuery.SelectByValue("optionValue");

//等待某元素的出現(用正規運算式確認是否出現)讓網頁載入完畢 3x1000/1000 秒
WaitForElement(ref _driver, "RegPattern", 3, 1000);
/// <summary>
/// 以正規運算式判斷目標的元素是否已經成功載入(extension)
/// </summary>
/// <param name="driver"></param>
/// <param name="pattern"></param>
/// <param name="retryCount">最多重複檢查幾次</param>
/// <param name="retryInterval">每次檢查間隔幾秒</param>
/// <returns></returns>
public static bool WaitForElement(this IWebDriver driver, string regPattern, int retryCount = 10, int retryInterval = 1000)
{
	try
	{
		for (int i = 0; i < retryCount; i++)
		{
			Match m = Regex.Match(driver.PageSource, regPattern, RegexOptions.Singleline);

			if (m.Success == false)
			{
				SpinWait.SpinUntil(() => false, retryInterval);

			}
			else
			{
				return true;
			}
		}
		//int zero = 0;
		//int abc = 777 / zero;//強制出現throws
		return false;
	}
	catch (Exception ex)
	{
		//throw ex;
		return false;
	}
}

//強制等候幾秒讓瀏覽器載入完畢
SpinWait.SpinUntil(() => false, 15000);



//閒置並可接受後續的指令
while (true)
{
	//do anything you want

	SpinWait.SpinUntil(() => false, 1000);
	Application.DoEvents();
}

//其他好用的By
//By.XPath在網頁的element都長的超級像的時候很好用(長的超級像的時候,通常用By.CssSelector就會很難用)
IWebElement playHref = _driver.FindElements(By.XPath("//*[@id=\"main-content\"]/span/div[2]/div/ul/li[7]/div/div[3]/div/div[1]/a")).LastOrDefault();//error頁
//利用javascript取得IWebElement, 之後再用selenium內建功能去設定textbox的value
IWebElement element = (IWebElement) ((IJavaScriptExecutor)driver).ExecuteScript("return $('.cheese')[0]");
//或是乾脆直接執行javascript去設定element的內容(經實戰驗證,這個是控制網頁element最好用的語法)
((IJavaScriptExecutor)driver).ExecuteScript("$('input[name*=CustomerId]').val('777')");

//**********範例:直接執行javascript******************
string clientID = "YourAccount";
string password = "YourPassword";
//輸入帳號
((IJavaScriptExecutor)driver).ExecuteScript("$('input[name*=CustomerId]').val('" + clientID + "')");
//輸入密碼
((IJavaScriptExecutor)driver).ExecuteScript("$('input[name*=Password]').val('" + password + "')");
//按下login
((IJavaScriptExecutor)driver).ExecuteScript("$('#loginControlsButton').click()");
SpinWait.SpinUntil(() => false, 7000);
//按下continue按鈕表示不儲值
((IJavaScriptExecutor)driver).ExecuteScript("$('a.general_button.green.loginNext')[0].click()");
SpinWait.SpinUntil(() => false, 7000);
//按下span的文字
((IJavaScriptExecutor)driver).ExecuteScript("$('span.switch-data')[0].click()");



//画面向下卷动
((IJavaScriptExecutor)driver).ExecuteScript("$(\"html, body\").animate({ scrollTop: $(document).height() }, 1000);");
//click一个href( > a 表示是 parent关系)
((IJavaScriptExecutor)driver).ExecuteScript("$(\".dota2.jq-game-type-tips > a\").click();");
SpinWait.SpinUntil(() => false, 2000);
//click一个href( space a 表示是 parent, grandparent, grandgrandparent关系)
((IJavaScriptExecutor)driver).ExecuteScript("$(\".dota2.jq-game-type-tips a\").click();");
SpinWait.SpinUntil(() => false, 2000);


//將chrome執行的目標切換到某某iframe
//因為有很多網站是用iframe做網頁排版的
//要切換過去,selenium才能正常抓到IWebElement
IWebDriver driver;
ChromeOptions chromeBrowserOptions = new ChromeOptions();
driver = new ChromeDriver(@"ChromeDriver", chromeBrowserOptions);
driver.SwitchTo().Frame(0);    

ps. By.CssSelector最好用之外,其他的By LinkText也不錯用喔,因為By.CssSelector有個缺點就是他的語法不能針對某個tag裡的文字,因為他的css selector不夠新,例如某個span裡的文字或是某個超連結裡面有放一些顯示在畫面上的中文字,這些文字在最新的css selector都可用來當成搜尋條件,但是在selenium的By.CssSelector則沒辦法,可能是比較舊的關係

常用語法2:

/// <summary>
/// 以不同的By來等候目標的element出現(extension)
/// </summary>
public static bool WaitForElement(this IWebDriver driver, By by, int timeoutInSeconds = 10)
{
	var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
	IWebElement element;
	try
	{
		element = wait.Until(drv => drv.FindElement(by));
		if (element != null)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	catch
	{
		return false;
	}
	
}//ps.不過個人的習慣上還是直接執行javascript做下一步,這個WaitForElement說實在不常用

/// <summary>
/// 重複執行限定最多N次的javascript直到成功(extension)
/// </summary>
/// <param name="script"></param>
/// <param name="retryCount"></param>
/// <param name="retryInterval"></param>
/// <returns></returns>
public static bool RunScript(this IWebDriver driver,string script, int retryCount = 10, int retryInterval  = 1000)
{
	for (int i = 1; i <= retryCount; i++)
	{
		try
		{
			if (i > 1)
			{
				SpinWait.SpinUntil(() => false, retryInterval);
			}

			((IJavaScriptExecutor)driver).ExecuteScript(script);                    
			return true;
		}
		catch (WebDriverException ex)
		{
			return false;
		}
		catch (Exception ex)
		{
			return false;
		}
	}

	return false;
}


2020/08/05 補充
當執行上面的((IJavaScriptExecutor)_driver).ExecuteScript而且使用jQuery時候,有時候會出現錯誤 'javascript error: $ is not defined
把$改成document.querySelector就可以了,舉例來說,假設我原本的寫法如下,並且在selenium出現執行錯誤:
((IJavaScriptExecutor)_driver).ExecuteScript("$('a[href*=signin]').click()");

改成下面的寫法就OK囉
((IJavaScriptExecutor)_driver).ExecuteScript("document.querySelector('a[href*=signin]').click()");

參考資料:
自己的經驗
How to Using Webdriver Selenium for selecting an option in C#?
https://stackoverflow.com/questions/4249353/jquery-scroll-to-bottom-of-the-page
https://stackoverflow.com/questions/6992993/selenium-c-sharp-webdriver-wait-until-element-is-present
https://stackoverflow.com/questions/28670805/how-fix-selenium-webriver-error-is-not-defined