首頁 > 軟體

C#使用selenium實現爬蟲

2022-06-08 18:02:42

一、介紹:

Selenium 是一個用於Web應用程式測試的工具。Selenium測試直接執行在瀏覽器中,就像真正的使用者在操作一樣。

1、Selenium Webdriver(也就是Selenium2,Selenium3)和Selenium RCSelenium 1)一樣提供了web自動化的各種語言呼叫介面庫。相比Selenium RCSelenium WebDriver的程式設計介面更加直觀易懂,也更加簡練。

但是和Selenium RC不同的是,Selenium Webdriver是通過各種瀏覽器的驅動(web driver)來驅動瀏覽器的,而不是通過注入JavaScript的方式。

我們的程式碼執行起來是一個程序,裡面呼叫Selenium WebDriver的庫和各個瀏覽器的驅動程序 進行互動,傳遞Selenium命令 給它們,並且獲取命令執行的結果,返回給我們的程式碼進行處理。

2、Selenium WebDriver目前包括兩個版本Selenium 2Selenium 3。這兩個版本從開發程式碼呼叫介面上來看,幾乎沒什麼區別。區別在於庫的實現和web driver的實現。

Selenium2Selenium組織幫各種瀏覽器寫web driver的,而Selenium 3裡面的web driver是由各個瀏覽器廠商(Apple,Google,Microsoft,Mozilla)自己提供的。所以Selenium 3的自動化效率更高,成功率也更高。

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

利用它可以驅動瀏覽器執行特定的動作,如點選、下拉等操作,同時還可以獲取瀏覽器當前呈現的頁面的原始碼 ,做到可見即可爬。

所以Selenium現在被廣泛用於Python爬蟲。查了下資料,發現這個工具確實強大,最重要的是,C#也是可以呼叫的。

官方支援Java,C#,Python,Ruby,PHP,Perl,Javascript等語言

官方檔案(有C#範例):https://www.selenium.dev/documentation/en/

安裝Selenium:

1、我們新建一個C#控制檯程式

2、使用Nuget搜尋以下依賴庫

需要參照的核心庫是Selenium.RC,Selenium.Support,Selenium.WebDriver

然後再需要參照瀏覽器驅動庫,這裡我以新版Edge瀏覽器為例,新版Edge使用方式跟Chrome是一樣的,程式包名稱為Selenium.WebDriver.MSEdgeDriver。

備註:也可以在微軟WebDriver官網下載Edge (Chromium)的webdriver,需要和當前瀏覽器版本一致。然後下載放置到專案可執行檔案的目錄。

如果使用Chrome:

先查下本機Chrome的版本

然後去Nuget搜尋Selenium.WebDriver.ChromeDriver進行下載安裝。

注意:webdriver版本只需要和當前瀏覽器主版本一致即可。

3、在Main函數中輸入以下程式碼

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");

執行,會彈出IE瀏覽器,網頁載入完成後,瀏覽器會自動關閉。控制檯輸入結果如下

這樣我們就可以輕鬆的獲取動態渲染頁面的原始碼。

二、等待

常用的等待分為顯示等待WebDriverWait()隱式等待ImplicitlyWait()強制等待sleep()三種,下面我們就分別介紹一下這三種等待的區別

  • Sleep(): 強制等待,設定固定休眠時間。
  • ImplicitlyWait():隱式等待,也叫智慧等待,是 webdirver 提供的一個超時等待。隱的等待一個元素被發現,或一個命令完成。如果超出了設定時間的則丟擲異常。
  • WebDriverWait():顯示等待,同樣也是 webdirver 提供的方法。在設定時間內,預設每隔一段時間檢測一次當前頁面元素是否存在,如果超過設定時間檢測不到則丟擲異常。預設檢測頻率為0.5s,預設丟擲異常為:NoSuchElementException

1、隱式等待:ImplicitlyWait

用到Timeouts物件。這個物件是用來對設定器進行一些設定的。

  • ImplicitlyWait:設定腳步在查詢(定位)元素時最大的超時時間。如FindElement()方法在一些超大網頁中進行定位時的超時時間。
  • PageLoad:設定頁面操作超時時間(不是頁面載入時間)。是在頁面進行跳轉操作或重新整理操作時的等待時間。如Navigation物件的各種操作方法,以及在頁面上進行某種操作後的等待時間。
  • AsynchronousJavaScript: 設定腳步非同步執行的超時時間。

程式碼如下:

driver.Navigate().GoToUrl("http://www.baidu.com");
ITimeouts timeouts = driver.Manage().Timeouts();

//設定查詢元素最大超時時間為30秒
timeouts.ImplicitWait = new TimeSpan(0, 0, 30);
//設定頁面操作最大超時時間為30秒
timeouts.PageLoad = new TimeSpan(0, 0, 30);
//設定指令碼非同步最大超時時間為30秒
timeouts.AsynchronousJavaScript = new TimeSpan(0, 0, 30);

2、顯示等待:WebDriverWait()

//等待頁面元素載入完成
//預設等待100秒
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(100));
//等待頁面上ID屬性值為submitButton的元素載入完成
IWebElement myElement = wait.Until((d) =>
{
    return d.FindElement(By.Id("submitButton"));
});

