腾讯的拍拍网今日特价秒杀器--拍拍抢拍精灵实现过程--核心代码 by wyw308 / http://blog.csdn.net/wyw308
结合网络上前辈的宝贵经验,配合自己手动抓包分析。发现:
1:再进入倒计时时无论你点刷新有多快,其实页面都是5秒钟才给你提交一次。(可恶的拍拍,蒙了多少朴实鞋童,没分析之前按一到抢拍时间就狂点“刷新”按钮,现在才明白白瞎了)
2:腾讯的验证码来源于第三方服务器,其Set-Cookie并不是保存到本地的cookie,它是一个标志为httponly的cookie,只存储在标头。具体的验证码地址为专门服务器http://captcha.qq.com/getimage,因此可以进行cookie欺骗。
开发思路:
1:考虑人性化效果,利用webBrowser模拟页面登陆进入抢拍界面,利用webBrowser动态生成主要cookie及post数据元素。
2:手动提前获取多组验证码,保存到容器。
3:时间一到,利用提前获取的验证码,手工构造post数据以及cookie数据,利用httpwebrequest进行底层自动提交。
4:查看返回结果。
[这里只是给出了思路及核心实现代码,细节优化略]
一:取宝贝的开始剩余时间:注意,拍拍网对于宝贝的开始抢拍时间有延时处理,比如倒计时到了3,2,1,娘的,他不开始,又重新回到了3,3,3。。。然后忽然就开始了,这里需要进行一些技术处理,如自己延时或者直接网上核对,但各有利弊,具体方法大家自己想。这里只给取倒计时by/ http://blog.csdn.net/wyw308
///
/// 返回倒计时毫秒by/ http://blog.csdn.net/wyw308
///
///
private double RemainTime(out string jsonstr)
{
Random ran = new Random();
double c = ran.NextDouble();//随机处理by /http://blog.csdn.net/wyw308
string url = "http://ext.paipai.com/oneaday/comdynum?" + GetInputValue("ComdyId") + "&t=" + c.ToString();//宝贝抢拍上架地址by/ http://blog.csdn.net/wyw308
CookieContainer cc = new CookieContainer();
HttpHelper.NetworkDelay =0 ;
HttpHelper.Encoding = Encoding.GetEncoding("GB2312");
string result = HttpHelper.GetHtml(url, cc);
result = HttpFunction.Regex_str(result, "{.+?}");
jsonstr = result;
Dictionary
string a = aa["UploadSec"].ToString();
if (a != null && a != "")
return double.Parse(a) * 1000;
else
return -1;
}
二:验证码容器,将提前获取的验证码及cookie值保存到此,然后使用
///
/// 验证码cookie极点队容器 by/ http://blog.csdn.net/wyw308
///将提前获取的验证码及cookie值保存到此,然后使用
///
public class PPCode
{
//by/ http://blog.csdn.net/wyw308
private string vcode;
private string vcookie;
public PPCode()
{
}
public PPCode(string VCODE, string VCOOKIE)
{
this.vcode = VCODE;
this.vcookie = VCOOKIE;
}
public string VCODE
{
get
{
return this.vcode;
}
set
{
this.vcode = value;
}
}
public string VCOOKIE
{
get
{
return this.vcookie;
}
set
{
this.vcookie = value;
}
}
}
///
/// 访问验证码,取cookie及验证码值 by/ http://blog.csdn.net/wyw308
///
private void GetPPcode()
{
// by/ http://blog.csdn.net/wyw308
Random ran = new Random();
double c = ran.NextDouble();
HttpHelper.Referer = HttpFunction.UrlEnCode(webBrowser1.Url.ToString(), "GB2312").Replace("%3D", "=");//当前页面地址
string url = "http://ptlogin2.paipai.com/getimage?aid=17000101&CacheTime=" + c;
url = "http://captcha.qq.com/getimage?aid=17000101&CacheTime=" + c;//验证码的真实地址 by /http://blog.csdn.net/wyw308
// url = "http://captcha.qq.com/getimage";
CookieContainer ckcode = new CookieContainer();
pictureBox1.Image = new Bitmap(HttpHelper.GetStream(url, HttpHelper.CookieContainer, out c_v));
txt_code.Text = "";
txt_code.Focus();
}
三:根据页面动态手工构建post方法,这样比较灵活机动,操作起来交互效果好,by/ http://blog.csdn.net/wyw308
///
/// 动态构造post的数据 by/ http://blog.csdn.net/wyw308
///
///
///
private string GetPostD()
{
// by/ http://blog.csdn.net/wyw308
string pd = string.Empty;
string PostInput = "ComdyId,clsId,Address1,Address,Region,AddressId,PostCode,Name,Mobile,Phone,BuyNum,shippingFeeItem,commodityattr,Encrypt,Rule,BcLevel,sendtype";
//post的input数据列表,根据抓包和webbrorser分析得到,by /http://blog.csdn.net/wyw308
string[] s_input = PostInput.Split(new char[] { ',' });
for (int i = 0; i < s_input.Length; i++)
{
if (i == 0)
pd = GetInputValue(s_input[i]);
else
pd = pd + "&" + GetInputValue(s_input[i]);
}
string PostSelect = "mProvince,mCity,mTown";//post的select数据列表by /http://blog.csdn.net/wyw308
string[] s_select = PostSelect.Split(new char[] { ',' });
for (int j = 0; j < s_select.Length; j++)
{
pd = pd + "&" + GetSelectValue(s_select[j]);
}
pd = pd + "&Remark=";
return pd;
}
///
/// 取页面input控件值 by/ http://blog.csdn.net/wyw308
///
///
///
private string GetInputValue(string InputName)
{
// by/ http://blog.csdn.net/wyw308
string str = string.Empty;
HtmlDocument doc = webBrowser1.Document;
HtmlElement ipt = doc.GetElementsByTagName("input")[InputName];
str = InputName + "=" + HttpFunction.UrlEnCode(ipt.GetAttribute("value"), "GB2312");
return str;
}
///
/// 取页面select控件值 by/ http://blog.csdn.net/wyw308
///
///
///
private string GetSelectValue(string InputName)
{
// by/ http://blog.csdn.net/wyw308
string str = string.Empty;
HtmlDocument doc = webBrowser1.Document;
HtmlElement sels = doc.GetElementsByTagName("select")[InputName];
HtmlElementCollection opts = sels.Children;//取页面select的有效值时坎坷了老半天,立标留念by /http://blog.csdn.net/wyw308
for (int i = 0; i < opts.Count; i++)
{
if (opts[i].OuterHtml.Contains("selected"))
str = InputName + "=" + opts[i].GetAttribute("value");
}
return str;
}
四:动态构建提交需要的cookie by/ http://blog.csdn.net/wyw308
///
/// 动态构建cookie容器 by/ http://blog.csdn.net/wyw308
///
///
///
///
public static CookieContainer GetCookieFromStr(string ck_str, string domain)
{
by/ http://blog.csdn.net/wyw308
CookieContainer myCookieContainer = new CookieContainer();
string cookieStr = ck_str;
string[] cookstr = cookieStr.Split(';');
foreach (string str in cookstr)
{
string[] cookieNameValue = str.Split('=');
if (cookieNameValue.Length > 1 )
{
Cookie ck = new Cookie(cookieNameValue[0].Trim().ToString(), str.Substring(cookieNameValue[0].Trim().ToString().Length + 2));//网上一个写好的方法,做了调整by/ http://blog.csdn.net/wyw308
ck.Domain = domain;
ck.Path = "/";
myCookieContainer.Add(ck);
}
}
return myCookieContainer;
}
五:自动通过底层提交post及cookie数据,模拟抢拍。
///
/// 动态构建post及cookie,自动提交
/// by/ http://blog.csdn.net/wyw308
///
private void PostToPai()
{
// by/ http://blog.csdn.net/wyw308
int r_q = 0, r_succ = 0;
bool qp_ok = false;
string domain = "ext.paipai.com";//cookie的域名,一定要写对,by /http://blog.csdn.net/wyw308
string url = HttpFunction.UrlEnCode(webBrowser1.Url.ToString(), "GB2312").Replace("%3D", "=");//当前页面地址
HtmlElement hl = webBrowser1.Document.GetElementById("fixupformid");
string PostUrl = string.Format(hl.GetAttribute("action"));//得到提交的地址
//动态构建提交需要的cookie值 by/ http://blog.csdn.net/wyw308
string ck_str = webBrowser1.Document.Cookie;//页面数据生成的cookie值
string ck1 = "";
string ck2 = "";
int ver_num = ck_str.IndexOf("verifysession");//截取无用的验证码cookie串,用提前获取的验证码替换
if (ver_num != -1)
{
ck1 = ck_str.Substring(0, ver_num);
ck2 = ck_str.Substring(ver_num + 98);
}
else
ck1 = ck_str;
string postd = GetPostD();//得到post数据by/ http://blog.csdn.net/wyw308
for (int i = 0; i < pp.Count; i++)//循环已经提前获取的验证码及cookie by/ http://blog.csdn.net/wyw308
{
if (i == 0 && !ckb_sg.Checked)//第一次提交随机延时
{
WriMsg("开始抢拍了....");
//Random r = new Random();
int tys = int.Parse(txt_ys.Text.Trim());
//int ys = r.Next(tys, 2 * tys + 1000);
WriMsg("延时" + tys.ToString() + "毫秒...");
Thread.Sleep(tys);
}
ck_str = ck1 + pp[i].VCOOKIE + ck2;
CookieContainer PostCookie = new CookieContainer();
PostCookie = HttpWeb.GetCookieFromStr(ck_str, domain);//构造最终提交的cookieby/ http://blog.csdn.net/wyw308
string postdata = string.Format(postd + "&verifycode=" + pp[i].VCODE);//构造最终post数据by/ http://blog.csdn.net/wyw308
HttpHelper.Encoding = Encoding.GetEncoding("GB2312");
if (ckb_sg.Checked || i == 0)
HttpHelper.NetworkDelay = 0;
else
HttpHelper.NetworkDelay = int.Parse(txt_jg.Text.Trim());//发送请求随机间隔时间
HttpHelper.Referer = HttpFunction.UrlEnCode(url, "GB2312");
WriMsg("正在发送请求...");
r_q = r_q + 1;
if (string.IsNullOrEmpty(postdata))//记录异常,由于拍拍反限制因此有莫名错误,调试时使用,by /http://blog.csdn.net/wyw308
{
string errmsg = i.ToString() + "#Err#PostUrl:/r/n" + url + "/r/n" + PostUrl + "/r/n" + pp[i].VCODE + "#" + pp[i].VCOOKIE + "/r/n/r/nPostData:/r/n" + postdata + "/r/n/r/nCookie:/r/n" + ck_str + "/r/n/r/nResult:/r/n";
HttpPaipai.Msg(HttpFunction.UrlDeCode(errmsg, "GB2312"));
return;
}
string result = HttpHelper.GetHtml(PostUrl, postdata, true, PostCookie);//最终提交请求by /http://blog.csdn.net/wyw308
result = HttpFunction.NoHTML(HttpFunction.Regex_goup_str(result, "
软件下载:http://blog.csdn.net/wyw308/archive/2011/05/10/6408159.aspx
用到的httphelp类(感谢原作者),这里做了些细微调整by/ http://blog.csdn.net/wyw308:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;
namespace bym
{
public class HttpHelper
{
#region 私有变量
private static CookieContainer cc = new CookieContainer();
private static string contentType = "application/x-www-form-urlencoded";
private static string accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-silverlight-2-b1, */*";
private static string userAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
private static Encoding encoding = Encoding.GetEncoding("utf-8");
private static int delay = 1000;//延迟访问防止连续访问被发现 3秒
private static int maxTry =2;
private static int currentTry = 0;
private static string referer;
#endregion
#region 属性
///
/// Cookie容器
///
public static CookieContainer CookieContainer
{
get
{
return cc;
}
}
///
/// 获取网页源码时使用的编码
///
///
public static Encoding Encoding
{
get
{
return encoding;
}
set
{
encoding = value;
}
}
public static int NetworkDelay
{
get
{
Random r = new Random();
return (r.Next(delay , delay * 2));
}
set
{
delay = value;
}
}
public static int MaxTry
{
get
{
return maxTry;
}
set
{
maxTry = value;
}
}
public static string Referer
{
get
{
return referer;
}
set
{
referer = value;
}
}
#endregion
#region 公共方法
///
/// 获取指定页面的HTML代码
///
/// 指定页面的路径
/// 回发的数据
/// 是否以post方式发送请求
/// Cookie集合
///
public static string GetHtml(string url, string postData, bool isPost, CookieContainer cookieContainer)
{
int err_num = 0;
if (string.IsNullOrEmpty(postData))
{
err_num = 1;
// return GetHtml(url, cookieContainer);
}
Thread.Sleep(NetworkDelay);//延迟访问
currentTry++;
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebResponse = null;
try
{
byte[] byteRequest = Encoding.Default.GetBytes(postData);
err_num = 2;
httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
err_num = 3;
httpWebRequest.CookieContainer = cookieContainer;
err_num = 4;
httpWebRequest.ContentType = contentType;
err_num = 5;
httpWebRequest.ServicePoint.ConnectionLimit = maxTry;
err_num = 6;
httpWebRequest.Referer = referer;
err_num = 7;
httpWebRequest.Accept = accept;
err_num = 7;
httpWebRequest.UserAgent = userAgent;
err_num = 8;
httpWebRequest.Method = isPost ? "POST" : "GET";
err_num = 8;
httpWebRequest.ContentLength = byteRequest.Length;
err_num = 9;
Stream stream = httpWebRequest.GetRequestStream();
err_num = 10;
stream.Write(byteRequest, 0, byteRequest.Length);
err_num = 11;
stream.Close();
err_num = 12;
httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
err_num = 13;
Stream responseStream = httpWebResponse.GetResponseStream();
err_num = 14;
StreamReader streamReader = new StreamReader(responseStream, encoding);
err_num = 15;
string html = streamReader.ReadToEnd();
err_num = 16;
streamReader.Close();
err_num = 17;
responseStream.Close();
err_num = 18;
currentTry = 0;
err_num = 19;
httpWebRequest.Abort();
err_num = 20;
httpWebResponse.Close();
err_num = 21;
return html;
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss ") + e.Message);
Console.ForegroundColor = ConsoleColor.White;
HttpWeb.WriteLog(err_num.ToString()+"#"+e.Message, "GetHtmlErr.log");
if (currentTry <= maxTry)
{
GetHtml(url, postData, isPost, cookieContainer);
}
currentTry--;
if (httpWebRequest != null)
{
httpWebRequest.Abort();
} if (httpWebResponse != null)
{
httpWebResponse.Close();
}
return string.Empty;
}
}
///
/// 获取指定页面的HTML代码
///
/// 指定页面的路径
/// Cookie集合
///
public static string GetHtml(string url, CookieContainer cookieContainer)
{
int a = 0;
Thread.Sleep(NetworkDelay);
a = 1;
currentTry++;
HttpWebRequest httpWebRequest = null;
a = 2;
HttpWebResponse httpWebResponse = null;
try
{
a = 3;
httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
a = 4;
httpWebRequest.CookieContainer = cookieContainer;
a = 5;
httpWebRequest.ContentType = contentType;
a = 6;
httpWebRequest.ServicePoint.ConnectionLimit = maxTry;
a = 7;
httpWebRequest.Referer = referer;
a = 8;
httpWebRequest.Accept = accept;
a = 9;
httpWebRequest.UserAgent = userAgent;
a = 10;
httpWebRequest.Method = "GET";
a = 11;
httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
a = 12;
Stream responseStream = httpWebResponse.GetResponseStream();
a = 13;
StreamReader streamReader = new StreamReader(responseStream, encoding);
a = 14;
string html = streamReader.ReadToEnd();
a = 15;
streamReader.Close();
a = 16;
responseStream.Close();
a = 17;
currentTry--;
httpWebRequest.Abort();
a = 18;
httpWebResponse.Close();
a = 19;
return html;
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss ") + e.Message);
Console.ForegroundColor = ConsoleColor.White;
HttpWeb.WriteLog(a.ToString()+"#"+e.Message, "GetHtml2.log");
if (currentTry <= maxTry)
{
GetHtml(url, cookieContainer);
}
currentTry--;
if (httpWebRequest != null)
{
httpWebRequest.Abort();
} if (httpWebResponse != null)
{
httpWebResponse.Close();
}
return string.Empty;
}
}
///
/// 获取指定页面的HTML代码
///
/// 指定页面的路径
///
public static string GetHtml(string url)
{
return GetHtml(url, cc);
}
///
/// 获取指定页面的HTML代码
///
/// 指定页面的路径
/// 回发的数据
/// 是否以post方式发送请求
///
public static string GetHtml(string url, string postData, bool isPost)
{
return GetHtml(url, postData, isPost, cc);
}
///
/// 获取指定页面的Stream
///
/// 指定页面的路径
/// 回发的数据
/// 是否以post方式发送请求
/// Cookie集合
///
public static Stream GetStream(string url, CookieContainer cookieContainer, out string ck_vccode)
{
//Thread.Sleep(delay);
int j = 0;
currentTry++;
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebResponse = null;
try
{
httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
j =1;
j = 2;
httpWebRequest.CookieContainer = cookieContainer;
httpWebRequest.ContentType = contentType;
j = 3;
httpWebRequest.ServicePoint.ConnectionLimit = maxTry;
j = 4;
httpWebRequest.Referer = url;
j = 5;
httpWebRequest.Accept = accept;
j = 6;
httpWebRequest.UserAgent = userAgent;
j = 7;
httpWebRequest.Method = "GET";
j = 8;
httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
j = 9;
Stream responseStream = httpWebResponse.GetResponseStream();
j = 10;
ck_vccode = httpWebResponse.Headers["Set-Cookie"];
j =11;
ck_vccode = ck_vccode.Substring(0, ck_vccode.IndexOf("PATH") - 1);
currentTry--;
j = 12;
//httpWebRequest.Abort();
//httpWebResponse.Close();
return responseStream;
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss ") + e.Message);
Console.ForegroundColor = ConsoleColor.White;
HttpWeb.WriteLog(j.ToString() + "#" + e.Message, "GetStreamErr.log");
if (currentTry <= maxTry)
{
GetHtml(url, cookieContainer);
}
currentTry--;
if (httpWebRequest != null)
{
httpWebRequest.Abort();
} if (httpWebResponse != null)
{
httpWebResponse.Close();
}
ck_vccode="";
return null;
}
}
#endregion
//CookieContainer co = new CookieContainer();//设置cookie
// co.SetCookies(new Uri(server), cookie);//SERVER 抓包里的host
}
}