C#使用selenium實(shí)現(xiàn)爬蟲
一、介紹:
Selenium 是一個(gè)用于Web應(yīng)用程序測試的工具。Selenium測試直接運(yùn)行在瀏覽器中,就像真正的用戶在操作一樣。
1、Selenium Webdriver(也就是Selenium2,Selenium3)和Selenium RC(Selenium 1)一樣提供了web自動(dòng)化的各種語言調(diào)用接口庫。相比Selenium RC,Selenium WebDriver的編程接口更加直觀易懂,也更加簡練。
但是和Selenium RC不同的是,Selenium Webdriver是通過各種瀏覽器的驅(qū)動(dòng)(web driver)來驅(qū)動(dòng)瀏覽器的,而不是通過注入JavaScript的方式。
我們的代碼運(yùn)行起來是一個(gè)進(jìn)程,里面調(diào)用Selenium WebDriver的庫和各個(gè)瀏覽器的驅(qū)動(dòng)進(jìn)程 進(jìn)行交互,傳遞Selenium命令 給它們,并且獲取命令執(zhí)行的結(jié)果,返回給我們的代碼進(jìn)行處理。
2、Selenium WebDriver目前包括兩個(gè)版本Selenium 2和Selenium 3。這兩個(gè)版本從開發(fā)代碼調(diào)用接口上來看,幾乎沒什么區(qū)別。區(qū)別在于庫的實(shí)現(xiàn)和web driver的實(shí)現(xiàn)。
Selenium2是Selenium組織幫各種瀏覽器寫web driver的,而Selenium 3里面的web driver是由各個(gè)瀏覽器廠商(Apple,Google,Microsoft,Mozilla)自己提供的。所以Selenium 3的自動(dòng)化效率更高,成功率也更高。
3、Selenium WebDriver 支持瀏覽器眾多:
- Google Chrome
- Microsoft Internet Explorer 7,8,9,10,11在 Windows Vista,Windows 7,Windows 8,Windows 8.1.
- Microsoft Edge
- Firefox
- Safari
- Opera
利用它可以驅(qū)動(dòng)瀏覽器執(zhí)行特定的動(dòng)作,如點(diǎn)擊、下拉等操作,同時(shí)還可以獲取瀏覽器當(dāng)前呈現(xiàn)的頁面的源代碼 ,做到可見即可爬。
所以Selenium現(xiàn)在被廣泛用于Python爬蟲。查了下資料,發(fā)現(xiàn)這個(gè)工具確實(shí)強(qiáng)大,最重要的是,C#也是可以調(diào)用的。
官方支持Java,C#,Python,Ruby,PHP,Perl,Javascript等語言
官方文檔(有C#示例):https://www.selenium.dev/documentation/en/
安裝Selenium:
1、我們新建一個(gè)C#控制臺(tái)程序
2、使用Nuget搜索以下依賴庫
需要引用的核心庫是Selenium.RC,Selenium.Support,Selenium.WebDriver
然后再需要引用瀏覽器驅(qū)動(dòng)庫,這里我以新版Edge瀏覽器為例,新版Edge使用方式跟Chrome是一樣的,程序包名稱為Selenium.WebDriver.MSEdgeDriver。

備注:也可以在微軟WebDriver官網(wǎng)下載Edge (Chromium)的webdriver,需要和當(dāng)前瀏覽器版本一致。然后下載放置到項(xiàng)目可執(zhí)行文件的目錄。
如果使用Chrome:
先查下本機(jī)Chrome的版本

然后去Nuget搜索Selenium.WebDriver.ChromeDriver進(jìn)行下載安裝。
注意:webdriver版本只需要和當(dāng)前瀏覽器主版本一致即可。

3、在Main函數(shù)中輸入以下代碼
using OpenQA.Selenium;
using OpenQA.Selenium.Edge;
using System;
using System.Windows.Forms;
namespace WinForm2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
using (IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service))
{
driver.Navigate().GoToUrl("http://www.baidu.com"); //driver.Url = "http://www.baidu.com"是一樣的
var source = driver.PageSource;
this.textBox1.Text = source;
}
}
}
}如果是Chrome瀏覽器,可以這樣:
IWebDriver driver = new OpenQA.Selenium.Chrome.ChromeDriver();
driver.Navigate().GoToUrl("http://www.baidu.com");運(yùn)行,會(huì)彈出IE瀏覽器,網(wǎng)頁加載完成后,瀏覽器會(huì)自動(dòng)關(guān)閉。控制臺(tái)輸入結(jié)果如下

