专业网站建设品牌,十四年专业建站经验,服务6000+客户--广州京杭网络
免费热线:400-963-0016      微信咨询  |  联系我们

C# 利用Selenium实现浏览器自动化操作的示例代码

当前位置:网站建设 > 技术支持
资料来源:网络整理       时间:2023/2/14 0:40:54       共计:3648 浏览

概述

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,如下所示:

1 2 3 //谷歌浏览器  ChromeOptions options = new ChromeOptions();  this.driver = new ChromeDriver(options);

通过ID获取元素并填充内容和触发事件,如下所示:

1 2 3 4 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获取元素,如下所示:

1 2 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;

核心代码

主要的核心代码,就是浏览器的元素定位查找和事件触发,如下所示:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 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;       }     }     } }

关于日志帮助类,代码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 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   } }

版权说明:
本网站凡注明“广州京杭 原创”的皆为本站原创文章,如需转载请注明出处!
本网转载皆注明出处,遵循行业规范,如发现作品内容版权或其它问题的,请与我们联系处理!
欢迎扫描右侧微信二维码与我们联系。
·上一条:selenium入门教程c# | ·下一条:C#编程之C#项目中使用 Selenium + PhantomJS 模拟登录

Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有    粤ICP备16019765号 

广州京杭网络科技有限公司 版权所有