三、查詢(定位物件)

通過FindElement()這個方法來查詢的。然後把引數傳遞過去。

driver.FindElement(By.Id ("kw")).SendKeys("搜尋鍵碼");
driver.FindElement(By.Id( "su")).Click();

其中By.id("su")就是定位引數,傳遞一個物件過去。有8種定位方式。

注意:其中PartialLinkText是模糊查詢。比如百度網頁中的關於 引數寫“關”就可以了,不用寫*這種符號。

//通過ID獲取元素
var byID = driver.FindElement(By.Id("cards"));

//通過類名獲取元素by class name
var byClassName = driver.FindElements(By.ClassName("menu"));

// 通過標籤名獲取元素by tag name 
var byTagName = driver.FindElement(By.TagName("iframe"));

// 通過名字獲取元素
var byName = driver.FindElement(By.Name("__VIEWSTATE"));

// 通過連結文字獲取元素by linked text  <a href="https://www.cnblogs.com/springsnow/p/%3C/span%3E%3Cspan%20style=" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"   target="_blank">http://www.google.com</a><a href="https://www.cnblogs.com/springsnow/p/%3C/span%3E%3Cspan%20style=" 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 href="https://www.cnblogs.com/springsnow/p/%3C/span%3E%3Cspan%20style=" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow"   target="_blank">http://www.google.com</a><a href="https://www.cnblogs.com/springsnow/p/%3C/span%3E%3Cspan%20style=" 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("//div"));

各方法使用優先原則:

優先使用id,name,classname,link;次之使用CssSelector();最後使用Xpath();

因為Xpath()方法的效能和效率最低下。

四、獲取頁面元素和元素內容

1.Title:標題

Console.WriteLine(driver.Title);//輸出標題名

2.Url:連結

Console.WriteLine(driver.Url);//輸出連結

3.Text:元素的文字值

Console.WriteLine(web.Text);//輸出元素標記中文字的資訊

4.Selected勾選情況、TagName標記名標、Enabled編輯狀態、Displayed顯示狀態

5.GetAttribute()獲取標籤的屬性

var byIDAttributeText = byID.GetAttribute("id");

6.彈出對話方塊的處理

首先,要先了解三種對話方塊:Alert、Confirmation以及Prompt。測試網頁test.html:

<html>
    <head>
         <title>這是標題</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>