這樣我們就可以輕松的獲取動(dòng)態(tài)渲染頁面的源碼。
二、等待
常用的等待分為顯示等待WebDriverWait()、隱式等待ImplicitlyWait()、強(qiáng)制等待sleep()三種,下面我們就分別介紹一下這三種等待的區(qū)別
- Sleep(): 強(qiáng)制等待,設(shè)置固定休眠時(shí)間。
- ImplicitlyWait():隱式等待,也叫智能等待,是 webdirver 提供的一個(gè)超時(shí)等待。隱的等待一個(gè)元素被發(fā)現(xiàn),或一個(gè)命令完成。如果超出了設(shè)置時(shí)間的則拋出異常。
- WebDriverWait():顯示等待,同樣也是 webdirver 提供的方法。在設(shè)置時(shí)間內(nèi),默認(rèn)每隔一段時(shí)間檢測一次當(dāng)前頁面元素是否存在,如果超過設(shè)置時(shí)間檢測不到則拋出異常。默認(rèn)檢測頻率為0.5s,默認(rèn)拋出異常為:NoSuchElementException
1、隱式等待:ImplicitlyWait
用到Timeouts對象。這個(gè)對象是用來對設(shè)置器進(jìn)行一些設(shè)置的。
- ImplicitlyWait:設(shè)置腳步在查找(定位)元素時(shí)最大的超時(shí)時(shí)間。如FindElement()方法在一些超大網(wǎng)頁中進(jìn)行定位時(shí)的超時(shí)時(shí)間。
- PageLoad:設(shè)置頁面操作超時(shí)時(shí)間(不是頁面加載時(shí)間)。是在頁面進(jìn)行跳轉(zhuǎn)操作或刷新操作時(shí)的等待時(shí)間。如Navigation對象的各種操作方法,以及在頁面上進(jìn)行某種操作后的等待時(shí)間。
- AsynchronousJavaScript: 設(shè)置腳步異步執(zhí)行的超時(shí)時(shí)間。
代碼如下:
driver.Navigate().GoToUrl("http://www.baidu.com");
ITimeouts timeouts = driver.Manage().Timeouts();
//設(shè)置查找元素最大超時(shí)時(shí)間為30秒
timeouts.ImplicitWait = new TimeSpan(0, 0, 30);
//設(shè)置頁面操作最大超時(shí)時(shí)間為30秒
timeouts.PageLoad = new TimeSpan(0, 0, 30);
//設(shè)置腳本異步最大超時(shí)時(shí)間為30秒
timeouts.AsynchronousJavaScript = new TimeSpan(0, 0, 30);2、顯示等待:WebDriverWait()
//等待頁面元素加載完成
//默認(rèn)等待100秒
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(100));
//等待頁面上ID屬性值為submitButton的元素加載完成
IWebElement myElement = wait.Until((d) =>
{
return d.FindElement(By.Id("submitButton"));
});三、查找(定位對象)
通過FindElement()這個(gè)方法來查找的。然后把參數(shù)傳遞過去。
driver.FindElement(By.Id ("kw")).SendKeys("搜索關(guān)鍵字");
driver.FindElement(By.Id( "su")).Click();其中By.id("su")就是定位參數(shù),傳遞一個(gè)對象過去。有8種定位方式。
注意:其中PartialLinkText是模糊查找。比如百度網(wǎng)頁中的關(guān)于 參數(shù)寫“關(guān)”就可以了,不用寫*這種符號(hào)。
//通過ID獲取元素
var byID = driver.FindElement(By.Id("cards"));
//通過類名獲取元素by class name
var byClassName = driver.FindElements(By.ClassName("menu"));
// 通過標(biāo)簽名獲取元素by tag name
var byTagName = driver.FindElement(By.TagName("iframe"));
// 通過名字獲取元素
var byName = driver.FindElement(By.Name("__VIEWSTATE"));
// 通過鏈接文本獲取元素by linked text <a rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank">http://www.google.com</a><a rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank">">linkedtext</a>>
var byLinkText = driver.FindElement(By.LinkText("linkedtext"));
// 通過部分鏈接文本獲取元素by partial link text :<a rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank">http://www.google.com</a><a rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" target="_blank">">linkedtext</a>>
var byPartialLinkText = driver.FindElement(By.PartialLinkText("text"));
//通過CSS選擇器獲取元素by css
var byCss = driver.FindElement(By.CssSelector("#header .content .logo"));
// 通過XPath來獲取元素(by xpath
var byXPath = driver.FindElements(By.XPath("http://div"));各方法使用優(yōu)先原則:
優(yōu)先使用id,name,classname,link;次之使用CssSelector();最后使用Xpath();
因?yàn)閄path()方法的性能和效率最低下。
四、獲取頁面元素和元素內(nèi)容
1.Title:標(biāo)題
Console.WriteLine(driver.Title);//輸出標(biāo)題名
2.Url:鏈接
Console.WriteLine(driver.Url);//輸出鏈接
3.Text:元素的文本值
Console.WriteLine(web.Text);//輸出元素標(biāo)記中文本的信息
4.Selected勾選情況、TagName標(biāo)記名標(biāo)、Enabled編輯狀態(tài)、Displayed顯示狀態(tài)
5.GetAttribute()獲取標(biāo)簽的屬性
var byIDAttributeText = byID.GetAttribute("id");6.彈出對話框的處理
首先,要先了解三種對話框:Alert、Confirmation以及Prompt。測試網(wǎng)頁test.html:
<html>
<head>
<title>這是標(biāo)題</title>
</head>
<body>
<input type="button" onclick="alert('這是Alert');" value="Alert" /><br/>
<input type="button" onclick="confirm('這是confirm');" value="confirm" /><br/>
<input type="button" onclick="prompt('這是Prompt');" value="prompt" /><br/>
</body>
</html>下面進(jìn)行測試:
var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service);
driver.Navigate().GoToUrl("file:///C:/Users/bobin.yang/Source/Repos/WinForm2/bin/Debug/HTMLPage1.html");
IWebElement web = driver.FindElement(By.XPath("http://input[1]"));
web.Click();
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0,0,2));
//Wait for the alert to be displayed
wait.Until(ExpectedConditions.AlertIsPresent());
Console.WriteLine(driver.SwitchTo().Alert().Text);//在接收消息前輸出
System.Threading.Thread.Sleep(1000);
driver.SwitchTo().Alert().Accept();
IWebElement web2 = driver.FindElement(By.XPath("http://input[2]"));
web2.Click();
WebDriverWait wait2 = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait2.Until(ExpectedConditions.AlertIsPresent());
Console.WriteLine(driver.SwitchTo().Alert().Text);//在接收消息前輸出
System.Threading.Thread.Sleep(1000);
driver.SwitchTo().Alert().Accept();
IWebElement web3 = driver.FindElement(By.XPath(@"html/body/input[3]"));
web3.Click();
System.Threading.Thread.Sleep(1000);
Console.WriteLine(driver.SwitchTo().Alert().Text);//在接收消息前輸出
driver.SwitchTo().Alert().SendKeys("這是輸入的內(nèi)容");
driver.SwitchTo().Alert().Accept();五、操作元素對象WebElement
主要是進(jìn)行Click和SendKeys操作,如圖。其它的自己查看定義就知道了。

