c#自动向网页Post信息并提取返回的信息

来源:互联网 发布:apache分32位和64位吗 编辑:程序博客网 时间:2024/05/21 13:54

1、 打开一家航空运输公司的查询网页,如http://www.skyteamcargo.com/en/tracking/,该页面有两个文本框,供用户输入业务代码,如180-36898035,

2、 然后单击“Go”按钮后,下一个页面显示查询出来的结果

现在要求以上步骤都用程序自动实现,并把查询结果提取出来,以备后面进一步处理。
要完成这样的功能,首先要解决以下几个问题:

l 能够用程序在后台将数据Post到目标网页

l 能接收到对方返回的HTML结果页面

l 能够分析该页面,并将需要的结果提取出来

经过一番研究和实验,我解决了以上几个问题,下面分别描述。

1. 用程序将指定数据Post到目标网页,并接收结果网页

我先用一个网络嗅探器来捕获用IE手工查询时浏览器和对方网页的HTTP协议交互过程,这里推荐用Ultra Network Sniffer,它有个Connection Monitor功能,可以监视某个程序的所有连接,这样就避免了其他无关数据包的干扰。如图

当在查询页面里输入数据后,点击“Go”按钮,嗅探器捕捉到的数据包如下图

请注意第三行,有一个Post数据包,这个就是我们需要的,

它所发送的网页地址为:http://www.skyteamcargo.com/en/tracking/tra_result.php

它所Post的数据为:awbpre=180&awbnum=36898035&x=17&y=9

很显然,180和36898035是可以替换的,而且要注意的是发送的目标网页不再是我们在浏览器里直接输入的初始页面http://www.skyteamcargo.com/en/tracking/了

下面我们用程序来发送这段数据,代码如下

public static string GetPage(string url, string postData,string encodeType,out string err)

     {

         Stream outstream = null;

         Stream instream = null;

         StreamReader sr = null;

         HttpWebResponse response = null;

         HttpWebRequest request = null;

         Encoding encoding = Encoding.GetEncoding(encodeType);

byte[] data = encoding.GetBytes(postData);

// 准备请求...

try

         {   

// 设置参数

              request = WebRequest.Create(url) as HttpWebRequest;

              CookieContainer cookieContainer = new CookieContainer();

              request.CookieContainer = cookieContainer;

              request.AllowAutoRedirect = true;

              request.Method = "POST";

              request.ContentType = "application/x-www-form-urlencoded";

              request.ContentLength = data.Length;

              outstream = request.GetRequestStream();

              outstream.Write(data,0,data.Length);

              outstream.Close();

//发送请求并获取相应回应数据

              response = request.GetResponse() as HttpWebResponse;

//直到request.GetResponse()程序才开始向目标网页发送Post请求

              instream = response.GetResponseStream();

              sr = new StreamReader( instream, encoding );

//返回结果网页(html)代码

string content = sr.ReadToEnd();

              err = string.Empty;

return content;

         }

catch(Exception ex)

         {

              err = ex.Message;

return string.Empty;

         }

}

上面的代码很好懂,就不多费口水了,只谈几点要注意的问题:

如果你的程序需要保留SessionID,如ASP.NET中的那个SessionID。比如说自动登录后,可能还要后继的处理,则你需要在向下一个页面发送请求之前将前一个request返回的cookieContainer赋值给新的request,因为在cookieContainer中保留了一个叫做ASPNETSessionID的Cookie。

如果你Post的目标页面是ASP.NET页面,则一般在要提交的Form里都有一个__ViewState隐藏Input字段,一个服务器返回的网页源码的ViewState的例子如下,

         value="dDwtMzg4MDA0NzA7Oz7+jHQ0vF37/ga2CitRkQ3sfg+ePg==" />

然而在嗅探器中捕捉到的Post数据是:

__VIEWSTATE=dDwtMzg4MDA0NzA7Oz7%2BjHQ0vF37%2Fga2CitRkQ3sfg%2BePg%3D%3D&UserName=admin&Password=123&Submit=Button0

请大家注意,这里ViewState的数据和前面的有点不一样,差别是其中的”+/=”等符号都被转成了%2B,%2F,%3D等,这其实将ViewState的值进行了URL编码,大家可以用System.Web.HttpUtility.UrlEncode()方法来做这种转换

当然,如果你只需要对页面做一次性访问,则大可不必理会这些,只用根据嗅探器捕获的结果来发送数据就可以了,但是如果你需要根据页面返回的ViewState值动态处理,则需要注意这一点。

2. 从HTML网页代码中提取信息

要从HTML网页中提取信息,首先得将网页代码格式化成XML形式的文件,然后可以用XPath很方便的提取出自己想要的信息,要将HTML格式化为XML形式,目前有几个选择

1、 Chris Lovett的SgmlReader:

http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=b90fddce-e60d-43f8-a5c4-c3bd760564bc