下面進行測試:

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("//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("//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("這是輸入的內容");
driver.SwitchTo().Alert().Accept();

五、操作元素物件WebElement

主要是進行Click和SendKeys操作,如圖。其它的自己檢視定義就知道了。 

1、模擬滑鼠點選元素

driver.FindElement(By.Id("copyright")).Click();
  • SenKeys就是在定位到輸入框後,把引數text賦值進去
  • Click就是進行滑鼠點選操作,比如點選按鈕等。和IDE上一樣的。單選、複選都是通過這個方法這點選的。
  • Clear方法:是用於清空輸入框的值,和SendKeys正好的作用正好相反。自己測試時,建議先給輸入框賦值,再用Thread.Sleep(3000)來暫停一下,再用Clear方法,不然你還沒看到效果時,程式已經完成了。
  • Submit:特殊之處在於,當定位的是Form表單中任何一個元素,當操作完之後,直接呼叫那個Submit方法就能對整個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 = "按相關性排序";

foreach (var option in listOption)
{
    if (option.Text == targetStr)  // if (option.GetAttribute("value").Equals(targetStr))
        option.Click();
}

3、執行JS

var jsReturnValue = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("jsfunname");

4、頁面導航

driver.Navigate().Forward();
driver.Navigate().Back();

Selenium中移動遊標到指定的元素上

//移動遊標到指定的元素上perform
Actions action=new Actions(driver);
action.MoveToElement(Find(By.XPath("//input[@id='submit' and @value='確定']"))).Perform();

5、拖拽操作(可以實現滑動驗證碼的驗證)

var element = driver.FindElement(By.Name("source"));
IWebElement target = driver.FindElement(By.Name("target"));
(new Actions(driver)).DragAndDrop(element, target).Perform();

6、模擬滑鼠晃動

//模擬遊標晃動movebyoffset()
Actions action = new Actions(driver);
action.MoveByOffset(2, 4);

7、截圖功能

//WebDriver中自帶截圖功能
Screenshot screenShotFile = ((ITakesScreenshot)driver).GetScreenshot();
screenShotFile.SaveAsFile("test", ImageFormat.Jpeg);

8、selenium操作滾輪滑動到底部

driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")

六、獲得視窗標識WindowHandles

要在不同的瀏覽器視窗之間切換,必須獲得不同的視窗(標籤)的識別符號。用一個集合來儲存這些資料。當需要到新視窗裡進行操作時,需要將測試器前往新的視窗。開始建立的測試器是對視窗來的,所以當我們需要切換視窗時。需要呼叫 測試器.SwitchTo().window(獲得標識) 這個方法來返回一個新的測試器物件。新的物件是代表的是切換的視窗。程式碼如下:

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();

//顯示所有標識
IList<string> listHand = driver.WindowHandles;//拿到所有標識
foreach (string item in listHand)
{
    Console.WriteLine(item);
}

/*這裡一會插入程式碼*/

Console.ReadKey();
driver.Quit();

效果如下:

下面切換到新開啟的視窗後,輸入一個12345來表示我們成功了 
在上面的程式碼基礎下 新增下面程式碼

//切換到註冊視窗再輸入12345
driver.SwitchTo().Window(listHand[1]);
driver.FindElement(By.Name("userName")).SendKeys("12345");

結果如圖:

1、關閉多個子Browser視窗

//獲取所有的WindowHandle,關閉所有子視窗
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、切換焦點到id為固定值的iframe上

進入頁面後,遊標預設焦點在DefaultContent中,若想要定位到iframe 需要轉換焦點

driver.SwitchTo().DefaultContent();
//切換焦點到mainFrame
driver.SwitchTo().Frame("mainFrame");

需要注意的是:切換焦點之後若想切換焦點到其他iframe上 需要先返回到defaultcontent,再切換焦點到指定的iframe上。

2、切換焦點到id值為動態值的iframe上

有時候 頁面上浮出層的id為動態值,此時需要先獲取所有符合記錄的iframe放置在陣列中,然後遍歷陣列切換焦點到目標iframe上。

如下方法:

protected string bizFrameId = string.Empty;
protected string bizId = string.Empty;
//獲取動態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屬性來獲取當前的Cookie集合,然後進行增刪改查操作。

Cookie由5個部分組成:名稱、值、所在域、路徑和過期時間。

下面我們進入百度首頁,然後獲取cookie,並讓它變動一下來看到效果。 程式碼如下:

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的內容
Console.WriteLine("--------------------");
Console.WriteLine($"當前Cookie集合的數量: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的過期時間:{listCookie.AllCookies[i].Expiry}");
    Console.WriteLine("-----");
}


