C#利用Selenium实现浏览器自动化操作
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小时内删除。