2、 Simon Mourier的.NET Html Agility Pack

http://blogs.msdn.com/smourier/archive/2003/06/04/8265.aspx

我选择了SgmlReader, 通过实际使用,发现SgmlReader也不是尽善尽美,格式化出来的XML有时候嵌套关系会搞错,但即使这样,根据他格式化出来的文本,用来提取数据也足够了。

public static DataSet ParsePage(string pageContent, string xpath, out string err)

     {

         err = string.Empty;

string pageContent = this.tbHTML.Text;

     StreamReader streamReader = null;

     StringWriter strWriter = null;

     SgmlReader sgmlReader = null;

     XmlTextWriter xmlWriter = null;

try

     {

              sgmlReader = new SgmlReader();

                   sgmlReader.DocType = "HTML";

                   sgmlReader.InputStream = new StringReader(pageContent);

                   strWriter = new StringWriter();

                   xmlWriter = new XmlTextWriter(strWriter);

                   xmlWriter.Formatting = Formatting.Indented;

while (sgmlReader.Read())

                   {

if (sgmlReader.NodeType != XmlNodeType.Whitespace)

                       {

                            xmlWriter.WriteNode(sgmlReader, true);

                       }

                   }

string wellFormedHTML = strWriter.ToString();

this.tbHTML.Text = wellFormedHTML;

string xpath = this.tbXPath.Text;

                   XPathDocument doc = new XPathDocument(new StringReader(wellFormedHTML));

                   XPathNavigator nav = doc.CreateNavigator();

                   XPathNodeIterator nodes = nav.Select(xpath);

while (nodes.MoveNext())

                   {

this.tbResult.Text += nodes.Current.Value+"/n";

                   }

              }

catch (Exception exp)

              {

string err = exp.Message;

                   MessageBox.Show("错误:"+err);

         }

}

}

根据上面的代码来看,目前主要的问题就是要设置正确的XPath了,Code Project上有篇文章提供了一个简单的XPath查询工具,我对其作了一些修改,主要增加了在节点的正文中搜索某个字符串的功能,方便大家根据获得的HTML页面查询XPath

Debugging XPath Queries : http://www.codeproject.com/dotnet/xpath_visualizer.asp

例如下面是一个根据查询出来的结果格式化后的XML文本片断,该信息的XPath为

//div[@class=”content”]/DIV[@id=”tblwithbck”]/TABLE/TR/TD/TABLE/TR/TD/DIV[@class=”data”]

需要注意的是XPath中的每个路径是大小写敏感的,我就是一开始没注意这个问题,犯了些错误。

2 piece(s) 42 K departed on flight KE6316/04JUN from PVG to ICN


Actual Time of Flight-Departure : 19:20


Scheduled Time of Flight-Arrival : 21:55

2 piece(s) 42 K departed on flight 9S0910/06JUN from ICN to DFW


Actual Time of Flight-Departure : 22:15


Scheduled Time of Flight-Arrival : 05:35+1

2 piece(s) 42 K departed on flight 3A3617/07JUN from DFW to ELP


Actual Time of Flight-Departure : 22:00

2 piece(s) 42 K arrived in ELP from flight 3A3617


Scheduled arrival : 08 JUN


Goods checked in at : 11:00

Arrival docs delivered for 2 piece(s) 42 K on 09 JUN at 09:48 in ELP

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 砂锅烫到手很痛怎么办 低压高怎么办吃什么好 熬夜多了掉头发怎么办 复蚕丝被洗过了怎么办 买了梅邦虫草精怎么办 医院不开转院证怎么办 棕垫一直有味道怎么办 棕子床垫味道大怎么办 羊绒大衣洗坏了怎么办 无痕内裤开胶了怎么办 衬衫洗了会缩水怎么办 脾虚引起的眼袋怎么办 沙漠玫瑰根烂了怎么办 多肉种子不发芽怎么办 多肉植物掉叶子怎么办 白色衣服染了蓝色怎么办 白色的衣服染色了怎么办 白毛衣染上金纺怎么办 白色的衣服变黄怎么办 白衣服84漂黄了怎么办 真丝的衣服皱了怎么办 衣服领子洗大了怎么办 真丝围巾洗皱了怎么办 真丝裙子洗花了怎么办 衣服晒得掉色了怎么办 衣服上出现霉点怎么办 校服后面的霉点怎么办 被子潮了有味道怎么办 涨奶堵塞有硬块怎么办 军训裤子腰大了怎么办 猫总是在床上尿怎么办 被子盖厚了上火怎么办 猫在被子上撒尿怎么办 脸上被辣椒辣了怎么办 压缩袋衣服皱了怎么办 新买的枕头太高怎么办 刚买的枕头太高怎么办 喝了过期的中药怎么办 喝了坏了的中药怎么办 德运奶粉过期了怎么办 手机膜里的气泡怎么办