//新增一個新的Cookie
Cookie newCookie = new Cookie("新Cookie", "新值", "", DateTime.Now.AddDays(1));

listCookie.AddCookie(newCookie);
Console.WriteLine("--------------------");
Console.WriteLine($"當前Cookie集合的數量: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的過期時間:{listCookie.AllCookies[i].Expiry}");
    Console.WriteLine("-----");
}

//刪除這個Cookie並再次顯示總數
listCookie.DeleteCookieNamed(newCookie.Name);

Console.WriteLine($"當前Cookie集合的數量:t{listCookie.AllCookies.Count}");


Console.ReadLine();
driver.Quit();

執行效果如下:

八、Window視窗控制

這個屬性是可以對當前的視窗進行簡單的控制。如獲取座標和大小,還可以將其最大化。下面我們用過範例程式碼來試試效果。 
下面的程式碼是先開啟網頁,列印座標和大小,再控制它最大化,再次列印座標和大小。

var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service);

driver.Navigate().GoToUrl("http://www.baidu.com");

//列印現在的座標和大小
IWindow window = driver.Manage().Window;
Console.WriteLine("第一次列印");
Console.WriteLine($"座標X為{window.Position.X}tY為{window.Position.Y}");
Console.WriteLine($"大小長為{window.Size.Width}t寬為{window.Size.Height}");
Console.WriteLine("-------------");

//控制最大化
window.Maximize();

//再次列印資料
Console.WriteLine("第二次列印");
Console.WriteLine($"座標X為{window.Position.X}tY為{window.Position.Y}");
Console.WriteLine($"大小長為{window.Size.Width}t寬為{window.Size.Height}");
Console.WriteLine("-------------");

Console.ReadLine();
driver.Quit();

效果如下:

這裡有兩個奇怪的地方:
1.我的螢幕是1080P的,輸出後的資料中,長只有1936.如果減去16的話到正好是1920.但是寬應該是1080,如果工作列的寬度是24的話,到也能說得過去。只是資料和我們要的有點偏差,這裡需要注意一下。
2.window屬性居然只有位置、大小和最大化方法。居然沒有最小化或還原(退出最大化狀態)方法。

九、事件

首先是準備好要新增的事件,然後再掛接。這裡可以使用C#的語法糖。在+=後面直接按兩次tab鍵,然後再移動到事件區編輯。

eventDriver.Navigating += EventDriver_Navigating;//導航前
eventDriver.Navigated += EventDriver_Navigated;//導航後
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;//異常發生後事件

掛接事件:

#region 事件區

/// 
/// 導航前發生的事件
/// 
/// 
/// 
private void EventDriver_Navigating(object sender, WebDriverNavigationEventArgs e)
{
    this.listMeassage.Add("-----------------------------------------");
    this.listMeassage.Add($"即將要跳轉到的URL為:{e.Driver.Url}");
}

/// 
/// 導航後發生的事件
/// 
/// 
/// 
private void EventDriver_Navigated(object sender, WebDriverNavigationEventArgs e)
{
    this.listMeassage.Add("-----------------------------------------");
    this.listMeassage.Add($"跳轉到的URL為:{e.Driver.Url}");
}

/// 
/// 查詢元素前發生
/// 
/// 
/// 
private void EventDriver_FindingElement(object sender, FindElementEventArgs e)
{
    this.listMeassage.Add("-----------------------------------------");

    this.listMeassage.Add($"即將查詢的元素為:{e.FindMethod.ToString()}");
}

