2010-08-05 142 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