1、模擬鼠標(biāo)點(diǎn)擊元素
driver.FindElement(By.Id("copyright")).Click();- SenKeys就是在定位到輸入框后,把參數(shù)text賦值進(jìn)去
- Click就是進(jìn)行鼠標(biāo)點(diǎn)擊操作,比如點(diǎn)擊按鈕等。和IDE上一樣的。單選、復(fù)選都是通過這個(gè)方法這點(diǎn)擊的。
- Clear方法:是用于清空輸入框的值,和SendKeys正好的作用正好相反。自己測試時(shí),建議先給輸入框賦值,再用Thread.Sleep(3000)來暫停一下,再用Clear方法,不然你還沒看到效果時(shí),程序已經(jīng)完成了。
- Submit:特殊之處在于,當(dāng)定位的是Form表單中任何一個(gè)元素,當(dāng)操作完之后,直接調(diào)用那個(gè)Submit方法就能對整個(gè)Form表單完成提交。不用再返回重新查找表單元素。
Selenium中在指定的文本框中輸入指定的字符串
//在文本框中輸入指定的字符串sendkeys()
Driver.FindElement(By.Id("tranAmtText")).SendKeys(“123456”);2、下拉列表框Select的操作
driver.Navigate().GoToUrl("http://tieba.baidu.com/f/search/adv");
IList listOption = driver.FindElement(By.Name("sm")).FindElements(By.TagName("option"));
string targetStr = "按相關(guān)性排序";
foreach (var option in listOption)
{
if (option.Text == targetStr) // if (option.GetAttribute("value").Equals(targetStr))
option.Click();
}3、執(zhí)行JS
var jsReturnValue = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("jsfunname");4、頁面導(dǎo)航
driver.Navigate().Forward(); driver.Navigate().Back();
Selenium中移動(dòng)光標(biāo)到指定的元素上
//移動(dòng)光標(biāo)到指定的元素上perform
Actions action=new Actions(driver);
action.MoveToElement(Find(By.XPath("http://input[@id='submit' and @value='確定']"))).Perform();5、拖拽操作(可以實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的驗(yàn)證)
var element = driver.FindElement(By.Name("source"));
IWebElement target = driver.FindElement(By.Name("target"));
(new Actions(driver)).DragAndDrop(element, target).Perform();6、模擬鼠標(biāo)晃動(dòng)
//模擬光標(biāo)晃動(dòng)movebyoffset() Actions action = new Actions(driver); action.MoveByOffset(2, 4);
7、截圖功能
//WebDriver中自帶截圖功能
Screenshot screenShotFile = ((ITakesScreenshot)driver).GetScreenshot();
screenShotFile.SaveAsFile("test", ImageFormat.Jpeg);8、selenium操作滾輪滑動(dòng)到底部
driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")六、獲得窗口標(biāo)識(shí)WindowHandles
要在不同的瀏覽器窗口之間切換,必須獲得不同的窗口(標(biāo)簽)的標(biāo)識(shí)符。用一個(gè)集合來保存這些數(shù)據(jù)。當(dāng)需要到新窗口里進(jìn)行操作時(shí),需要將測試器前往新的窗口。開始創(chuàng)建的測試器是對窗口來的,所以當(dāng)我們需要切換窗口時(shí)。需要調(diào)用 測試器.SwitchTo().window(獲得標(biāo)識(shí)) 這個(gè)方法來返回一個(gè)新的測試器對象。新的對象是代表的是切換的窗口。代碼如下:
var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service);
driver.Navigate().GoToUrl("http://tieba.baidu.com/f/search/adv");
//找到注冊元素
IWebElement register = driver.FindElement(By.XPath(@".//*[@id='com_userbar']/ul/li[5]/div/a"));
register.Click();
//顯示所有標(biāo)識(shí)
IList<string> listHand = driver.WindowHandles;//拿到所有標(biāo)識(shí)
foreach (string item in listHand)
{
Console.WriteLine(item);
}
/*這里一會(huì)插入代碼*/
Console.ReadKey();
driver.Quit();效果如下:

