C#利⽤Selenium实现浏览器⾃动化操作
概述
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 ChromeOptions options = new ChromeOptions();
3this.driver = new ChromeDriver(options);
通过ID获取元素并填充内容和触发事件,如下所⽰:
1this.driver.FindElement(By.Id("email")).SendKeys(username);
2this.driver.FindElement(By.Id("password")).SendKeys(password);
3//# 7. 点击登录按钮
4this.driver.FindElement(By.Id("sign-in")).Click();
通过XPath获取元素,如下所⽰:
1string xpath1 = "//div[@class=\"product-list\"]/div[@class=\"product\"]/div[@class=\"price-and-detail\
"]/div[@class=\"price\"]/span[@class=\"noStock\"]"; 2string txt = this.driver.FindElement(By.XPath(xpath1)).Text;
核⼼代码
主要的核⼼代码,就是浏览器的元素定位查和事件触发,如下所⽰:
1using OpenQA.Selenium;
2using OpenQA.Selenium.IE;
3using OpenQA.Selenium.Chrome;
4using System;
5using System.Collections.Generic;
6using System.Linq;
7using System.Text;
8using System.Threading;
9using System.Threading.Tasks;
10
11namespace AiSmoking.Core
12 {
13public class Smoking
14 {
15///<summary>
16///是否正在运⾏
17///</summary>
18private bool running = false;
19
20///<summary>
21///驱动
22///</summary>
23private IWebDriver driver = null;
24
25
26///<summary>
27/// # ⽆货
28///</summary>
29private string no_stock = "Currently Out of Stock";
30
31
32///<summary>
33/// # 线程等待秒数
34///</summary>
35private int wait_sec = 2;
36
37private Dictionary<string, string> cfg_info;
38
39private string work_path = string.Empty;
40
41///<summary>
42///构造函数
43///</summary>
44public Smoking()
45 {
46
47 }
48
qq空间非主流49///<summary>
50///带参构造函数
51///</summary>
52///<param name="cfg_info"></param>
53///<param name="work_path"></param>
54public Smoking(Dictionary<string, string> cfg_info,string work_path)
55 {
56this.cfg_info = cfg_info;
57this.work_path = work_path;
58this.wait_sec = int.Parse(cfg_info["wait_sec"]);
59//# 如果⼩于2,则等于2
60this.wait_sec = (this.wait_sec < 2 ? 2 : this.wait_sec);
61this.wait_sec = this.wait_sec * 1000;
62 }
63
64///<summary>
65///开始跑
66///</summary>
67public void startRun()
68 {
69//"""运⾏起来"""
70try
71 {
72this.running = true;
73string url = this.cfg_info["url"];
74string username = this.cfg_info["username"];
75string password = this.cfg_info["password"];
76string item_id = this.cfg_info["item_id"];
77if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(item_id))
78 {
79 LogHelper.put("配置信息不全,请检查config.cfg⽂件是否为空,然后再重启");
80return;
81 }
82if (this.driver == null)
83 {
84string explorer = this.cfg_info["explorer"];
85if (explorer == "Chrome")
86 {
87//⾕歌浏览器
88 ChromeOptions options = new ChromeOptions();
89this.driver = new ChromeDriver(options);
90 }
91else
92 {
93//默认IE
94var options = new InternetExplorerOptions();
95//options.AddAdditionalCapability.('encoding=UTF-8')
96//options.add_argument('Accept= text / css, * / *')
97//options.add_argument('Accept - Language= zh - Hans - CN, zh - Hans;q = 0.5')
98//options.add_argument('Accept - Encoding= gzip, deflate')
99//options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko')
100//# 2. 定义浏览器驱动对象
101this.driver = new InternetExplorerDriver(options);
102 }
103 }
104this.run(url, username, password, item_id);
105 }
106catch (Exception e)
107 {
108 LogHelper.put("运⾏过程中出错,请重新打开再试"+e.StackTrace);
109 }
110 }
111
112
113///<summary>
114///运⾏
115///</summary>
116///<param name="url"></param>
117///<param name="username"></param>
沈阳 旅行社
118///<param name="password"></param>
119///<param name="item_id"></param>
120private void run(string url, string username, string password, string item_id)
121 {
122//"""运⾏起来"""
123//# 3. 访问⽹站
124this.driver.Navigate().GoToUrl(url);
125//# 4. 最⼤化窗⼝
126this.driver.Manage().Window.Maximize();
127if (this.checkIsExists(By.LinkText("账户登录")))
128 {
师范院校
129//# 判断是否登录:未登录
130this.login(username, password);
131 }
132if (this.checkIsExists(By.PartialLinkText("欢迎回来")))
133 {
134//# 判断是否登录:已登录
135 LogHelper.put("登录成功,下⼀步开始⼯作了");
136this.working(item_id);
137 }
138else
139 {
140 LogHelper.put("登录失败,请设置账号密码");
141 }
142 }
143
144///<summary>
145///停⽌运⾏
146///</summary>
147public void stopRun()
148 {
149//"""停⽌"""
150try
151 {
152this.running = false;
153//# 如果驱动不为空,则关闭
154//self.close_browser_nicely(self.__driver)
155if (this.driver != null)
156 {
157this.driver.Quit();
158//# 关闭后切要为None,否则启动报错
159this.driver = null;
160 }
161 }
162catch (Exception e)
163 {
164//print('Stop Failure')
165 }
166finally
167 {
168this.driver = null;
169 }
170 }
171
172
173private void login(string username, string password)
174 {
175//# 5. 点击链接跳转到登录页⾯
176this.driver.FindElement(By.LinkText("账户登录")).Click();
177//# 6. 输⼊账号密码
178//# 判断是否加载完成
179if (this.checkIsExists(By.Id("email")))
180 {
181this.driver.FindElement(By.Id("email")).SendKeys(username);
182this.driver.FindElement(By.Id("password")).SendKeys(password);
183//# 7. 点击登录按钮
184this.driver.FindElement(By.Id("sign-in")).Click();
185 }
186 }
187
188///<summary>
189///⼯作状态
190///</summary>
191///<param name="item_id"></param>
192private void working(string item_id)
193 {
194while (this.running)
195 {
196try
197 {
198//# 正常获取信息
199if (this.checkIsExists(By.Id("string")))
200 {
201this.driver.FindElement(By.Id("string")).Clear();
202this.driver.FindElement(By.Id("string")).SendKeys(item_id);
203this.driver.FindElement(By.Id("string")).SendKeys(Keys.Enter);
204 }
205//# 判断是否查询到商品
206string xpath = "//div[@class=\"specialty-header search\"]/div[@class=\"specialty-description\"]/div[@class=\"gt-450\"]/span[2] ";
207if (this.checkIsExists(By.XPath(xpath)))
208 {
209int count = int.Parse(this.driver.FindElement(By.XPath(xpath)).Text);
210if (count < 1)
211 {
212 Thread.Sleep(this.wait_sec);
213 LogHelper.put("没有查询到item id =" + item_id + "对应的信息");
214continue;
215 }
216 }
217else
218 {
219 Thread.Sleep(this.wait_sec);
220 LogHelper.put("没有查询到item id2 =" + item_id + "对应的信息");
221continue;
222 }
223//# 判断当前库存是否有货
224
225string xpath1 = "//div[@class=\"product-list\"]/div[@class=\"product\"]/div[@class=\"price-and-detail\"]/div[@class=\"price\"]/span[@class=\"noStock\"]"; 226if (this.checkIsExists(By.XPath(xpath1)))
227 {
228string txt = this.driver.FindElement(By.XPath(xpath1)).Text;
229if (txt == _stock)
230 {
231//# 当前⽆货
232 Thread.Sleep(this.wait_sec);
233 LogHelper.put("查询⼀次" + item_id + ",⽆货");
234continue;
235 }
236 }
237//# 链接path1
238string xpath2 = "//div[@class=\"product-list\"]/div[@class=\"product\"]/div[@class=\"imgDiv\"]/a"; 239//# 判断是否加载完毕
240//# this.waiting((By.CLASS_NAME, "imgDiv"))
241if (this.checkIsExists(By.XPath(xpath2)))
242 {
243this.driver.FindElement(By.XPath(xpath2)).Click();
244 Thread.Sleep(this.wait_sec);
245//# 加⼊购物车
246if (this.checkIsExists(By.ClassName("add-to-cart")))
247 {
248this.driver.FindElement(By.ClassName("add-to-cart")).Click();
249 LogHelper.put("加⼊购物车成功,商品item-id:" + item_id);
250break;
251 }
252else
253 {
254 LogHelper.put("未到加⼊购物车按钮");
255 }
256 }
257else
258 {
259 LogHelper.put("没有查询到,可能是商品编码不对,或者已下架");
260 }
261 Thread.Sleep(this.wait_sec);
262 }
什么音响好263catch (Exception e)
264 {
265 Thread.Sleep(this.wait_sec);
266 LogHelper.put(e);
267 }
268 }
269 }
270
271///<summary>
272///判断是否存在
273///</summary>
274///<param name="by"></param>
275///<returns></returns>
276private bool checkIsExists(By by)
277 {
278try
279 {华为双系统怎么切换
280int i = 0;
281while (this.running && i < 3)
282 {
283if (this.driver.FindElements(by).Count > 0)
我国有几个直辖市
284 {
285break;
286 }
287else
288 {
289 Thread.Sleep(this.wait_sec);
290 i = i + 1;
291 }
292 }
293return this.driver.FindElements(by).Count > 0;
294 }
295catch (Exception e)
296 {
297 LogHelper.put(e);
298return false;
299 }
300 }
301
302 }
303 }
View Code
关于⽇志帮助类,代码如下:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6using log4net;
7
8 [assembly: log4net.Config.XmlConfigurator(Watch = true)]
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论