在进行网页自动化时我们做得最多的工作就是不停的往某个URL GET/POST数据并得到相应的Response,通过分析Response的结果再进行下一步操作,通过网页自动化我们可以做很多工作,比如去某个网站抓取我们想要的数据,批量注册,模拟人工操作网页,批量提交,去年12306网上订火车票的系统出来后相继开发出来的各种抢票工具就是这一网页自动化应用的最好注脚。非常幸运的是,.NET C#提供了强大的函数库可以轻易的完成这一作,但是现在我要发布的AliasNet将把这一工作变得更为简单。有我简单?一句话就OK。
总的来说:AliasNet,提供一种简单,方便,封装,统一的GET/POST方法。
1. AliasNet的基本使用
string response=new GetAndPostHelper().GETString("http://www.baidu.com") ;
OK,response里保存的就将是百度首页的HTML内容。
2. AliasNet的高级使用
GETAndPostHelper() helper=new GetAndPostHelper();//初始化HTTP的GETAndPostHelper
GETAndPostHelper() helper=new GetAndPostHelper(true);//初始化HTTPS的GETAndPostHelper
helper.SetCookies(CookieContainer cookies);//设置本次连接的Cookie
helper.SetCredential(userName,password);//设置本次连接的认证信息(这在内部网站里很有用)
helper.SetProxy(proxyIP,proxyPort);//设置本次连接的代理
helper.GETString(url);//GET数据,返回string
helper.GETBytes(url);//GET数据,返回byte[]
helper.POSTString(url,parameter);//POST数据,返回string
helper.POSTBytes(url,paremeter);//POST数据,返回byte[]
helper.DownloadFile(url,fileName);//将url内容保存为本地文件,这对下载图片网页等很有用
GET数据时,参数就连到URL里面作为QueryString传递到服务器,但是当POST数据时,我们需要显式的传递一个参数parameter,它是类Parameter的实体,其中类Parameter定义如下:
/// <summary> /// Parameter类,继承自 Dictionary<string, string>
/// 以Key-Value的形式保存GET/POST的数
/// </summary>
public class Parameters : Dictionary<string, string>
{
/// <summary>
/// 重写ToString方法,以QueryString的方式连接各值
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> pair in this)
{
sb.Append(string.Format("{0}={1}&", pair.Key, pair.Value));
}
if (sb.Length > 0)
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
}
可以看到Parameter就是一个string-string的字典,我们把需要POST的数据放到里面去就OK了。
3.GET/POST 响应数据的处理办法
一般来说我们GET/POST数据无非是两种需求,一是下载相应的文件(可以用helper.DownloadFile)实现 ,二是获取返回结果提取数据(可以用helper.GETString(POSTStrin))实现。现重点说说后者。
根据服务器的返回结果,我们可以把他们为以下三类:
(1)HTML
处理HTML字符串当然首推HtmlAgilityPack.dll 了,可以用HTMLDocumnet载入 HTML字符串,再用XPath搜索想要的节点,最后用HTMLNode的innerText,innerHTML,GetAttribute 等方法就可以很方便的得到数据。
(2)JSON
处理JSOn数据我最喜欢使用Newtonsoft.Json 来实例化一个实体类,然后操作类来实现。AliasNet提供了JsonClassBase基类来处理JSON数据,一般来说,分析JSON数据的结构并写出现应的.NET实体类,并让之继承自JsonClassBase基类,使用调用 JsonClassBase.FromJson<T>(string json)方法就可以把JSON数据轻易的转换为.NET实体类了。
(3)包括XML等的其它
4.实例:利用AliasNet从无忧代理上获取最新的代理
无忧代理是我喜欢上的几个代理网上,每隔几小时它都会更新当前最新最好用的代理IP和端口,所以我们可以用AliasNet来自动抓取代理信息。
下面的例子将会抓取http://www.51proxied.com/http_anonymous.html 即无忧代理的匿名HTTP代理
// <summary>
/// 从无忧代理网站得到当前最新的代理
/// </summary>
/// <param name="proxyUrl">代理Web URL</param>
/// <param name="regionFilter">过滤指定的region,不过滤使用""或null</param>
/// <returns>代理命令</returns>
public static List<Proxy> _51proxied_HttpProxy(string proxyUrl, string regionFilter)
{
string resultString = new GetAndPostHelper().GETString(proxyUrl);
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(resultString);
HtmlNode divNode = doc.GetElementbyId("tb");
HtmlNodeCollection tdNodesCollection = divNode.SelectNodes("//div/table//td");
List<HtmlNode> tdNodes = new List<HtmlNode>();
foreach (HtmlNode node in tdNodesCollection)
tdNodes.Add(node);
List<Proxy> proxy = new List<Proxy>();
for (int i = 0; i < tdNodes.Count / 4; i++)
{
string region = tdNodes[i * 4 + 3].InnerText.Trim();
if (string.IsNullOrEmpty(regionFilter) || region == regionFilter)
{
Proxy p = new Proxy();
p.IP = tdNodes[i * 4 + 1].InnerText.Trim(); ;
p.Port = int.Parse(tdNodes[i * 4 + 2].InnerText.Trim());
p.Region = region;
proxy.Add(p);
}
}
return proxy; }
这个方法我也封装成了ProxyFinder放到了AliasNet里面,一方面可以做为AliasNet使用的一个例子,一方面也算是额外的福利吧,反正我抓代理用得也蛮多的。
总结:
AliasNet现已托管到GitHub上并全面开源,感兴趣的可以访问:https://github.com/superliujian/AliasNet 或者联系我:liu_jian_china@qq.com
另外预告一下:简单自适应的轻量级数据库访问库AliasDB也已经开源,近期将公布。 AliasDB使得用户只需要提供一个连接字符串就可以运用统一的访问访问MySQL/SQLServer/Oracle/SQLite以及通过支持ODBC/OleDb 的所有数据库(比如Access), 而且,当你的数据库结构变化时,比如字段增删等,该访问仍然有效,不用再做任意的ORM,或者 自己写SQL语句或者 自己编写数据库实体。这在中小型系统中十分有用。