【问题标题】:Testing a website using C# [closed]使用 C# 测试网站 [关闭]
【发布时间】:2010-08-05 19:16:16
【问题描述】:

伙计们,

我需要完成一些复杂的网络爬取。

简单来说目标:登录到一个页面,在一些文本字段中输入一些值,单击提交,然后从检索到的页面中提取一些值。

最好的方法是什么?

  1. 一些单元测试 3rd 方库?
  2. 在 C# 中手动爬取?
  3. 也许有专门为此准备的库?
  4. 还有其他方法吗?

这需要在网络应用中完成。

非常感谢您的帮助。

【问题讨论】:

    标签: c# web-crawler http-post


    【解决方案1】:

    等待。

    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.
    

    编辑 -

    在从网络浏览器中阅读有关执行此操作的编辑后,您可能会考虑使用 WebRequest 和 HTML Agility Pack 来验证您返回的内容:

    网络请求:

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

    HTML 敏捷包:

    How to use HTML Agility pack

    【讨论】:

    • 哦,对不起.. 我忘了说:我需要在网络应用程序中完成此操作。这就是为什么我不能使用 watin。
    • 啊,刚刚看到网络应用编辑..这对那个没有帮助..哈哈
    • 感谢伊恩的尝试。我很感激。还有其他方向吗?
    • 我检查了 HTML Agility Pack,但不知道从哪里获取它。我的意思是,我看到了他们的示例,它允许实际查询页面上的 XPATH 结构,但不确定这如何使我更接近目标,这涉及更多的东西,例如 HTTP POST、移动 CookieContainer 等等。 ..
    【解决方案2】:

    不确定它将如何在 Web 应用程序中工作,但您是否考虑过尝试HtmlUnit?我认为它应该可以正常工作,因为它基本上是一个无头网络浏览器。

    Steven Sanderson 有一个blog post about using HtmlUnit in .NET code

    【讨论】:

    • 似乎让我离我们的目标更近了...我会研究几分钟并在此处发布结果。谢谢!很快就和你谈谈。
    • 这是我卡住的地方:需要包含来自 Java 的 IKVM.OpenJDK.Security.dll 才能在 >net 中使用,但我不知道该怎么做......
    • 不,您不需要来自 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。
    • 所有其他 DLL [除了 .Security] Steven Sanderson 在他的博客 [上面的链接] 的下载中已经准备好在 .Net 中使用的 COM 对象。但是当我从 IKVM 下载目录下载 .Security DLL 时,它会抛出这个:'无法加载文件或程序集'IKVM.OpenJDK.Security,Version=0.42.0.3,Culture=neutral,PublicKeyToken=13235d27fcbfff58'或其依赖项之一。找到的程序集的清单定义与程序集引用不匹配。 (来自 HRESULT 的异常:0x80131040)'嗯......也许是因为 DLL 没有为 .Net 准备好?
    • 所有 IKVM.OpenJDK.* 都是 .NET 程序集,因此它们不需要为 .NET 做任何准备。我认为最好的办法是追溯您的步骤并确保您包含上述所有程序集。如果 Sanderson 博客上的下载对你有用,那么我认为你不需要自己下载 IKVM,因为 Sanderson 的下载是最新的。
    【解决方案3】:

    如果您正在寻找更轻量级的东西,请尝试 SimpleBrowser for .Net - 在 Github 上开源。

    https://github.com/axefrog/SimpleBrowser

    【讨论】:

    • 看起来很有希望使用 jQuery 之类的选择器的功能
    【解决方案4】:

    我本来想说 Selenium,但如果你要在内部进行,我可能会使用 NUnit 之类的东西来编写测试,然后从 Web 应用程序运行它们。

    http://www.nunit.org/

    为什么在网络应用程序中?这就像在车内对汽车进行碰撞测试。

    【讨论】:

    • 好问题。答案是这样的:我在一家巴士公司工作。我们与许多巴士供应商合作。当我们接到服务电话时,代理商需要与许多供应商核实最便宜的价格是多少。因此,对于所有为我们提供 API 的提供商来说,解决方案很简单。但是,对于那些提供需要我们登录才能获得价格的网站的人,我们需要编写这样的应用程序。现在:由于我们的内部系统是作为网络应用程序编写的,因此这种爬取应该是该网络应用程序的一部分……乍一看很奇怪,但重新考虑时非常有用……
    • 你不是真的在测试网络应用吗?也许改变您的问题以反映您正在查看从外部网站抓取数据以在您的 web 应用程序中使用是合适的?
    【解决方案5】:

    如果您知道表单 post 值应该输入和输出的内容,您可以在 C# 中创建一个使用 HttpWebRequest 并发布到页面并解析结果的应用程序。这段代码是高度专业化的,供我自己使用,但你应该能够对其进行调整,让它做你想做的事。它实际上是一个更大的类的一部分,它允许您向其中添加发布/获取项目,然后为您提交一个 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
    

    【讨论】:

    • 谢谢贾斯汀。我试过这样做,由于某种原因,我无法通过第一步。我总是回到第一个 URL,并且帖子不起作用,即使当我手动执行时,一切似乎都正常。你有这方面的代码示例吗?
    • @charlie,添加了代码。同样,这非常具体到我们如何做事。但它向您展示了如何设置请求,如果您需要更改任何值,您当然可以这样做。很多时候,需要在帖子上将允许重定向属性设置为 false,以防止自动重定向变成获取并且您丢失帖子。我经常发现自己在做一个帖子,然后发送到另一个页面,所以你必须做一个帖子,获取重定向 URL 并再次发布到该页面。 HTTP 提交可能有点棘手,可能需要一些工作才能正确完成。
    猜你喜欢
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-28
    • 2015-11-21
    • 2013-12-17
    相关资源
    最近更新 更多