C#屏幕刮ASP.NET Web窗体页 – POST请求不完全工作
请忍受我这个稍长的描述,但我有一个奇怪的问题,C#屏幕刮ASP.NET Web表单页面.我想要做的步骤如下:
1)通过HTTPS使用基本身份验证来保护站点,所以我需要正确登录. 2)我在页面上执行GET请求来检索__VIEWSTATE值(如果我没有设置这个东西,那么事情什么都不做)! 3)登录后,会有几个表单字段来完成,然后提交一个提交按钮,POST的形式就是服务器 4)当提交按钮被按下时,表单被POST到服务器,响应是相同的页面和表单,但现在在表单底部有一个额外的小HTML表格,需要一些数据. 我已经设法使用WebClient类对登录名和表单进行排序.我使用fiddler(和firebug)来检查在正常使用浏览器完成表单时发送的POST字段值.我可以从POST请求中成功获得响应,并显示正如预期在表单下方的数据表.然而,问题是,尽管表中填有数据,但是它填充了我不期望的数据.出现的数据是,如果我在浏览器中正常完成表单,但是将一个特定参数(下拉列表)设置为与将POST请求传递给服务器不同的值.我已经确认使用fiddler和firebug,我正在传递完全相同的POST参数,正常使用Web浏览器完成的表单发送.我现在完全坚持为什么这个参数不被服务器’考虑’? 一个区别是这个特定的控件是一个选择列表,它在更改时执行页面重新加载或“回发”.然而,除了稍后在表单中更改其他一些选择列表内容之外,这似乎并没有做任何事情. 我想我正在问有没有什么我会失踪,会导致这个?我完全把我的头发撕掉了.谁能帮忙?我已经发布了下面的代码(地址和参数被隐藏了隐私). // a place to store the html string responseBody = ""; // create out web client to handle the request using (WebClient webClient = new WebClient()) { // space to store responses from the remote site byte[] responseBytes; // site uses basic authentication over HTTPS so we'll need to login CredentialCache credentials = new CredentialCache(); credentials.Add(new Uri(Url),"Basic",new NetworkCredential(Username,Password)); // set the credentials in the web client webClient.Credentials = credentials; // a place for __VIEWSTATE string viewState = ""; // try and get __VIEWSTATE from the web site try { responseBytes = webClient.DownloadData(Url); viewState = GetHtmlInputValue(Encoding.UTF8.GetString(responseBytes),"__VIEWSTATE"); } catch (Exception e) { bool cancel = false; ComponentMetaData.FireError(10,"Read web page data","Error whilst trying to get __VIEWSTATE from web page: " + e.Message,"",out cancel); } // add our POST parameters (don't forget the __VIEWSTATE or it won't work as its an ASP.NET web page) NameValueCollection requestParameters = new NameValueCollection(); // add ASP.NET fields requestParameters.Add("__EVENTTARGET",__EVENTTARGET); requestParameters.Add("__EVENTARGUMENT",__EVENTARGUMENT); requestParameters.Add("__LASTFOCUS",__LASTFOCUS); // add __VIEWSTATE requestParameters.Add("__VIEWSTATE",viewState); // all other form parameters requestParameters.Add("btnSubmit",btnSubmit); /* I've hidden the rest of the parameters hidden for privacy just in case */ // see if we can connect and get data try { // set content type webClient.Headers.Clear(); webClient.Headers.Add("Content-Type","application/x-www-form-urlencoded"); // 'POST' the form data using web client and hope we get a response responseBytes = webClient.UploadValues(Url,"POST",requestParameters); // transform the response to a string responseBody = Encoding.UTF8.GetString(responseBytes); } catch (Exception e) { bool cancel = false; ComponentMetaData.FireError(10,"Error whilst trying to connect to web page: " + e.Message,out cancel); } } 请忽略“ComponentMetaData”引用,因为这是SSIS脚本源的一部分. 任何想法或帮助将不胜感激 – 欢呼声! RE:感谢快速的回应,我可以对这些评论说的是… 有一个普通的ASP会话cookie,但cookie中没有值(当然,除了会话ID),我认为网站使用基本身份验证而不是表单身份验证我可以忽略cookie – 当我进入站点和获取数据返回这是可以的.我想这是值得一试,但我不得不只是改变代码来使用WebRequest类方法… 对于选择列表javascript,没有JavaScript在页面加载后更改选择列表的值.选择列表中唯一的JavaScript是一个onchange事件来做一个“回发”,只是在最后的POST中似乎更改了表单上的一些空白的其他选择列表.注意:生成POST请求时,包括所有POST参数,即使它们为空,并且还包括所有“web表单”特殊字段,如__VIEWSTATE,__EVENTTARGET等… 我不是Web表单的专家(MVC人自己),但网络形式的“引擎”还有什么期待?我已经为’application-type’的’application-x-www-form-urlencoded’发送了1个标题,但是我已经尝试过设置其他文件,例如从原始POST复制’User-Agent’头,但是最终与我从服务器得到一个500错误,不知道为什么会发生? 以下是“GetHtmlInputValue”的代码,它有点简单/基本,可以做得更好,但是: private string GetHtmlInputValue(string html,string inputID) { string valueDelimiter = "value=""; int namePosition = html.IndexOf(inputID); int valuePosition = html.IndexOf(valueDelimiter,namePosition); int startPosition = valuePosition + valueDelimiter.Length; int endPosition = html.IndexOf(""",startPosition); return html.Substring(startPosition,endPosition - startPosition); } 解决方法
如果我正确理解你的意见,那么在下拉菜单中选择一个项目将导致POST被执行,并且服务器改变窗体另一部分中的可用选项.然后,服务器将在__VIEWSTATE字段值中包含下拉列表的当前值.
执行抓取时,应确保__VIEWSTATE包含所需的下拉列表值.要进一步调查,尝试从服务器decode the viewstate,并查看哪些值被发回. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |