【C#】Selenium的概念與操作方法

  • 9018
  • 0
  • C#
  • 2020-11-26

筆者近期都在忙著籌備第二個專案,最近在研究Selenium的使用方法,日後會用來抓取專案會使用的資料。Selenium常常伴隨著出現的關鍵字可能會是自動化測試、爬蟲,究竟Selenium到底是什麼,又可以做些甚麼事情,就讓我們繼續看下去!

 

 

什麼是Selenium?


Selenium是為瀏覽器自動化需求所設計的開源工具集合(參1),像是在網頁中常見的操作功能,透過網址拜訪該網頁、上下頁等,可透過各程式語言(C#、Python、JAVA等)開發,並轉換成HTTP的請求,並直接運行在瀏覽器中。更白話一點,就是透過程式碼模擬人類操作瀏覽器的行為

在正式講解Selenium的操作之前,也順便提一下Selenium的歷史脈絡(參2)。從2004年起,由ThoughtWorks公司開發出了Selenium 1.0Selenium 1.0 包含了 Selenium IDE + Selenium Grid + Selenium RCSelenium 1.0使用JavaScript與瀏覽器溝通及調用元素,統一透過Selenium RC的伺服器作為代理伺服器,其中Client Libraries是撰寫指令程式碼,用來控制Selenium Server,而Selenium Server則負責控制瀏覽器的行為(參3)。

(圖片來源,參4)

2007年ThoughtWorks的Simon Stewart開發出名為WebDriver的高級瀏覽器自動化工具,故Selenium 2.0 = WebDriver + Selenium 1.0。Selenium 2.0的核心就在於將Selenium RC 更換成WebDriver,WebDriver一樣可以直接操作瀏覽元素,甚至還可以控制瀏覽器本身(視窗大小、截圖、新增關閉頁面等),但WebDriver是針對各瀏覽器而獨立設計,故在速度上會比Selenium 1.0更快。另外,順道一提,自動化測試工具可不是只有Selenium,像QTPloadrunner等都可以做到自動化測試 (參5)。

圖片來源(參4),
 

Selenium的概念與操作


搜索 Selenium關鍵字,出現的幾乎都是Python的教學,筆者之前也是使用Python的Selenium,但感覺C#在觀念上都差不多,只是函數名稱有點不太一樣而已。剛剛上一節提到,Selenium 2.0之後重點在於WebDriver,而WebDriver又依瀏覽器類型及版本作區分,所以第一個學習重點就是要找到對應的WebDriver。


查看瀏覽器的版本

Chrome:

Firefox:

確定版本後就可以去下載對應的版本囉(參6參7),其他的瀏覽器就自行尋找囉!



C#專案中安裝並啟用WebDriver


如果把WebDriver的檔案跟C#專案放在同一個資料夾裡,只要下列指令就可以囉

IWebDriver driver = new ChromeDriver();

因筆者想做一些測試,故建立類別放入瀏覽器類別與路徑

IWebDriver driver;
public Selenium(String browser, string path)
{
    switch (browser.ToLower())
    {
        case "chrome":
            this.driver = new ChromeDriver(path);
            break;
        case "firefox":
            this.driver = new FirefoxDriver(path);
            break;
        case "ie":
            this.driver = new InternetExplorerDriver(path);
        default:
            this.driver = new ChromeDriver(path);
            break;
     }
}


Selenium常見功能
這裡介紹一些常用的方法。

IWebDriver driver = new ChromeDriver();

//拜訪URL
driver.Navigate().GoToUrl("https://www.ptt.cc/bbs/hotboards.html")

//返回上一頁
driver.Navigate().Back ( );

//設定cookie,如PTT 八卦版需要new Cookie("over18","1")
driver.Manage().Cookies.AddCookie(new Cookie(key, value));

//找網頁元素,定位後可再接Text、Click、SendKeys等取文字或瀏覽器操作
driver.FindElement()
driver.FindElements()


//定位元素
//driver.FindElement(By.Id("main-content"))
//driver.FindElement(By.CssSelector("#main-content > div:nth-child(4) > span,article-meta-value"))
//driver.FindElement(By.ClassName("push"))


Selenium進階寫法,利用轉型實現更多功能

//透過javascript的語法,新增分頁並拜訪網頁
((IJavaScriptExecutor)driver).ExecuteScript($"window.open('{url}');"); 
driver.SwitchTo().Window(driver.WindowHandles.Last()); //將控制權更改為最後一個分頁
driver.SwitchTo().Window(driver.WindowHandles[driver.WindowHandles.Count - 1]) //也可以這樣寫

//截圖
Screenshot screenshot = ((ITakesScreenshot)selenium).GetScreenshot();
screenshot.SaveAsFile("beauty.jpg", ScreenshotImageFormat.Jpeg);


強制等待、顯式等待與隱式等待

使用Selenium在取網頁元素時,可能會發生該元素尚未被渲染,所以會有可能抓不到該元素,因此一個完整的selenium架構中,也應該要寫好等待的規則,並針對報錯的狀態做處理。

強制等待: 顧名思義就是傻傻地等,故非必要不使用。
隱式等待: 比強制等待更聰明一點,只需要宣告一次,之後只要開啟新的頁面或URL,會判斷整個網頁是否載入完畢(網頁Tab的小圈圈是否轉完),若秒數內沒載完就報錯。但因為要等待整個頁面載完才能執行下個動作。
顯式等待: 直接對要等待的元素前面聲明,所以通常會跟FindElement一起出現。
 

//傻傻地等
Thread.Sleep(10) //不管怎樣,等10秒就對了

//隱式等待,秒數內載完網頁所有元素,否則報錯。載完就提早進入下一步,故比Thread.Sleep更優
this.driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10); //10秒內載完網頁所有元素

//顯式等待,需要給定元素位置,只要該元素找到就進入下一步。
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementExists(by));

還有查到一些加速的方法,例如關掉圖片下載、關閉瀏覽器顯示等等,有興趣自己玩玩看吧(參8參9)
 

參考資料

  1. https://blog.poychang.net/note-selenium/
  2. https://en.wikipedia.org/wiki/Selenium_(software)
  3. https://www.itread01.com/content/1549266495.html
  4. https://ek21.com/news/tech/27426/
  5. https://kknews.cc/zh-tw/code/6akr49v.html
  6. https://chromedriver.chromium.org/downloads
  7. https://github.com/mozilla/geckodriver/releases
  8. www.twblogs.net/a/5d53092dbd9eee541c3173fc
  9. https://www.itdaan.com/tw/8cfbedf8cdf1e14d6419af20f401a63e