使用 WATiN 自动刮取 Orkut 好友的生日
通过使用此应用程序,Orkut 用户可以无误地向他们的朋友发送生日祝福信息,甚至无需登录 Orkut 网站
引言
通过使用此应用程序,Orkut 用户可以无误地向他们的朋友发送生日祝福信息,甚至无需登录 Orkut 网站。这就像在向 Orkut 朋友发送生日祝福信息时,无需错过最亲近的朋友的生日,从而消除了人与网站的交互。只需运行此应用程序,您就可以在几秒钟内完成这项工作。您可以设置一个时间,让此应用程序在预定义的时间每天运行。
实施
您需要在控制面板调度程序中以预定义的时间添加此应用程序。在预定义的时间,此应用程序将运行并执行您在 Orkut 中发送生日祝福信息时应该执行的所有操作。:) 如果我们运行此控制台应用程序,我们将看到一个 Internet Explorer 浏览器打开并自动化了整个手动过程。这不是很酷吗?:)
背景
我记得那些日子,我常常登录 Orkut 查看朋友的生日。如果有,我就会送上最好的祝福。但最困难的部分是记住朋友的生日(这是我的经验)。假设我们在某一天无法打开 Orkut(恰好是我朋友的生日),那么我们就会错过祝福朋友。如果第二天我们有机会登录 Orkut,那么我们需要发送带有“迟来的”字样的祝福。:( 然后有一天我想到我们需要一个可以消除我们痛苦情况的应用程序。这个应用程序应该在我的控制之下,在我手中,并且可以处理所有这些事情。这就像一台电脑代替我工作。在与我的想法、想法和知识搏斗了几个小时之后,我提出了一个想法,我可以开发一个可以按照我的想法行事的应用程序。这太棒了。:) 因此,我很乐意展示一个应用程序,它是我的知识/想法在 C#、.NET 和 WATIN 中的复制品。
什么是 WATiN
WATIN,发音为“What-in”,是“Web Application Testing in .NET”的缩写。WATiN 是一个工具包,用于在 Web 应用程序开发过程中自动化基于浏览器的测试。此自动化测试工具使用 C# 语言来驱动 Internet Explorer Web 浏览器。要了解更多关于 WATiN 工具包的信息,请参阅此链接。
使用方法
为了与 Orkut 网站交互,我使用了 WATIN 工具作为我的代码和 Orkut 网站之间的 API 交互。对于编程语言,我使用了 C# 和 .NET 2.0,我希望你们熟悉 WATiN。我更喜欢逐行解释代码,这样我们就可以了解如何将 WATiN 用于自动化目的以及其他目的,例如像 API 一样与其它网站交互。
流程图 (http://jawedm.blogspot.com)
- 打开一个新的 Internet Explorer 实例(可以处于可见模式)。
- 转到 http://www.orkut.com/。
- 使用预定义的电子邮件 ID 和密码登录。
- 移动到登录用户主页。
- 检查今天是否有朋友生日,如果有,则转到步骤 6,否则转到步骤 10
- 点击链接“留下一个便笺”并转到所选朋友的便笺簿。
- 输入预定义的生日消息/祝福并发布该便笺。
- 返回到登录用户主网页。
- 进一步检查下一个生日日期,如果今天是,则重复步骤 6 到 8。
- 点击 Orkut 网站的注销链接。
- 成功注销后,关闭浏览器。
现在让我们将以上步骤转化为代码。
- 打开 Visual Studio 并选择新项目作为控制台应用程序。(我假设您熟悉 Visual Studio 2005)
- 转到添加引用并添加 WATiN.core.dll 和 Nunitframework.dll 到您的项目中。
- 在您的代码文件中添加以下命名空间以访问 WATiN 类和方法。
using Watin.core; using NUnit.Framework
- 我正在使用 XML 文件来存储登录邮箱 ID、密码和生日祝福。起初我考虑使用 APPconfig 来存储数据信息,但我改变主意使用了 XML,因为 XML 非常易于维护和通过代码读取,最棒的是任何人都可以轻松使用它。
- 所以首先我们将编写代码来读取登录邮箱 ID、密码和生日祝福。
用于读取用户电子邮件 ID、密码和祝福便条的 XML 文件代码
//Start Reading Xml for Input data //String variable to store data from XML file. string[] UserInput=new string[3]; //Get the Current directory path string xmlPath = Environment.CurrentDirectory; //Get the xml path to read output xmlPath = xmlPath.Replace("bin\\Debug","UserInputData.xml"); XmlTextReader reader = new XmlTextReader(xmlPath); reader.Read(); int i=0; /*start reading the XML file for UserEmailid,UserPassword and Birthday wishes.*/ while (reader.Read()) { switch (reader.NodeType) { //Display the text in each element. case XmlNodeType.Text: //Console.WriteLine(reader.Value); //store the value in string UserInput[i] = reader.Value; i++; break; } } //Stop reading from XML file
- 现在我们实际的工作/代码将开始。在此部分中,我们将通过登录 Orkut 使用 WATiN 派生 Internet Explorer。我们将在隐形模式下创建一个新的 Internet Explorer 实例。这段代码将如下所示
//Make Internet Explorer run in invisible mode. IE.Settings.MakeNewIeInstanceVisible = false; //Open an Instance of Internet Explorer IE ie = new IE();
- 通过代码,我们将强制浏览器实例通过在地址栏中输入 http://www.orkut.com/ 来访问 Orkut 网站并执行前往操作。
// Type www.orkut.com in browser. ie.GoTo(https://www.orkut.com); ie.WaitForComplete(); //Verify that logout link exit. Assert.IsTrue(ie.Frame("orkutFrame").Link(Find.ByText("Logout")).Exists); //Click on logout link ie.Frame("orkutFrame").Link(Find.ByText("Logout")).Click(); ie.WaitForComplete(); // ie.Close();
- 现在在 Orkut 主页上,我们将向相应的邮箱 ID 字段和密码字段提供邮箱 ID 和密码。这些值已从 XML 中读取。我认为其余代码是不言自明的,因为我添加了注释,以便您可以清楚地了解代码。
using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using WatiN.Core; using NUnit.Framework; //using WatiN.Core.Interfaces; using System.Configuration; using System.Text.RegularExpressions; using System.Xml; using System.Xml.XPath; using System.Data; using System.Web; using System.Threading; using System.Runtime.InteropServices; //Author: Md.Jawed //date: 24th July 2009 //Description: This Application would sendout an Orkut scrap for Birthday wishes.; namespace OrkutBirthdayScrap { class OrkutBirthdayScrap { //A common use for a cross-process Mutex is to ensure //that only instance of a program can run at a time. //Mutex provides the same functionality as C#'s lock statement, //making Mutex mostly redundant. static Mutex mutex = new Mutex(false, "http://jawedm.blogspot.com"); [STAThread] static void Main(string[] args) { // Wait 3 seconds if contended – in case another instance // of the program is in the process of shutting down. if (!mutex.WaitOne(TimeSpan.FromSeconds(3), false)) { Console.WriteLine("Another instance of the app is running. Bye!"); return; } else { Console.WriteLine("Automatic Birthday Scrap to Orkut friends Using WATiN Is Running!!! Please visit http://jawedm.blogspot.com for more information"); //make the browser in invisible mode // IE.Settings.MakeNewIeInstanceVisible = false; //Open an Instance of IE IE ie = new IE(); //declare an string to store value from xml string[] UserInput = new string[3]; try { //Read from XML file //Get the Current directory path string xmlPath = Environment.CurrentDirectory; //Get the xml path to read out put xmlPath = xmlPath.Replace("bin\\Debug", "UserInputData.xml"); XmlTextReader reader = new XmlTextReader(xmlPath); reader.Read(); int i = 0; //start reading the XML file for UserEmailid, //UserPassword and Birthday wishes. while (reader.Read()) { switch (reader.NodeType) { // Do some work here on the data. case XmlNodeType.Text: //Display the text //in each element. //store value in variable after //reading from XML node by node. UserInput[i] = reader.Value; i++; break; } } } catch (Exception Gex) { ie.Close(); Console.WriteLine("Some problem has occured. Please Run this application once again"); } //Stop reading from XML file //IE.Settings.MakeNewIeInstanceVisible = false; //VERIFY THAT USER HAS NOT ALREADY LOGIN INTO ORKUT //iF YES THEN cLOSE THE PREVIOUS SESSION AND START NEW SESSION. try { // Type www.orkut.com in browser. ie.GoTo("https://www.orkut.com"); ie.WaitForComplete(); //Verify that logout link exit. Assert.IsTrue(ie.Frame("orkutFrame").Link (Find.ByText("Logout")).Exists); //Click on logout link ie.Frame("orkutFrame").Link(Find.ByText("Logout")).Click(); ie.WaitForComplete(); // ie.Close(); } catch (Exception ex) { // } try { //Type Your emailid in to emailid textbox. ie.TextField("Email").TypeText(UserInput[0]); //Provide your Password in password textbox. ie.TextField("Passwd").TypeText(UserInput[1]); //Click on signIn button to login into orkut. ie.Button(Find.ByName("signIn")).Click(); ie.WaitForComplete(); string VerifyUrl = ie.Url; //verify that login as successful. return true if (VerifyUrl == "http://www.orkut.co.in/Main#Home.aspx") { //Check that Birthday box exist on home page. bool res = ie.Frame("orkutFrame").Div("mbox"). Table(Find.ByIndex(2)).Exists; if (res) { //Remember the number of user exist in BirthdayBox. int numBirthdayFriend = 0; Div birthDayDiv = ie.Frame("orkutFrame"). Div("mbox").Table(Find.ByIndex(2)).Div (Find.ByClass("boxgrid")).Div(Find.ByIndex (numBirthdayFriend)); while ((ie.Frame("orkutFrame").Div("mbox"). Table(Find.ByIndex(2)).Div(Find.ByClass("boxgrid")). Div(Find.ByIndex(numBirthdayFriend)).Exists)) { if (ie.Frame("orkutFrame").Div("mbox"). Table(Find.ByIndex(2)).Div(Find.ByClass("boxgrid")). Div(Find.ByIndex(numBirthdayFriend)).Div (Find.ByIndex(1)). Link(Find.ByIndex(1)).Exists) { Assert.IsTrue(ie.Frame("orkutFrame"). Div("mbox").Table(Find.ByIndex(2)). Div(Find.ByClass("boxgrid")). Div(Find.ByIndex(numBirthdayFriend)). Div(Find.ByIndex(1)).Exists); //Check if any one has a birthday today or not Assert.AreEqual("leave a scrap", ie.Frame("orkutFrame").Div("mbox"). Table(Find.ByIndex(2)).Div (Find.ByClass("boxgrid")). Div(Find.ByIndex(numBirthdayFriend)). Div(Find.ByIndex(1)). Link(Find.ByIndex(1)).Text); //Click on leave scrap option to //leave a scrap to birthday buddy ie.Frame("orkutFrame").Div("mbox"). Table(Find.ByIndex(2)). Div(Find.ByClass("boxgrid")). Div(Find.ByIndex(numBirthdayFriend)). Div(Find.ByIndex(1)).Link(Find.ByIndex(1)). Click(); ie.WaitForComplete(); //Verify that we have landed at Scrap //book of birthday buddy page. Assert.IsTrue(ie.Frame("orkutFrame"). TextField("scrapText").Exists); //Type a Scrap to Birthday buddy. ie.Frame("orkutFrame").TextField("scrapText"). TypeText(UserInput[2]); //Post Scrap. ie.Frame("orkutFrame").Link(Find.ByText ("post scrap")).Click(); ie.WaitForComplete(); //Click on Home link to return back to //home page after leaving scrap for friend. ie.Frame("orkutFrame").Link(Find.ByText ("Home")).Click(); ie.WaitForComplete(); } numBirthdayFriend = numBirthdayFriend + 3; } } else { Console.WriteLine("Sorry Today you don't have any friend's birthday"); } ie.Frame("orkutFrame").Link(Find.ByText("Logout")).Click(); ie.WaitForComplete(); ie.Close(); } else { //Sorry Login Unsuccessful. ie.Close(); } } catch (AssertionException Aex) { ie.Close(); } catch (WatiN.Core.Exceptions.ElementNotFoundException Wex) { ie.Close(); } catch (Exception ex) { Console.WriteLine("Some problem has occured. Please Run this application once again"); ie.Close(); } Process.GetCurrentProcess().Kill(); } mutex.ReleaseMutex(); } } }
关注点
连续点击 EXE 会打开多个浏览器和命令窗口(稍后会发生超时异常)。 为避免此问题:我使用了 Mutex 的概念。跨进程 Mutex 的常见用途是确保程序只能运行一个实例。Mutex 提供与 C# 的 lock
语句相同的功能,这使得 Mutex 在大多数情况下是多余的。
我学到了什么?
我从这篇文章中学到的是,WATiN 不仅仅用于自动化目的。我们也可以将其用于驱动程序/API 接口。更重要的是,从现在开始,这个应用程序将满足我们的 Orkut 需求。
结论
阅读本文后,我希望我们应该知道如何使用 WATiN 框架来测试 Web 应用程序以及如何将其用于 API 目的。我认为我们可以用它进行密集的 UI 和功能测试,当然也可以用于 API 或作为驱动程序,最棒的是,通过使用此应用程序,我们可以避免登录 Orkut 发送生日祝福。
即将推出的应用
- 如何使用 WATiN 从 DIGITE 获取/生成缺陷状态、已记录项以及更多信息,并通过电子邮件将这些生成的报告发送给一群人。
- 我已自行开发了一个使用 WATiN 的自动化应用程序,并将其命名为 “一个使用 WATiN 的自动化功能图形用户界面测试应用程序”。目前我正在我的项目中将此应用程序用于自动化。
注意: 我还在这个 OrkutBirthdayScrap.zip 文件中包含了 ReadMe 文件,它会指导您如何使用此应用程序。
您可以在我的博客上找到更多和最近开发的 WATiN 应用程序 @ http://jawedm.blogspot.com。
历史
- 2009 年 8 月 29 日:初始发布
- 2009年8月31日:上传了安装文件并修改了源代码
- 2009年9月1日:上传了具有隐形模式功能的安装文件