关于小米手机网站抢购的一点技术分析
2019独角兽企业重金招聘Python工程师标准>>>
先PS一下:最近小米手机火了,看起来好像地球人已经不能阻止它的发展趋势了
其实本文论述的技术也并非小米手机专用,只是用小米手机来做借鉴,但课题起源于朋友请求帮忙购买小米手机,于是借助专业知识写了一个抢购的工具,拿出来和大家分享一下。说叫抢购工具,其实就是自动下订单而已,因为小米手机网站的订单只要在72小时内完成支付就可以,所以在第一时间完成下单以后找闲暇时间进行支付就可以了。
再PS一下:【声明】本工具原理为模拟浏览器访问和执行页面,不包含任何入侵和破坏行为。本工具的优点只是自动化处理以及节省不必要的流量耗费。
1、首先分析任务实现需要操作的步骤:
a、登录系统,此步骤中小米商城网站使用了通行证认证模式,即需要将表单提交到passport.xiaomi.com,认证成功后通过token传递回商城网站的callback页面。
b、清空购物车,本步骤可选。因为是工具自动购买,防止错误下单,可在每次执行操作前自动清空购物车,购物车清空后会302到购物车页面,http://order.xiaomi.com/cart,页面提示“清空购物车成功”。
c、将商品放入购物车。此步骤小米网站没有使用post,而是get,通过url将商品id以及数量传递给服务器,并且还使用了友好url,例如 http://order.xiaomi.com/cart/add/1016-0-1 是将 小米手机M1放入购物车,其中1016为小米手机的商品id,0表示此商品为单品(非组合套装),1表示购买一个。以此类推。放入购物车以后会自动302到购物车页面,不过此时url为 http://order.xiaomi.com/cart/index,显示购物车中的商品。
d、提交订单。本步骤同样为get方式,直接请求地址 http://order.xiaomi.com/buy/checkout 即开始将购物车中的商品作为一个订单进行提交,此时进入订单详细信息填写页面,填写收货人、收货地址、电话、发票等信息,确认订单需要post,请求的地址仍然是 http://order.xiaomi.com/buy/checkout。
2、关键技术点分析及实现
清楚了任务要求,接下来分析技术点,鉴于本人对C#比较熟悉,故选用C#语言实现,采用了Winform项目框架。
a、核心需求即是通过http协议下载页面,以下为本人使用的核心代码:
View Code
Uri uri = rawUri;
HttpWebSession session = new HttpWebSession()
{
RequestUri = uri,
};
var _request = session.Request =
(HttpWebRequest)WebRequest.Create(uri);
_httpWebSessions.Add(session);
if (Proxy != null)
{
_request.Proxy = Proxy;
}
_request.AllowAutoRedirect = false;
if (Uri.UriSchemeHttps == uri.Scheme)
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(RemoteCertificateValidation);//
}
if (Credentials != null)
{
_request.Credentials = Credentials;
}
if (!string.IsNullOrEmpty(Accept))
{
_request.Accept = Accept;
}
if (!string.IsNullOrEmpty(AcceptLanguage))
{
_request.Headers.Add("Accept-Language", AcceptLanguage);
}
if (!string.IsNullOrEmpty(AcceptCharset))
{
_request.Headers.Add("Accept-Charset", AcceptCharset);
}
_request.KeepAlive = KeepAlive;
if (!string.IsNullOrEmpty(RefererUrl))
{
_request.Referer = RefererUrl;
}
switch (_acceptEncoding)
{
case AcceptEncoding.GZIP:
{
_request.Headers.Add("Accept-Encoding", "gzip");
break;
}
case AcceptEncoding.DEFLATE:
{
_request.Headers.Add("Accept-Encoding", "deflate");
break;
}
case AcceptEncoding.BOTH:
{
_request.Headers.Add("Accept-Encoding", "gzip,deflate");
break;
}
}
if (_request.CachePolicy == null || _request.CachePolicy.Level != _cacheLevel)
{
_request.CachePolicy = new RequestCachePolicy(_cacheLevel);
}
if (_headers != null && _headers.Count > 0)
{
foreach (KeyValuePair<string, string> item in _headers)
{
try
{
_request.Headers.Add(item.Key, item.Value);
}
catch
{ }
}
}
_request.UserAgent = _userAgent;
_request.Referer = RefererUrl;
if (TimeOut != 0)
{
_request.Timeout = TimeOut;
}
if (postData == null)
{
if (postDictionary != null)
{
foreach (var item in postDictionary)
{
postText += item.Key + "=" + item.Value + "&";
}
postText = postText.Trim('&');
}
if (!string.IsNullOrEmpty(postText))
{
postData = _encoding.GetBytes(postText);
}
}
if (_cookieContainer != null)
{
string strCookieHeader = _cookieContainer.GetCookieHeader(uri);
if (!string.IsNullOrEmpty(strCookieHeader))
{
_request.Headers["Cookie"] = strCookieHeader;
}
}
if (postData != null)
{
session.PostedData = postData;
_request.Method = "POST";
_request.ContentType = "application/x-www-form-urlencoded";
_request.ContentLength = postData.Length;
Stream requestStream = _request.GetRequestStream();
requestStream.Write(postData, 0, postData.Length);
requestStream.Close();
}
var _response = session.Response = (HttpWebResponse)_request.GetResponse();
if (_cookieContainer != null)
{
string strSetCookieHeader = _response.Headers["Set-Cookie"];
if (!string.IsNullOrEmpty(strSetCookieHeader))
{
_cookieContainer.SetCookies(_response.ResponseUri, strSetCookieHeader);
}
}
StatusCode = _response.StatusCode;
_requestCookieCollection = _cookieContainer.GetCookieCollection(rawUri);
_response.Cookies = _cookieContainer.GetCookieCollection(_response.ResponseUri);
if (IsEncodingAccepted(_response, AcceptEncoding.GZIP))
{
responseStream = new GZipStream(_response.GetResponseStream(), CompressionMode.Decompress);
}
else if (IsEncodingAccepted(_response, AcceptEncoding.DEFLATE))
{
responseStream = new DeflateStream(_response.GetResponseStream(), CompressionMode.Decompress);
}
else
{
responseStream = _response.GetResponseStream();
}
if (StatusCode == HttpStatusCode.Redirect || StatusCode == HttpStatusCode.Moved)
{
if (_allowAutoRedirect)
{
responseStream.Close();
string strRedirectUrl = _response.Headers["Location"];
var stream = GetStream(new Uri(rawUri, strRedirectUrl), true, null, null, null, null, null);
return stream;
}
// return GetStream(
}
else if (StatusCode == HttpStatusCode.Unauthorized)
{
string strAuthorizition = OnAuthorizition();
if (!string.IsNullOrEmpty(strAuthorizition))
{
}
}
上述代码是本人多年积累的一个类库中的一点核心代码,解决了诸多常见问题,比如cookieContainer对domain识别异常,https访问等等,如有需要本人可提供下载。
b、逻辑处理的自动机
鉴于web访问过程中容易出现的各种不确定性因素,经常会出现请求同一个地址却返回不一样的内容,多数为302活301。本人使用了注册处理函数的方式,每次请求完以后,根据返回的页面url找到相应的处理函数进行操作,比如登录时,发送的是指向http://passport.xiaomi.com/index.php?...的一个请求,但返回结果往往变成 http://www.xiaomi.com/,在相应的处理函数中就需要进行清空购物车或者将商品放入购物车。
View Code
protected virtual void ProcessHttpSessions(ProcessState state)
{
state.Processed = true;
if (RunState == RunState.Pauseing)
{
OnLog("==========被用户暂停==========");
ChangeState(RunState.Paused);
state.Break = true;
return;
}
if (RunState == RunState.PauseingByNetService)
{
OnLog("==========被换IP服务暂停==========");
ChangeState(RunState.PausedByNetService);
state.Break = true;
return;
}
if (RunState == RunState.Stopping)
{
OnLog("==========被用户停止==========");
ChangeState(RunState.Stoped);
state.Break = true;
return;
}
if (_httpClient == null || _httpClient.HttpWebSessions == null)
{
state.Continue = true;
return;
}
int oldSessionCount = _httpClient.HttpWebSessions.Count;
Action<ProcessState> processerAction = null;
if (string.IsNullOrEmpty(_httpClient.RequestUrl))
{
OnLogError("没有要处理的请求");
state.Break = true;
return;
}
if (httpSessionProcesser.ContainsKey(_httpClient.RequestUrl))
{
processerAction = httpSessionProcesser[_httpClient.RequestUrl];
}
if (processerAction == null)
{
foreach (var processer in httpSessionProcesser)
{
if (_httpClient.RequestUrl.StartsWith(processer.Key) ||
Regex.IsMatch(_httpClient.RequestUrl, processer.Key))
{
processerAction = processer.Value;
break;
}
}
}
if (processerAction != null)
{
processerAction(state);
if (state.Break || state.Continue)
{
return;
}
if (!state.Processed)
{
ProcessHttpSessions(state);
}
return;
}
OnLogError("出错了,RequestUrl:" + _httpClient.RequestUrl);
OnLogError("ResponseUrl:" + _httpClient.ResponseUrl);
OnLogError("ResponseText:" + _httpClient.ResponseText);
state.Break = true;
}
经过实践和改进,本人已将上述部分分离成独立类库,如有需要可提供,以进行参考和交流。
3、软件界面布局,界面截图已隐藏掉部分敏感信息
转载于:https://my.oschina.net/leeyibin/blog/84788
关于小米手机网站抢购的一点技术分析相关推荐
- java抢购小米手机_小米手机怎样抢购
小米手机性价比高,是很多人想要购买的手机.但是由于小米采用的是饥饿营销策略,所以购买小米手机需要每周二中午12:00通过网站抢购,不然只能通过黄牛多花几百块钱的费用.但是小米手机怎么抢呢,下面我就来介 ...
- 电信3g在小米信号显示无服务器,关于小米手机电信3G信号问题的分析
上周,我遭遇了所谓的"小米信号门",表现症状为数据开关关闭状态下,3G信号满,1X信号满,数据开关打开,3G信号空,1X信号满,数据自动切换到2G通道进行上网.手机为小米M1电信版 ...
- 支付宝支付之扫码支付(电脑网站支付)、H5支付(手机网站支付)相关业务流程分析总结
前言 在上一篇文章<微信支付之扫码支付.公众号支付.H5支付.小程序支付相关业务流程分析总结>中,分析和总结了微信支付相关支付类型的业务流程,这里作为与微信支付平起平坐不相伯仲的支付宝支付 ...
- 简单个人静态HTML网页设计作品 基于HTML+CSS+JavaScript仿小米手机网站 html静态在线购物商城网页制作
常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电商. 宠物. 电器. 茶叶. 家居. 酒店. 舞蹈. 动漫. 服装. 体育. 化妆品. 物流. 环保. 书籍. 婚纱. 游戏. 节日. ...
- 多语言网站开发 不完全技术分析收录
转自:http://www.cnbruce.com/blog/showlog.asp?cat_id=27&log_id=691 语言是信息传播的主要障碍. 多语言网站,顾名思义就是能够以多种语 ...
- 德州仪器TI芯片自动下单抢购监控软件技术分析
2011年4月5日,德州仪器(TI)和美国国家半导体(NS)宣布签署合并协议,TI将以25美元/股.总额约65亿美元的现金价格,收购国家半导体.本次收购将使业界共同致力于解决客户模拟问题的两个领导者实 ...
- 手机uc怎么放大页面_手机网站怎样做可以提高用户体验度?——竹晨网络
目前,手机已经占据了人们大多数的闲暇时间,互联网的流量开始逐渐向移动端倾斜,重视移动端的用户体验,就可以给客户端增加很多意想不到的功能.但是还是有很多公司和站长不知道手机网站应该怎么建才能符合用户的使 ...
- WAP 2.0网站是用XHTML MP基础(手机网站开发基础技术)
原文链接(英文):http://www.developershome.com/wap/xhtmlmp/ 同时推荐的文章(英文)http://mobiforge.com/starting/story/a ...
- 小米手机硬改技术_小米11手机爆料:首发骁龙875 或采用屏下摄像头技术
12月1日高通应该就要公布骁龙875处理器,而对于这颗2021年的旗舰芯片,小米手机必然要抢首发,这也是他们一贯的传统.据最新消息称,小米11手机有望首发骁龙875处理器,不过这款手机预计要在明年3月 ...
- 小米MIX Alpha获得百万美金技术大奖;索尼或将推出无边框手机;Linus 不建议用 ZFS | 极客头条...
整理 | 屠敏 快来收听极客头条音频版吧,智能播报由标贝科技提供技术支持. 「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注 ...
最新文章
- Linux CENTOS7 Linux流量监控工具-iftop 安装过程以及示例!
- AT5198 01 Matrix(构造)
- 汇真科技李利鹏 :人工智能的应用边界
- pww区域连接特征提取算法
- js获取url的参数
- 从graphql endpoint获取schema文件
- 架构重构改善既有代码的设计
- 2021数学建模C题思路数据挖掘
- python 退出_如果读完这篇文章不能让你入门Python,那我将永久退出编程界
- BugkuCTF-MISC题细心的大象
- VS2010 测试功能之旅:编码的UI测试(4)-通过编写测试代码的方式“.NET研究”建立UI测试(下)...
- Kubernetes 两步验证 - 使用 Serverless 实现动态准入控制
- 《惢客创业日记》2020.02.11-02.21(周二)惢客的三个发展阶段(下)
- 【微信数据迁移】微信数据怎么恢复到另一部手机
- 点击编辑按钮,前端table表格行内指定td可修改。(table是动态生成的)
- 云虚拟主机搭建个人博客
- 渗透学习-文件上传篇-基础知识部分(持续更新中)
- 基于SSM的小区缴费系统
- c226打印机驱动安装_打印机驱动怎么安装图文详解
- python如何输出多个星号_如何使用python输出连续星号?