概述
Selenium是一款免费的分布式的自动化测试工具,支持多种开发语言,无论是C、 java、ruby、python、或是C# ,你都可以通过selenium完成自动化测试。本文以一个简单的小例子,简述C# 利用Selenium进行浏览器的模拟操作,仅供学习分享使用,如有不足之处,还请指正。
涉及知识点
要实现本例的功能,除了要掌握Html ,JavaScript,CSS等基础知识,还涉及以下知识点:
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
}
}
|
Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有