/// 
/// 查詢元素後發生
/// 
/// 
/// 
private void EventDriver_FindElementCompleted(object sender, FindElementEventArgs e)
{
    this.listMeassage.Add("-----------------------------------------");
    this.listMeassage.Add($"找到元素,條件為:{e.FindMethod.ToString()}");
}

/// 
/// 單擊元素前發生
/// 
/// 
/// 
private void EventDriver_ElementClicking(object sender, WebElementEventArgs e)
{
    this.listMeassage.Add("-----------------------------------------");
    this.listMeassage.Add($"要單擊的元素的value屬性為:{e.Element.GetAttribute("value")}");
}

/// 
/// 單擊元素後發生
/// 
/// 
/// 
private void EventDriver_ElementClicked(object sender, WebElementEventArgs e)
{
    System.Threading.Thread.Sleep(3 * 1000);//暫停3秒
    this.listMeassage.Add("-----------------------------------------");
    this.listMeassage.Add($"單擊元素後,現在的URL為:{e.Driver.Url}");
}

/// 
/// 單擊元素前發生
/// 
/// 
/// 
private void EventDriver_ElementValueChanging(object sender, WebElementEventArgs e)
{
    this.listMeassage.Add("-----------------------------------------");
    this.listMeassage.Add($"元素更改前的值為:{e.Element.GetAttribute("value")}");
}

/// 
/// 單擊元素後發生
/// 
/// 
/// 
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($"發生異常,截圖已儲存到:{strPath}");
}

十、關閉瀏覽器

有下面兩種:

  • Close():關閉WedDriver物件所在的視窗; 
    第一個是關閉一個視窗,一個wedDriver物件是可以有多個視窗的(之前的視窗切換也是提到過),需要關閉時要保證當前啟用的視窗。比如一個wedDriver物件裡有好多個視窗,你要關閉第2個視窗,就要用SwitchTo().Window()方法切換到第2個視窗才能關閉,不能直接關閉第幾個視窗的。
  • Quit():關閉所有相關視窗; 
    第二個關閉和這個webDriver物件所有相關的視窗。當然,一個指令碼是可以有多個webDriver物件

下面程式碼的程式碼展示這了兩個方法的用法和用途。 
1.開啟百度首頁,單擊“註冊”超級連結。 
2.在彈出的視窗(百度賬戶註冊)中,呼叫Close()方法,關閉新彈出的頁面 
3.再一次點選“註冊”超級連結,呼叫Quit()方法來結束測試。

var service = EdgeDriverService.CreateDefaultService(@".", "msedgedriver.exe");
IWebDriver driver = new OpenQA.Selenium.Edge.EdgeDriver(service);

//導航到百度首頁
driver.Navigate().GoToUrl("http://www.baidu.com");

//進行點選
Console.WriteLine("-------------------");
Console.WriteLine("進行點選");
driver.FindElement(By.LinkText("登入")).Click();
System.Threading.Thread.Sleep(3 * 1000);
driver.FindElement(By.LinkText("立即註冊")).Click();

//獲取視窗控制程式碼
IList<string> listHand = driver.WindowHandles;

//切換到註冊視窗並關閉
Console.WriteLine("-------------------");
Console.WriteLine("切換到註冊視窗");
driver.SwitchTo().Window(listHand[1]);
System.Threading.Thread.Sleep(3 * 1000);
Console.WriteLine("-------------------");
Console.WriteLine("關閉註冊視窗");
driver.Close();
System.Threading.Thread.Sleep(3 * 1000);

//切換到主視窗並結束測試
Console.WriteLine("-------------------");
Console.WriteLine("切換到主視窗並結束測試");
driver.SwitchTo().Window(listHand[0]);
driver.FindElement(By.LinkText("立即註冊")).Click();
System.Threading.Thread.Sleep(3 * 1000);
driver.Quit();

Console.ReadLine();

到此這篇關於C#使用selenium實現爬蟲的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com