要抓取某个网站的数据,但是该网站不提供列表,只提供了一个按分类查询的功能。
每次查询要先提供近40K(相当的大了,主要是因为 __VIEWSTATE 这个参数,.NET网站都有这个东东)的数据到网站,然后在 302 跳转到某个页面上。
昨天我耗了N长时间在这个上面,我把所有该发送的数据都发送了,但是一直没有发生 302 跳转。
跟踪了很长时间,我发现在 302 跳转之前的那个 Response 发送回来一个名为 ASP.NET_SessionId 的 cookie ,我认为是在请求的时候,没有把这个 cookie 给发送出去的原因,于是就想着怎么在请求的时候,不自动 redirect ,这样就可以在 response 的时取回这个 cookie 了(事实上跟本就没有发生重定向),接着在请求要重定向的地址。。。于是:
req.AllowAutoRedirect = false;
但是结果还是一样, response.StatusCode = OK, 跟本就不是 302
后来我又想,得不到这个 sessionID,我就手动给它加个吧:
Cookie cookSession = new Cookie("ASP.NET_SessionId" , "2fohl0qqvaxkyc450cmpqa2k");//这个值是从抓包软件里取得的。
cookSession.Domain = "www.nzsport.co.nz/";
cookSession.HttpOnly = true;
cookSession.Path = "/";
cookies.Add(cookSession);
req.CookieContainer = new CookieContainer();
req.CookieContainer.Add(cookies);
运行后,结果还是一样。。。
在后来,认真看了看抓包结果,发现 request 的 Content-Type 是
multipart/form-data; boundary=---------------------------491299511942
POST 的数据原始格式是:
-----------------------------491299511942
Content-Disposition: form-data; name="__EVENTTARGET"
-----------------------------491299511942
Content-Disposition: form-data; name="__EVENTARGUMENT"
。。。
。。。
-----------------------------491299511942--
于是按照着这个格式重新组织数据:
Dictionary<string , string> postDatas = new Dictionary<string , string>();
postDatas.Add("__dnnVariable" , dnnVariable);
postDatas.Add("__EVENTARGUMENT" , "");
postDatas.Add("__EVENTTARGET" , "");
postDatas.Add("__LASTFOCUS" , "");
postDatas.Add("__VIEWSTATE" , viewState);
。。。
。。。
string postData = "";
foreach( string item in postDatas.Keys ) {
postData += string.Format("-----------------------------491299511942\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n",item, postDatas[item]);
//postData += string.Format("{0}={1}&",item, System.Web.HttpUtility.UrlEncode( postDatas[item] ));
}
postData += "-----------------------------491299511942--";
req.ContentType = "multipart/form-data; boundary=-----------------------------491299511942";
运行之后,仍然没有成功,在认真比较一下,发现
multipart/form-data; boundary=---------------------------491299511942 中 boundary= 后面的部分 其实是比 上面 foreach 段里的那个 要少两个中线( - ),改过来就可以了。(少两个中线才是正确的,不要误解。。。)
至于一开始用 req.ContentType = "application/x-www-form-urlencoded"; 没有成功,是因为没有对 post 的数据进行 UrlEncode ,加上 UrlEncode 就行了。
postData += string.Format("{0}={1}&",item, System.Web.HttpUtility.UrlEncode( postDatas[item] ));
每次查询要先提供近40K(相当的大了,主要是因为 __VIEWSTATE 这个参数,.NET网站都有这个东东)的数据到网站,然后在 302 跳转到某个页面上。
昨天我耗了N长时间在这个上面,我把所有该发送的数据都发送了,但是一直没有发生 302 跳转。
跟踪了很长时间,我发现在 302 跳转之前的那个 Response 发送回来一个名为 ASP.NET_SessionId 的 cookie ,我认为是在请求的时候,没有把这个 cookie 给发送出去的原因,于是就想着怎么在请求的时候,不自动 redirect ,这样就可以在 response 的时取回这个 cookie 了(事实上跟本就没有发生重定向),接着在请求要重定向的地址。。。于是:
req.AllowAutoRedirect = false;
但是结果还是一样, response.StatusCode = OK, 跟本就不是 302
后来我又想,得不到这个 sessionID,我就手动给它加个吧:
Cookie cookSession = new Cookie("ASP.NET_SessionId" , "2fohl0qqvaxkyc450cmpqa2k");//这个值是从抓包软件里取得的。
cookSession.Domain = "www.nzsport.co.nz/";
cookSession.HttpOnly = true;
cookSession.Path = "/";
cookies.Add(cookSession);
req.CookieContainer = new CookieContainer();
req.CookieContainer.Add(cookies);
运行后,结果还是一样。。。
在后来,认真看了看抓包结果,发现 request 的 Content-Type 是
multipart/form-data; boundary=---------------------------491299511942
POST 的数据原始格式是:
-----------------------------491299511942
Content-Disposition: form-data; name="__EVENTTARGET"
-----------------------------491299511942
Content-Disposition: form-data; name="__EVENTARGUMENT"
。。。
。。。
-----------------------------491299511942--
于是按照着这个格式重新组织数据:
Dictionary<string , string> postDatas = new Dictionary<string , string>();
postDatas.Add("__dnnVariable" , dnnVariable);
postDatas.Add("__EVENTARGUMENT" , "");
postDatas.Add("__EVENTTARGET" , "");
postDatas.Add("__LASTFOCUS" , "");
postDatas.Add("__VIEWSTATE" , viewState);
。。。
。。。
string postData = "";
foreach( string item in postDatas.Keys ) {
postData += string.Format("-----------------------------491299511942\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n",item, postDatas[item]);
//postData += string.Format("{0}={1}&",item, System.Web.HttpUtility.UrlEncode( postDatas[item] ));
}
postData += "-----------------------------491299511942--";
req.ContentType = "multipart/form-data; boundary=-----------------------------491299511942";
运行之后,仍然没有成功,在认真比较一下,发现
multipart/form-data; boundary=---------------------------491299511942 中 boundary= 后面的部分 其实是比 上面 foreach 段里的那个 要少两个中线( - ),改过来就可以了。(少两个中线才是正确的,不要误解。。。)
至于一开始用 req.ContentType = "application/x-www-form-urlencoded"; 没有成功,是因为没有对 post 的数据进行 UrlEncode ,加上 UrlEncode 就行了。
postData += string.Format("{0}={1}&",item, System.Web.HttpUtility.UrlEncode( postDatas[item] ));
| < Prev | Next > |
|---|
Last Updated ( Saturday, 31 October 2009 14:24 )



