使用Selenium
1、创建一个c#控制台程序
2、使用Nuget搜索以下依赖库,需要引用的核心库是Selenium.RC,Selenium.Support,Selenium.WebDriver
![](https://i-blog.csdnimg.cn/blog_migrate/37422ebeb7f1f434f111b356c1cd4008.png)
然后再需要引用 浏览器驱动库,这里我以IE浏览器为例,Chrome使用方式跟IE是一样的,程序包名称为Selenium.WebDriver.ChromeDriver。
![](https://i-blog.csdnimg.cn/blog_migrate/729fb1bc0ee482c6fa7900e6310624ce.png)
3、在Main函数中输入以下代码
这里使用用了using(){},表示执行完{}里面的代码之后会自动释放括号内的代码资源。
(用于连接数据库的多,这样的话就可以不用写代码去关闭数据库连接了)
static void Main(string[] args)
{
using (IWebDriver driver = new OpenQA.Selenium.IE.InternetExplorerDriver())
{
driver.Navigate().GoToUrl("http://www.baidu.com"); //driver.Url = "http://www.baidu.com"是一样的
var source = driver.PageSource;
Console.WriteLine(source);
}
}
运行,会弹出IE浏览器,网页加载完成后,浏览器会自动关闭。控制台输入结果如下
![](https://i-blog.csdnimg.cn/blog_migrate/49109299bd328564ef1da6f2ee929c78.png)
这样我们就可以轻松的获取动态渲染页面的源码。
基本用法:
通过id获取元素
1 //by id
2 //<div id="cards"></div>
3 var byID = driver.FindElement(By.Id("cards"));
通过类名获取元素
1 //by class name
2 //<div class="menu"></div>
3 var byClassName = driver.FindElements(By.ClassName("menu"));
通过标签名获取元素
1 //by tag name
2 //<iframe></iframe>
3 var byTagName = driver.FindElement(By.TagName("iframe"));
通过名字(name属性)获取元素
1 //by name
2 //<div name="__VIEWSTATE"></DIV>
3 var byName = driver.FindElement(By.Name("__VIEWSTATE"));
通过链接文本获取元素
1 //by linked text
2 //<a href="http://www.google.com">linkedtext</a>>
3 var byLinkText = driver.FindElement(By.LinkText("linkedtext"));
通过部分链接文本获取元素
1 //是模糊查找。比如百度网页中的关于 参数写“关”就可以了,不用写*这种符号
2 //<a href="http://www.google.com">linkedtext</a>>
3 var byPartialLinkText = driver.FindElement(By.PartialLinkText("text"));
通过CSS选择器获取元素
通过CSS选择器获取元素
1 //by css
2 var byCss = driver.FindElement(By.CssSelector("#header .content .logo"));
通过XPath来获取元素
通过XPath来获取元素
1 //by xpath
2 var byXPath = driver.FindElements(By.XPath("//div"));
在浏览器上打开开发者工具,然后点击要查看xpath的元素
![](https://i-blog.csdnimg.cn/blog_migrate/1b1226017a507397bbaf2d7028fb7241.png)
点击后会自动定位到元素代码,选中右键 -->点击Copy,复制需要的相应内容,我这里用的谷歌,不同浏览器可能复制xpath的位置会不同
![](https://i-blog.csdnimg.cn/blog_migrate/b1981dbc7771227a27a9b5be34d0d911.png)
模拟鼠标点击元素
1 driver.FindElement(By.Id("copyright")).Click();
2 或者
3 IWebElement eles = driver.FindElement(By.LinkText("关于百度"));
4 Actions actionsObj = new Actions(driver);
5 actionsObj.Click(eles).Perform();
鼠标双击控件
1 IWebElement eles=driver.FindElement(By.Id("id"));
2 Actions actionsObj = new Actions(driver);
3 actionsObj.DoubleClick(eles).Perform();
鼠标单击拖动
下面的代码演示的是从第1个控件单击并拖动至第4个控件,并选中这4个控件,如下所示(点击长按 -->拖动 --> 松手 )
![](https://i-blog.csdnimg.cn/blog_migrate/f60078432dc9fe758c9a16a5c9fa6648.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c586102703ee6046a144234cf9216cab.png)
driver.Url = "http://www.jqueryui.org.cn/demo/5640.html";
Thread.Sleep(1000);
driver.Manage().Window.Maximize();
ReadOnlyCollection<IWebElement> items = driver.FindElements(By.XPath("//ol[@id='selectable']/li"));
Assert.AreEqual<int>(7, items.Count);
Actions actionsObj = new Actions(driver);
actionsObj.ClickAndHold(items[0]).ClickAndHold(items[4]).Release().Perform();
移动鼠标到指定控件
1 IWebElement eles=driver.FindElement(By.Id("id"));
2 Actions actionsObj = new Actions(driver);
3 actionsObj.MoveToElement(eles).Perform();
鼠标拖放
拖放操作因操作简单易懂,在Web页面中应用也越来越广,特别是一些银行页面中。以下代码演示如何通过Selenium API来完成操作
![](https://i-blog.csdnimg.cn/blog_migrate/3d5a58cf8891fb65feeefc275d2f2d68.png)
1、方法一:通过方法DragAndDrop()实现
driver.Url = "http://www.jqueryui.org.cn/demo/5622.html";
Thread.Sleep(1000);
driver.Manage().Window.Maximize();
IWebElement soureEle = driver.FindElement(By.Id("draggable"));
IWebElement targetEle = driver.FindElement(By.Id("droppable"));
Actions actionObj = new Actions(driver);
actionObj.DragAndDrop(soureEle, targetEle).Perform();
IWebElement textEle = driver.FindElement(By.XPath("//div[@id='droppable']/p"));
Assert.IsTrue(textEle.Text.Contains("Dropped!"));
2、方法二:通过方法MoveToElement()实现
driver.Url = "http://www.jqueryui.org.cn/demo/5622.html";
Thread.Sleep(1000);
driver.Manage().Window.Maximize();
IWebElement soureEle = driver.FindElement(By.Id("draggable"));
IWebElement targetEle = driver.FindElement(By.Id("droppable"));
Actions actionObj = new Actions(driver);
actionObj.ClickAndHold(soureEle).MoveToElement(targetEle).Release(targetEle).Perform();
IWebElement textEle = driver.FindElement(By.XPath("//div[@id='droppable']/p"));
Assert.IsTrue(textEle.Text.Contains("Dropped!"));
3、方法三:通过方法MoveByOffset()实现
driver.Url = "http://www.jqueryui.org.cn/demo/5622.html";
Thread.Sleep(1000);
driver.Manage().Window.Maximize();
IWebElement soureEle = driver.FindElement(By.Id("draggable"));
IWebElement targetEle = driver.FindElement(By.Id("droppable"));
Actions actionObj = new Actions(driver);
actionObj.ClickAndHold(soureEle).MoveByOffset(100, 0).Perform();
IWebElement textEle = driver.FindElement(By.XPath("//div[@id='droppable']/p"));
Assert.IsTrue(textEle.Text.Contains("Dropped!"));
拖动进度条或滑块
driver.Url = "http://demo.lanrenzhijia.com/2015/drag1218/";
Thread.Sleep(1000);
driver.Manage().Window.Maximize();
IWebElement origianlValueEle = driver.FindElement(By.Id("title"));
Assert.AreEqual("0", origianlValueEle.Text);
IWebElement sliderEle = driver.FindElement(By.Id("btn"));
Actions actionsObj = new Actions(driver);
actionsObj.DragAndDropToOffset(sliderEle, 100, 0).Perform();
Assert.AreEqual("51%", origianlValueEle.Text);
单击鼠标右键菜单
这种情况Selenium API提供一种方法ContextClick()方法
driver.Url = "http://www.helloweba.com/demo/2017/basicContext/";
Thread.Sleep(1000);
driver.Manage().Window.Maximize();
IWebElement btnEle = driver.FindElement(By.XPath("//button[contains(@class,'btn-success context')]"));
Actions actionsObj = new Actions(driver);
actionsObj.ContextClick(btnEle).Perform();//点击右键菜单
IWebElement rightMenu = driver.FindElement(By.XPath("//div[@class='basicContext']/table/tbody/tr[2]"));
rightMenu.Click();//选择菜单
IAlert alert = driver.SwitchTo().Alert();
string alertText = alert.Text;
alert.Accept();
Assert.AreEqual<string>("Item clicked!",alertText);
弹框处理
类似下图所示的警告框,无法通过前端工具定位,需要跳转到弹框,然后再对其操作
![](https://i-blog.csdnimg.cn/blog_migrate/1382746e1ea69c4da7dd73ad6e4f0175.png)
3种弹框:
警告类弹框,Alert():一个按钮
确认类弹框,Confirmation:一个确认,一个取消
消息类弹框,Prompt:一个输入框, 一个确认,一个取消
跳转到弹框:
SwitchTo().Alert()
常用的弹框处理方法:
Text 获取警告框的内容
Accept() 相当于点击确认按钮
Dismiss() 相当于点击取消按钮
SendKeys() 向警告框输入值
1 IAlert alert = driver.SwitchTo().Alert();//获取警告框
2 string alertText = alert.Text;//获取警告框中的内容
3 alert .Accept();//接受(确认)
执行JS
1 //execute javascript
2 var jsReturnValue = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("jsfunname");
当点击的元素包含href跳转的时候可以使用JavaScript来进行点击操作
(IJavaScriptExecutor)driver.ExecuteScript("arguments[0].click();",
driver.FindElement(By.XPath("/html/body/div[2]/div/div[2]/div[2]/div[1]/h3/a")));
获取元素的值和属性
3 var byIDText = byID.Text;
4 var byIDAttributeText = byID.GetAttribute("id");
页面导航
//Navigation()方法 摘要:指示驱动程序将将来的命令发送到不同的框架或窗口。说明:就是对对象进行进一些基本操作,比如刷新,打开,回退,向前
driver.Navigate().Forward(); //向前
driver.Navigate().Back(); //返回4 driver.Navigate().Refrsh();//刷新当前打开的页面5 driver.Close();//关闭当前选中的浏览器窗口,如果是最后一个窗口就退出浏览器6 driver.Quit();//退出,关闭测试其对象,也会退出所有关联的窗口 7 driver.Manage().Window.Maximize();//浏览器最大化 8 .GoToUrl(Uri url)和 GoToUrl(string Url) //打开链接,在Navigate()方法后调用,将对象定位到指定的URL中去。如果是第一次调用,新打开一个浏览器窗体。和Open()方法一样
模拟键盘 SendKeys.SendWait()用法
1 SendKeys.SendWait("{F5}"); //发送F5按键
2 SendKeys.SendWait("^s"); //发送 Ctrl + s 键
3 SendKeys.SendWait("%{F4}"); // 发送 Alt + F4 键
4
5 //按键 代码
6 //BACKSPACE {BACKSPACE}, {BS}, 或 {BKSP}
7 //BREAK {BREAK}
8 //CAPS LOCK {CAPSLOCK}
9 //DEL or DELETE {DELETE} 或 {DEL}
10 // DOWN ARROW {DOWN}
11 //END {END}
12 //ENTER {ENTER}或 ~
13 //ESC {ESC}
14 //HELP {HELP}
15 //HOME {HOME}
16 //INS or INSERT {INSERT} 或 {INS}
17 //LEFT ARROW {LEFT}
18 //NUM LOCK {NUMLOCK}
19 //PAGE DOWN {PGDN}
20 //PAGE UP {PGUP}
21 //PRINT SCREEN {PRTSC}
22 //RIGHT ARROW {RIGHT}
23
24 //为了指定重复键,使用 {key number} 的形式。必须在 key 与 number 之间放置一个空格。例如,{LEFT 42} 意指 42 次按下
25 //LEFT ARROW 键;{h 10} 则是指 10 次按下 H 键。
//为弹出windows文件选择框写入地址 Thread.Sleep(1000); SendKeys.SendWait(@path);//path是传入的路径 Thread.Sleep(1000); SendKeys.SendWait(@"{Enter}");
获取table中tr的数据
1 var ssoTr = driver.FindElement(By.XPath("/html/body/div[2]/div/div[2]/div[2]/div[3]/div[1]/table/tbody")).FindElements(By.TagName("tr"));
2 var toDayTr = ssoTr.Where(x => x.Text.Contains(DateTime.Now.ToString("yyyy-MM-dd"))).ToList();
iFrame的切换
//如果要取的元素显示报错找不到,其中一个原因可能是被iframe标签包裹住了,这个时候就要切换到iframe中,然后再取元素。
//注意,切换到iframe中就不可以继续操作主文档中的元素,如果要操作主文档的元素就需要切回到主文档
var iframe = driver.FindElement(By.Id("login-iframe-2019"));//找到ifram元素
driver.SwitchTo().Frame(iframe);//切换到ifram
driver.switch_to.default_content();//切回主文档
嵌套的iFrame操作
1 <html>
2 <iframe id="frame1">
3 <iframe id="frame2" / >
4 </iframe>
5 </html>
//从主文档切到frame2,一层层切进去
driver.SwitchTo().Frame("rame1)
driver.SwitchTo().Frame("rame2)
//从frame2再切回frame1,这里selenium给我们提供了一个方法能够从子frame切回到父frame,而不用我们切回主文档再切进来。
driver.SwitchTo().ParentFrame() // 如果当前已是主文档,则无效果
//补充:之前曾看到过用点分法来切入嵌套frame的方法,但我没有试过不知道额能否成功
//切到 “frame1” 下的 “第一个frame” 下的 “frame3” 中。
driver.SwitchTo().Frame("frame1.0.frame1");
鼠标滚动
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("window.scrollTo(0,100)");//滚动鼠标位置到100
js.ExecuteScript("window.scrollTo(0,0)");//滚动鼠标至顶部
js.ExecuteScript("window.scrollTo(0,document.body.scrollHeight)'");//滚动鼠标至底部-这个我用报错了,暂时还没研究是啥问题 知道的小伙伴可以留言告诉我~
避免登录时总是需要手机号验证
Selenium启动浏览器时,默认是打开一个新用户,不会加载原有的配置以及插件,所以每次都需要登录,有的可能识别出时自动而是软件还会需要手机号验证码。
两种解决办法(我这里以谷歌浏览器为例):
1、加载浏览器配置文件(我试了这个方法没有效果,有尝试成功过的欢迎分享~)
①打开谷歌浏览器,输入chrome://version/,得到个人资料路径地址
![](https://i-blog.csdnimg.cn/blog_migrate/4b8d7d315f1b09ef22d35fd22d36264e.png)
②这里打开阿里云,但是打开之后还是需要输入账号密码登录,没有加载浏览器配置文件,百度到有人说登录进入之后就不需要再次登录了,但是我试过没有效果(执行脚本时需要关掉谷歌浏览器,不然可能会报错)
1 var option = new ChromeOptions();
2 option.AddArgument(@"个人资料路径地址,地址截取到User Data 即可,路径后面的Default不需要,不然还是打开一个新用户");
3 driver = new ChromeDriver(option);
4 driver.Url = "https://account.aliyun.com/login/login.htm?spm=5176.19720258.J_8058803260.35.e9392c4aykXZ6w&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F";
还有一种方式,打开时指定chrome驱动
①右键谷歌 ---》 属性,复制起始位置中的地址
![](https://i-blog.csdnimg.cn/blog_migrate/a5043096fe7553bff0c3aa73f870c31c.png)
②配置本地谷歌环境变量;
此电脑 --》 右键属性 --》点击高级系统设置 --》环境变量 --》选中Path,点击编辑 --》点击新建,将刚刚复制的路径粘贴上去一路点击确认下来即可
最后打开刚刚复制的路径,将下载的谷歌驱动 chromedriver.exe粘贴
![](https://i-blog.csdnimg.cn/blog_migrate/9404517e38e0a21f3305f6be77d40f25.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2f41ddfd63613e23018e057f4d8fb0a8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/91a560d311b42d95890049a45a2eec69.png)
var option = new ChromeOptions();
option.AddArgument(@"个人资料路径地址,地址截取到User Data 即可,路径后面的Default不需要,不然还是打开一个新用户");
driver = new ChromeDriver(@"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe", option);
![](https://i-blog.csdnimg.cn/blog_migrate/68266b6cbe81d04542104a4cc450bd3b.png)
②
这里我一直报C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe路径不存在,但是这个是有的
var option = new ChromeOptions();
option.AddArgument(@"个人资料路径地址,地址截取到User Data 即可,路径后面的Default不需要,不然还是打开一个新用户");
driver = new ChromeDriver(@"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe", option);
driver.Url = "https://account.aliyun.com/login/login.htm?spm=5176.19720258.J_8058803260.35.e9392c4aykXZ6w&oauth_callback=https%3A%2F%2Fwww.aliyun.com%2F";
2、使用Debug方式启动浏览器,使用Selenium连接到一个已打开的浏览器
chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\AutomationProfile
// chrome:表示启动chrome浏览器
// remote-debugging-port:表示执行浏览器端口
// 9222为个人设置的端口
// --user-data-dir="C:\selenum\AutomationProfile":表示新建一个浏览器配置信息,地址自己定义
//先打开一个网页或者直接win+r打开cmd,输入命令行chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenum\AutomationProfile",端口号可以自己定义;
Process proc = new Process();
proc.StartInfo.FileName = @"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe";
proc.StartInfo.Arguments = "https://vod.console.aliyun.com/?spm=5176.12818093.ProductAndService--ali--widget-home-product-recent.dre0.419916d0LZyB0A#/media/video/list --new-window --remote-debugging-port=9222 --user-data-dir=E:\\selenum"; proc.Start();
//将selenium连接到已经打开的浏览器,创建WebDriver并将浏览器的连接地址和端口作为参数传递给WebDriver
ChromeOptions options = new ChromeOptions();
options.DebuggerAddress = "127.0.0.1:9222";
driver = new ChromeDriver(options);