下面切換到新打開的窗口后,輸入一個(gè)12345來表示我們成功了
在上面的代碼基礎(chǔ)下 添加下面代碼
//切換到注冊窗口再輸入12345
driver.SwitchTo().Window(listHand[1]);
driver.FindElement(By.Name("userName")).SendKeys("12345");結(jié)果如圖:

1、關(guān)閉多個(gè)子Browser窗口
//獲取所有的WindowHandle,關(guān)閉所有子窗口
string oldwin = driver.CurrentWindowHandle;
ReadOnlyCollection<string> windows = driver.WindowHandles;
foreach (var win in windows)
{
if (win != oldwin)
{
driver.SwitchTo().Window(win).Close();
}
}
driver.SwitchTo().Window(oldwin);2、對iframe中元素的定位
1、切換焦點(diǎn)到id為固定值的iframe上
進(jìn)入頁面后,光標(biāo)默認(rèn)焦點(diǎn)在DefaultContent中,若想要定位到iframe 需要轉(zhuǎn)換焦點(diǎn)
driver.SwitchTo().DefaultContent();
//切換焦點(diǎn)到mainFrame
driver.SwitchTo().Frame("mainFrame");需要注意的是:切換焦點(diǎn)之后若想切換焦點(diǎn)到其他iframe上 需要先返回到defaultcontent,再切換焦點(diǎn)到指定的iframe上。
2、切換焦點(diǎn)到id值為動(dòng)態(tài)值的iframe上
有時(shí)候 頁面上浮出層的id為動(dòng)態(tài)值,此時(shí)需要先獲取所有符合記錄的iframe放置在數(shù)組中,然后遍歷數(shù)組切換焦點(diǎn)到目標(biāo)iframe上。
如下方法:
protected string bizFrameId = string.Empty;
protected string bizId = string.Empty;
//獲取動(dòng)態(tài)iframe的id值
protected void SetIframeId()
{
ReadOnlyCollection els = driver.FindElements(By.TagName("iframe"));
foreach (var e in driver.FindElements(By.TagName("iframe")))
{
string s1 = e.GetAttribute("id");
if (s1.IndexOf("window") >= 0 && s1.IndexOf("content") >= 0)
{
bizFrameId = e.GetAttribute("id");
string[] ss = s1.Split(new char[] { '_' });
bizId = ss[1];
}
}
}七、Cookies
在C#中,通過Cookies屬性來獲取當(dāng)前的Cookie集合,然后進(jìn)行增刪改查操作。
Cookie由5個(gè)部分組成:名稱、值、所在域、路徑和過期時(shí)間。
下面我們進(jìn)入百度首頁,然后獲取cookie,并讓它變動(dòng)一下來看到效果。 代碼如下:
var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service);
driver.Navigate().GoToUrl("http://www.baidu.com");
//獲取Cookie
ICookieJar listCookie = driver.Manage().Cookies;
// IList listCookie = driver.Manage( ).Cookies.AllCookies;//只是顯示 可以用Ilist對象
//顯示初始Cookie的內(nèi)容
Console.WriteLine("--------------------");
Console.WriteLine($"當(dāng)前Cookie集合的數(shù)量:\t{listCookie.AllCookies.Count}");
for (int i = 0; i < listCookie.AllCookies.Count; i++)
{
Console.WriteLine($"Cookie的名稱:{listCookie.AllCookies[i].Name}");
Console.WriteLine($"Cookie的值:{listCookie.AllCookies[i].Value}");
Console.WriteLine($"Cookie的所在域:{listCookie.AllCookies[i].Domain}");
Console.WriteLine($"Cookie的路徑:{listCookie.AllCookies[i].Path}");
Console.WriteLine($"Cookie的過期時(shí)間:{listCookie.AllCookies[i].Expiry}");
Console.WriteLine("-----");
}
//添加一個(gè)新的Cookie
Cookie newCookie = new Cookie("新Cookie", "新值", "", DateTime.Now.AddDays(1));
listCookie.AddCookie(newCookie);
Console.WriteLine("--------------------");
Console.WriteLine($"當(dāng)前Cookie集合的數(shù)量:\t{listCookie.AllCookies.Count}");
for (int i = 0; i < listCookie.AllCookies.Count; i++)
{
Console.WriteLine($"Cookie的名稱:{listCookie.AllCookies[i].Name}");
Console.WriteLine($"Cookie的值:{listCookie.AllCookies[i].Value}");
Console.WriteLine($"Cookie的所在域:{listCookie.AllCookies[i].Domain}");
Console.WriteLine($"Cookie的路徑:{listCookie.AllCookies[i].Path}");
Console.WriteLine($"Cookie的過期時(shí)間:{listCookie.AllCookies[i].Expiry}");
Console.WriteLine("-----");
}
//刪除這個(gè)Cookie并再次顯示總數(shù)
listCookie.DeleteCookieNamed(newCookie.Name);
Console.WriteLine($"當(dāng)前Cookie集合的數(shù)量:\t{listCookie.AllCookies.Count}");
Console.ReadLine();
driver.Quit();運(yùn)行效果如下:

