C# 利用Selenium實現瀏覽器自動化操作的示例程式碼
阿新 • • 發佈:2020-09-12
概述
Selenium是一款免費的分散式的自動化測試工具,支援多種開發語言,無論是C、 java、ruby、python、或是C# ,你都可以通過selenium完成自動化測試。本文以一個簡單的小例子,簡述C# 利用Selenium進行瀏覽器的模擬操作,僅供學習分享使用,如有不足之處,還請指正。
涉及知識點
要實現本例的功能,除了要掌握Html ,JavaScript,CSS等基礎知識,還涉及以下知識點:
- log4net:主要用於日誌的記錄和儲存,本例採用log4net進行日誌記錄,便於過程跟蹤和問題排查,關於log4net的配置和介紹,之前已有說明,本文不做贅述。
- Queue:佇列,先進先出模式,本文主要用於將日誌資訊保存於佇列中,然後再顯示到頁面上,其中Enqueue用於新增內容到結尾處,Dequeue用於返回並移除一個位置的物件。
- IWebDriver:瀏覽器驅動介面,所有的關於瀏覽器的操作都可以通過此介面進行,不同瀏覽器有不同的實現類,如:IE瀏覽器(InternetExplorerDriver)Chrome瀏覽器(ChromeDriver)等。
- BackgroundWorker:後臺工作執行緒,區別於主執行緒,通過事件觸發不同的狀態。
Selenium安裝
本例開發工具為VS2019,通過NuGet進行需要的軟體包的安裝與管理,如下所示:
示例效果圖
本例採用Chrome瀏覽器,用於監控某一個網站並獲取相應內容,如下所示:
Selenium示例介紹
定義一個webDriver,如下所示:
//谷歌瀏覽器 ChromeOptions options = new ChromeOptions(); this.driver = new ChromeDriver(options);
通過ID獲取元素並填充內容和觸發事件,如下所示:
this.driver.FindElement(By.Id("email")).SendKeys(username); this.driver.FindElement(By.Id("password")).SendKeys(password); //# 7. 點選登入按鈕 this.driver.FindElement(By.Id("sign-in")).Click();
通過XPath獲取元素,如下所示:
string xpath1 = "//div[@class=\"product-list\"]/div[@class=\"product\"]/div[@class=\"price-and-detail\"]/div[@class=\"price\"]/span[@class=\"noStock\"]"; string txt = this.driver.FindElement(By.XPath(xpath1)).Text;
核心程式碼
主要的核心程式碼,就是瀏覽器的元素定位查詢和事件觸發,如下所示:
using OpenQA.Selenium; using OpenQA.Selenium.IE; using OpenQA.Selenium.Chrome; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace AiSmoking.Core { public class Smoking { /// <summary> /// 是否正在執行 /// </summary> private bool running = false; /// <summary> /// 驅動 /// </summary> private IWebDriver driver = null; /// <summary> /// # 無貨 /// </summary> private string no_stock = "Currently Out of Stock"; /// <summary> /// # 執行緒等待秒數 /// </summary> private int wait_sec = 2; private Dictionary<string,string> cfg_info; private string work_path = string.Empty; /// <summary> /// 建構函式 /// </summary> public Smoking() { } /// <summary> /// 帶參建構函式 /// </summary> /// <param name="cfg_info"></param> /// <param name="work_path"></param> public Smoking(Dictionary<string,string> cfg_info,string work_path) { this.cfg_info = cfg_info; this.work_path = work_path; this.wait_sec = int.Parse(cfg_info["wait_sec"]); //# 如果小於2,則等於2 this.wait_sec = (this.wait_sec < 2 ? 2 : this.wait_sec); this.wait_sec = this.wait_sec * 1000; } /// <summary> /// 開始跑 /// </summary> public void startRun() { //"""執行起來""" try { this.running = true; string url = this.cfg_info["url"]; string username = this.cfg_info["username"]; string password = this.cfg_info["password"]; string item_id = this.cfg_info["item_id"]; if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(item_id)) { LogHelper.put("配置資訊不全,請檢查config.cfg檔案是否為空,然後再重啟"); return; } if (this.driver == null) { string explorer = this.cfg_info["explorer"]; if (explorer == "Chrome") { //谷歌瀏覽器 ChromeOptions options = new ChromeOptions(); this.driver = new ChromeDriver(options); } else { //預設IE var options = new InternetExplorerOptions(); //options.AddAdditionalCapability.('encoding=UTF-8') //options.add_argument('Accept= text / css,* / *') //options.add_argument('Accept - Language= zh - Hans - CN,zh - Hans;q = 0.5') //options.add_argument('Accept - Encoding= gzip,deflate') //options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko') //# 2. 定義瀏覽器驅動物件 this.driver = new InternetExplorerDriver(options); } } this.run(url,username,password,item_id); } catch (Exception e) { LogHelper.put("執行過程中出錯,請重新開啟再試"+e.StackTrace); } } /// <summary> /// 執行 /// </summary> /// <param name="url"></param> /// <param name="username"></param> /// <param name="password"></param> /// <param name="item_id"></param> private void run(string url,string username,string password,string item_id) { //"""執行起來""" //# 3. 訪問網站 this.driver.Navigate().GoToUrl(url); //# 4. 最大化視窗 this.driver.Manage().Window.Maximize(); if (this.checkIsExists(By.LinkText("賬戶登入"))) { //# 判斷是否登入:未登入 this.login(username,password); } if (this.checkIsExists(By.PartialLinkText("歡迎回來"))) { //# 判斷是否登入:已登入 LogHelper.put("登入成功,下一步開始工作了"); this.working(item_id); } else { LogHelper.put("登入失敗,請設定賬號密碼"); } } /// <summary> /// 停止執行 /// </summary> public void stopRun() { //"""停止""" try { this.running = false; //# 如果驅動不為空,則關閉 //self.close_browser_nicely(self.__driver) if (this.driver != null) { this.driver.Quit(); //# 關閉後切要為None,否則啟動報錯 this.driver = null; } } catch (Exception e) { //print('Stop Failure') } finally { this.driver = null; } } private void login(string username,string password) { //# 5. 點選連結跳轉到登入頁面 this.driver.FindElement(By.LinkText("賬戶登入")).Click(); //# 6. 輸入賬號密碼 //# 判斷是否載入完成 if (this.checkIsExists(By.Id("email"))) { this.driver.FindElement(By.Id("email")).SendKeys(username); this.driver.FindElement(By.Id("password")).SendKeys(password); //# 7. 點選登入按鈕 this.driver.FindElement(By.Id("sign-in")).Click(); } } /// <summary> /// 工作狀態 /// </summary> /// <param name="item_id"></param> private void working(string item_id) { while (this.running) { try { //# 正常獲取資訊 if (this.checkIsExists(By.Id("string"))) { this.driver.FindElement(By.Id("string")).Clear(); this.driver.FindElement(By.Id("string")).SendKeys(item_id); this.driver.FindElement(By.Id("string")).SendKeys(Keys.Enter); } //# 判斷是否查詢到商品 string xpath = "//div[@class=\"specialty-header search\"]/div[@class=\"specialty-description\"]/div[@class=\"gt-450\"]/span[2] "; if (this.checkIsExists(By.XPath(xpath))) { int count = int.Parse(this.driver.FindElement(By.XPath(xpath)).Text); if (count < 1) { Thread.Sleep(this.wait_sec); LogHelper.put("沒有查詢到item id =" + item_id + "對應的資訊"); continue; } } else { Thread.Sleep(this.wait_sec); LogHelper.put("沒有查詢到item id2 =" + item_id + "對應的資訊"); continue; } //# 判斷當前庫存是否有貨 string xpath1 = "//div[@class=\"product-list\"]/div[@class=\"product\"]/div[@class=\"price-and-detail\"]/div[@class=\"price\"]/span[@class=\"noStock\"]"; if (this.checkIsExists(By.XPath(xpath1))) { string txt = this.driver.FindElement(By.XPath(xpath1)).Text; if (txt == this.no_stock) { //# 當前無貨 Thread.Sleep(this.wait_sec); LogHelper.put("查詢一次" + item_id + ",無貨"); continue; } } //# 連結path1 string xpath2 = "//div[@class=\"product-list\"]/div[@class=\"product\"]/div[@class=\"imgDiv\"]/a"; //# 判斷是否載入完畢 //# this.waiting((By.CLASS_NAME,"imgDiv")) if (this.checkIsExists(By.XPath(xpath2))) { this.driver.FindElement(By.XPath(xpath2)).Click(); Thread.Sleep(this.wait_sec); //# 加入購物車 if (this.checkIsExists(By.ClassName("add-to-cart"))) { this.driver.FindElement(By.ClassName("add-to-cart")).Click(); LogHelper.put("加入購物車成功,商品item-id:" + item_id); break; } else { LogHelper.put("未找到加入購物車按鈕"); } } else { LogHelper.put("沒有查詢到,可能是商品編碼不對,或者已下架"); } Thread.Sleep(this.wait_sec); } catch (Exception e) { Thread.Sleep(this.wait_sec); LogHelper.put(e); } } } /// <summary> /// 判斷是否存在 /// </summary> /// <param name="by"></param> /// <returns></returns> private bool checkIsExists(By by) { try { int i = 0; while (this.running && i < 3) { if (this.driver.FindElements(by).Count > 0) { break; } else { Thread.Sleep(this.wait_sec); i = i + 1; } } return this.driver.FindElements(by).Count > 0; } catch (Exception e) { LogHelper.put(e); return false; } } } }
關於日誌幫助類,程式碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using log4net; [assembly: log4net.Config.XmlConfigurator(Watch = true)] namespace AiSmoking.Core { /// <summary> /// 日誌幫助類 /// </summary> public static class LogHelper { /// <summary> /// 日誌例項 /// </summary> private static ILog logInstance = LogManager.GetLogger("smoking"); private static Queue<string> queue = new Queue<string>(2000); public static void put(string msg) { queue.Enqueue(msg); WriteLog(msg,LogLevel.Info); } public static void put(Exception ex) { WriteLog(ex.StackTrace,LogLevel.Error); } public static string get() { if (queue.Count > 0) { return queue.Dequeue(); } else { return string.Empty; } } public static void WriteLog(string message,LogLevel level) { switch (level) { case LogLevel.Debug: logInstance.Debug(message); break; case LogLevel.Error: logInstance.Error(message); break; case LogLevel.Fatal: logInstance.Fatal(message); break; case LogLevel.Info: logInstance.Info(message); break; case LogLevel.Warn: logInstance.Warn(message); break; default: logInstance.Info(message); break; } } } public enum LogLevel { Debug = 0,Error = 1,Fatal = 2,Info = 3,Warn = 4 } }
作者:Alan.hsiang
出處:http://www.cnblogs.com/hsiang/
以上就是C# 利用Selenium實現瀏覽器自動化操作的示例程式碼的詳細內容,更多關於c# 實現瀏覽器自動化操作的資料請關注我們其它相關文章!