使用分页刮取ASP.NET网站

我试图刮一个基本的asp.net目录网站,其中有分页。

该网站有50多个页面,在任何一个页面上最多包含10个分页链接。

我正在使用fiddler来帮助复制使用浏览器发布的所有参数,变量,表单域,cookie等。 我在两个post之间看到的唯一区别是__EVENTVALIDATION值。

使用HttpWebRequest我总是拥有相同的价值,而通过浏览器每次点击都会有变化。

使用HttpWebRequest我正确地获得了10个第一页,但是以下所有页面都将我重定向到主页。 Bellow是回发javascript,对于前10个之后的链接总是相同的。

 javascript:__doPostBack('CT_Main_2$gvDirectorySearch$ctl53$ctl00$ctl11','') 

任何想法为什么__EVENTVALIDATION不会随着HttpWebRequest而改变?

根据您的描述,它听起来像一个anti-forgery tokenanti-forgery token用于防止cross-site request forgery (XSRF)攻击。

对于一个利用反伪造令牌的网站,它通常会在客户端的浏览器中设置一个cookie,并且它会期望与正在发布的表单中的参数具有相同的标记。

要克服它,您需要在后续请求中发送服务器设置的令牌,您还需要扫描HTML表单以获取相同的令牌,并将其包括在内。


编辑

所以我深入挖掘并创建了一个ASP.NET WebForms站点并尝试复制您的问题,但无法在每个请求中设法提取__EVENTVALIDATION字段。

不过,如果您发现任何有用的话,这是我的代码……

 void Main() { string eventValidationToken = string.Empty; var firstResponse = this.Get(@"http://localhost:7428/Account/Login"); firstResponse.FormValues["ctl00$MainContent$Email"] = "email@example.com"; firstResponse.FormValues["ctl00$MainContent$Password"] = "password"; string secondRequestPostdata = firstResponse.ToString(); var secondResponse = this.Post(@"http://localhost:7428/Account/Login", secondRequestPostdata); Console.WriteLine (firstResponse.FormValues["__EVENTVALIDATION"]); Console.WriteLine (secondResponse.FormValues["__EVENTVALIDATION"]); } public FormData Get(string uri) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:7428/Account/Login"); using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { return new FormData(reader.ReadToEnd()); } } public FormData Post(string uri, string postContent) { byte[] formBytes = Encoding.UTF8.GetBytes(postContent); var request = (HttpWebRequest)WebRequest.Create("http://localhost:7428/Account/Login"); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = formBytes.Length; using (Stream stream = request.GetRequestStream()) { stream.Write(formBytes, 0, formBytes.Length); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { return new FormData(reader.ReadToEnd()); } } public class FormData { public FormData(string html) { this.Html = html; this.FormValues = new Dictionary(); this.FormValues["__EVENTTARGET"] = this.Extract(@"__EVENTTARGET"); this.FormValues["__EVENTARGUMENT"] = this.Extract(@"__EVENTARGUMENT"); this.FormValues["__VIEWSTATE"] = this.Extract(@"__VIEWSTATE"); this.FormValues["__VIEWSTATEGENERATOR"] = this.Extract(@"__VIEWSTATEGENERATOR"); this.FormValues["__EVENTVALIDATION"] = this.Extract(@"__EVENTVALIDATION"); this.FormValues["ctl00$MainContent$Email"] = string.Empty; this.FormValues["ctl00$MainContent$Password"] = string.Empty; this.FormValues["ctl00$MainContent$ctl05"] = "Log in"; } public string Html { get; set; } private string Extract(string id) { return Regex.Match(this.Html, @"id=""" + id + @""" value=""([^""]*)") .Groups[1] .Value; } public Dictionary FormValues { get;set; } public override string ToString() { var formData = this.FormValues.Select(form => HttpUtility.UrlEncode(form.Key) + "=" + HttpUtility.UrlEncode(form.Value)); return string.Join("&", formData); } }