八、Window窗口控制
這個(gè)屬性是可以對當(dāng)前的窗口進(jìn)行簡單的控制。如獲取坐標(biāo)和大小,還可以將其最大化。下面我們用過示例代碼來試試效果。
下面的代碼是先打開網(wǎng)頁,打印坐標(biāo)和大小,再控制它最大化,再次打印坐標(biāo)和大小。
var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service);
driver.Navigate().GoToUrl("http://www.baidu.com");
//打印現(xiàn)在的坐標(biāo)和大小
IWindow window = driver.Manage().Window;
Console.WriteLine("第一次打印");
Console.WriteLine($"坐標(biāo)X為{window.Position.X}\tY為{window.Position.Y}");
Console.WriteLine($"大小長為{window.Size.Width}\t寬為{window.Size.Height}");
Console.WriteLine("-------------");
//控制最大化
window.Maximize();
//再次打印數(shù)據(jù)
Console.WriteLine("第二次打印");
Console.WriteLine($"坐標(biāo)X為{window.Position.X}\tY為{window.Position.Y}");
Console.WriteLine($"大小長為{window.Size.Width}\t寬為{window.Size.Height}");
Console.WriteLine("-------------");
Console.ReadLine();
driver.Quit();效果如下:

這里有兩個(gè)奇怪的地方:
1.我的屏幕是1080P的,輸出后的數(shù)據(jù)中,長只有1936.如果減去16的話到正好是1920.但是寬應(yīng)該是1080,如果任務(wù)欄的寬度是24的話,到也能說得過去。只是數(shù)據(jù)和我們要的有點(diǎn)偏差,這里需要注意一下。
2.window屬性居然只有位置、大小和最大化方法。居然沒有最小化或還原(退出最大化狀態(tài))方法。
九、事件
首先是準(zhǔn)備好要添加的事件,然后再掛接。這里可以使用C#的語法糖。在+=后面直接按兩次tab鍵,然后再移動(dòng)到事件區(qū)編輯。
eventDriver.Navigating += EventDriver_Navigating;//導(dǎo)航前 eventDriver.Navigated += EventDriver_Navigated;//導(dǎo)航后 eventDriver.FindingElement += EventDriver_FindingElement;//查找元素前 eventDriver.FindElementCompleted += EventDriver_FindElementCompleted;//查找元素后 eventDriver.ElementClicking += EventDriver_ElementClicking;//元素單擊前 eventDriver.ElementClicked += EventDriver_ElementClicked;//元素單擊后 eventDriver.ElementValueChanging += EventDriver_ElementValueChanging;//元素值改變前 eventDriver.ElementValueChanged += EventDriver_ElementValueChanged;//元素值改變后 eventDriver.ExceptionThrown += EventDriver_ExceptionThrown;//異常發(fā)生后事件
掛接事件:
#region 事件區(qū)
///
/// 導(dǎo)航前發(fā)生的事件
///
///
///
private void EventDriver_Navigating(object sender, WebDriverNavigationEventArgs e)
{
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"即將要跳轉(zhuǎn)到的URL為:{e.Driver.Url}");
}
///
/// 導(dǎo)航后發(fā)生的事件
///
///
///
private void EventDriver_Navigated(object sender, WebDriverNavigationEventArgs e)
{
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"跳轉(zhuǎn)到的URL為:{e.Driver.Url}");
}
///
/// 查找元素前發(fā)生
///
///
///
private void EventDriver_FindingElement(object sender, FindElementEventArgs e)
{
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"即將查找的元素為:{e.FindMethod.ToString()}");
}
///
/// 查找元素后發(fā)生
///
///
///
private void EventDriver_FindElementCompleted(object sender, FindElementEventArgs e)
{
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"找到元素,條件為:{e.FindMethod.ToString()}");
}
///
/// 單擊元素前發(fā)生
///
///
///
private void EventDriver_ElementClicking(object sender, WebElementEventArgs e)
{
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"要單擊的元素的value屬性為:{e.Element.GetAttribute("value")}");
}
///
/// 單擊元素后發(fā)生
///
///
///
private void EventDriver_ElementClicked(object sender, WebElementEventArgs e)
{
System.Threading.Thread.Sleep(3 * 1000);//暫停3秒
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"單擊元素后,現(xiàn)在的URL為:{e.Driver.Url}");
}
///
/// 單擊元素前發(fā)生
///
///
///
private void EventDriver_ElementValueChanging(object sender, WebElementEventArgs e)
{
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"元素更改前的值為:{e.Element.GetAttribute("value")}");
}
///
/// 單擊元素后發(fā)生
///
///
///
private void EventDriver_ElementValueChanged(object sender, WebElementEventArgs e)
{
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"元素更改后的值為:{e.Element.GetAttribute("value")}");
}
///
/// 異常(保存截圖到本地)
///
///
///
private void EventDriver_ExceptionThrown(object sender, WebDriverExceptionEventArgs e)
{
//地址
string strPath = $@"D:\Desktop\{DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss")}.png";
//保存截圖
Screenshot screen = (sender as EventFiringWebDriver).GetScreenshot();
screen.SaveAsFile(strPath, System.Drawing.Imaging.ImageFormat.Png);
//輸出保存信息
this.listMeassage.Add("-----------------------------------------");
this.listMeassage.Add($"發(fā)生異常,截圖已保存到:{strPath}");
}十、關(guān)閉瀏覽器
有下面兩種:
- Close():關(guān)閉WedDriver對象所在的窗口;
第一個(gè)是關(guān)閉一個(gè)窗口,一個(gè)wedDriver對象是可以有多個(gè)窗口的(之前的窗口切換也是提到過),需要關(guān)閉時(shí)要保證當(dāng)前激活的窗口。比如一個(gè)wedDriver對象里有好多個(gè)窗口,你要關(guān)閉第2個(gè)窗口,就要用SwitchTo().Window()方法切換到第2個(gè)窗口才能關(guān)閉,不能直接關(guān)閉第幾個(gè)窗口的。 - Quit():關(guān)閉所有相關(guān)窗口;
第二個(gè)關(guān)閉和這個(gè)webDriver對象所有相關(guān)的窗口。當(dāng)然,一個(gè)腳本是可以有多個(gè)webDriver對象
下面代碼的代碼展示這了兩個(gè)方法的用法和用途。
1.打開百度首頁,單擊“注冊”超級鏈接。
2.在彈出的窗口(百度賬戶注冊)中,調(diào)用Close()方法,關(guān)閉新彈出的頁面
3.再一次點(diǎn)擊“注冊”超級鏈接,調(diào)用Quit()方法來結(jié)束測試。
var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service);
//導(dǎo)航到百度首頁
driver.Navigate().GoToUrl("http://www.baidu.com");
//進(jìn)行點(diǎn)擊
Console.WriteLine("-------------------");
Console.WriteLine("進(jìn)行點(diǎn)擊");
driver.FindElement(By.LinkText("登錄")).Click();
System.Threading.Thread.Sleep(3 * 1000);
driver.FindElement(By.LinkText("立即注冊")).Click();
//獲取窗口句柄
IList<string> listHand = driver.WindowHandles;
//切換到注冊窗口并關(guān)閉
Console.WriteLine("-------------------");
Console.WriteLine("切換到注冊窗口");
driver.SwitchTo().Window(listHand[1]);
System.Threading.Thread.Sleep(3 * 1000);
Console.WriteLine("-------------------");
Console.WriteLine("關(guān)閉注冊窗口");
driver.Close();
System.Threading.Thread.Sleep(3 * 1000);
//切換到主窗口并結(jié)束測試
Console.WriteLine("-------------------");
Console.WriteLine("切換到主窗口并結(jié)束測試");
driver.SwitchTo().Window(listHand[0]);
driver.FindElement(By.LinkText("立即注冊")).Click();
System.Threading.Thread.Sleep(3 * 1000);
driver.Quit();
Console.ReadLine();到此這篇關(guān)于C#使用selenium實(shí)現(xiàn)爬蟲的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# 基于udp廣播收集局域網(wǎng)類所有設(shè)備信息
這篇文章主要介紹了C# 基于udp廣播收集局域網(wǎng)類所有設(shè)備信息的方法,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-12-12

