2010-08-05 145 views
1

民間,使用C#測試網站

我需要完成一些複雜的網頁抓取。

簡單的目標是:登錄到頁面,在某些文本字段中輸入一些值,單擊提交,然後從檢索到的頁面中提取一些值。

什麼是最好的方法?

  1. 部分單元測試第三方庫?
  2. 在C#中手動抓取?
  3. 也許有專門的準備好lib吧?
  4. 還有其他的方法嗎?

這需要在一個web應用程序內完成。

非常感謝您的幫助。

回答

3

不知道它將如何在Web應用程序內工作,但你有沒有考慮給HtmlUnit一個嘗試?我認爲它應該很好,因爲它基本上是一個無頭網頁瀏覽器。

史蒂文桑德森有一個blog post about using HtmlUnit in .NET code

+0

似乎讓我更接近我們的目標... 我會仔細研究它幾分鐘,並在這裏發佈結果。 謝謝!以後再聊。 – charlie 2010-08-05 19:44:16

+0

這是我卡住的地方:它需要包含Java中的IKVM.OpenJDK.Security.dll才能在> net中使用,但我不知道如何去做...... – charlie 2010-08-05 22:04:39

+0

不,你不需要需要Java SDK中的任何東西。如果你看看你的IKVM下載目錄,你會發現一堆DLLS,其中一個是IKVM.OpenJDK.Security.dll。您需要像在.NET程序集中那樣,在項目中添加對該項目的引用。您還需要添加對IKVM.OpenJDK.Core,IKVM.OpenJDK.Text,IKVM.OpenJDK.Util,IKVM.OpenJDK.XML.API,IKVM.OpenJDK.XML.Parse,IKVM.OpenJDK.XML的引用。路徑和IKVM.Runtime.dll。 – Mhmmd 2010-08-05 22:47:20

4

WatiN。

http://watin.sourceforge.net/

var browser = new IE(); 

browser.GoTo("http://www.mywebsite.com"); 

browser.TextField("username").TypeText("username goes here"); // alternatively, use .Value = if you don't need to simulate keystrokes. 

browser.Button(Find.ById("submitButton")).Click(); 

,並在你的斷言返回頁面:

Assert.AreEqual("You are logged in as Username.", ie.TextField("username").Value); // you can essentially check any HTML tag, I just used TextField for brevity. 

編輯 -

讀取編輯從一個Web瀏覽器中執行此操作後,您可能會考慮使用WebRequest和HTML Agility Pack來驗證您返回的內容:

的WebRequest:

http://msdn.microsoft.com/en-us/library/debx8sh9.aspx

HTML敏捷性包:

How to use HTML Agility pack

+0

噢,對不起。我忘了提:我需要這是一個Web應用程序中完成的。這就是爲什麼我不能使用watin。 – charlie 2010-08-05 19:19:17

+0

啊,只是看到了Web應用程序編輯..這將無助於..大聲笑 – 2010-08-05 19:23:35

+0

謝謝伊恩嘗試。我很感激。 任何其他方向? – charlie 2010-08-05 19:26:04

0

如果你知道什麼表單提交值都應該是進入和出來,你可以創建一個應用程序C#使用HttpWebRequest併發布到頁面並解析結果。這段代碼是高度專業化的,供我自己使用,但你應該能夠調整它,並使它做你想做的事情。它實際上是一個更大的類的一部分,可以讓你添加post/get項目,然後爲你提交一個http請求。

// this is for the query string 
char[] temp = new char[1]; 
temp[0] = '?'; 

// create the query string for post/get types 
Uri uri = _type == PostType.Post ? new Uri(url) : new Uri((url + "?" + postData).TrimEnd(temp)); 

// create the request 
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 

request.Accept = _accept; 
request.ContentType = _contentType; 
request.Method = _type == PostType.Post ? "POST" : "GET"; 
request.CookieContainer = _cookieContainer; 
request.Referer = _referer; 
request.AllowAutoRedirect = _allowRedirect; 
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3"; 

// set the timeout to a big value like 2 minutes 
request.Timeout = 120000; 

// set our credentials 
request.Credentials = CredentialCache.DefaultCredentials; 

// if we have a proxy set its creds as well 
if(request.Proxy != null) 
{ 
    request.Proxy.Credentials = CredentialCache.DefaultCredentials; 
} 


// append post items if we need to 
if(!String.IsNullOrEmpty(_body)) 
{ 
    using(StreamWriter sw = new StreamWriter(request.GetRequestStream(), Encoding.ASCII)) 
    { 
    sw.Write(_body); 
    } 
} 

if(_type == PostType.Post && 
    String.IsNullOrEmpty(_body)) 
{ 
    using(Stream writeStream = request.GetRequestStream()) 
    { 
     UTF8Encoding encoding = new UTF8Encoding(); 
     byte[] bytes = encoding.GetBytes(postData); 

     writeStream.Write(bytes, 0, bytes.Length); 
    } 
} 

if(_headers.Count > 0) 
{ 
    request.Headers.Add(_headers); 
}//end if 

// we want to keep this open for a bit 
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
{ 
    // TODO: do something with the response 
}//end using 
+0

謝謝賈斯汀。 我試過這樣做,出於某種原因,我無法通過第一步。 我總是回到第一個URL,並且帖子不起作用,儘管當我手動執行時,一切似乎都正常。 你有這樣的代碼示例嗎? – charlie 2010-08-05 19:24:13

+0

@charlie,添加了代碼。這又是一個非常具體的我們如何做事。但它會告訴你如何設置請求,如果你需要改變任何值,你當然可以這樣做。很多時候,允許重定向屬性需要在帖子上設置爲false,以防止自動重定向轉化爲獲取,你失去了帖子。我經常發現自己做了一個帖子,發送到另一個頁面,所以你必須做一個帖子,獲取重定向網址並重新發布到該頁面。 HTTP提交可能有點棘手,可以採取一些工作來確保正確。 – Justin 2010-08-05 19:38:37

1

我要說硒,但如果你打算這樣做,內部我可能會做一些這樣的NUnit寫的測試,然後從web應用程序運行它們。

http://www.nunit.org/

在web-app但內心爲什麼?這就像在車內對汽車進行碰撞測試。

+0

+1我喜歡這個比喻。 – 2010-08-05 19:28:28

+0

好問題。答案是這樣的: 我正在爲巴士公司工作。我們與許多巴士供應商合作。當我們接到服務電話時,代理商需要向許多提供商查詢最便宜的價格。 因此,對於所有提供API的供應商而言,解決方案非常簡單。 但是,對於那些提供要求我們登錄才能獲得價格的網站,我們需要編寫這樣的應用程序。 現在:因爲我們的內部系統是作爲一個網絡應用程序編寫的,所以這個爬行應該是這個網絡應用程序的一部分... 奇怪的是一見鍾情,但在重新思考時非常有用... – charlie 2010-08-05 19:29:24

+1

我們是不是真的在測試網絡應用程序?也許改變你的問題,以反映你正在考慮從外部網站抓取數據以便在你的web應用程序中使用將是適當的? – Doon 2010-08-05 19:41:51