[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