java实现京东秒杀功能分享 京东秒杀软件
简单介绍下功能
1.每隔一段时间(比如1分钟)在京东手机每日一秒杀页面提取产品(手机)链接。
http://sale.360buy.com/act/8vthfgr10cjmdyz.html#01
2.根据提取到得产品链接给后台发送数据,以便获取产品价格,描述,折扣,库存(是否有货)等信息。
3.根据得到的信息,进行判断。
若符合条件自动调用浏览器(前提是chrome加入环境变量,或者改代码将浏览器.exe路径加入代码,修改程序)打开产品订购页面。
4.其实也就解决了一个问题:不用自己频繁的刷新网页了,不用自己查看;
登陆,提交订单还得浏览器解决(貌似这几个功能点比较复杂,没做处理)
程序做的不太完善:
运行前需要修改几个地方:
1.环境变量:chrome 加入浏览器变量,以便调用。。或者自己修改源代码用其它方式打开。
2.活动中每个产品的价格信息需要设置。这个比较不好,必须修改源代码。
修改的地方在filter()这个函数里。
3.另外一个需要修改的地方是
hasstore(string skuidkey)
address="http://price.360buy.com/stocksoa/stockhandler.ashx?callback=getprovincestockcallback&type=pcastock&skuid="+skuidkey+"&provinceid=1&cityid=2800&areaid=2850";
这个地方的cityid=2800&areaid=...地里位置信息。这个没做处理。需要从手机产品页自己搞出来。
其实也比较简单。chrome+f12 ,修改“城市”,区域等信息后,会看到一个get请求发送到后台,这个链接里面包含了需要的信息。(http://price.360buy.com/stocksoa/stockhandler.ashx?callback=getprovincestockcallback&type=pcastock&skuid=64ebd0f20f593d95c72c6eed59b64658&provinceid=1&cityid=2805&areaid=2854)适当修改。
util.java
package view.util;
import java.util.arraylist;
public class util {
public static void print(object o){
system.out.print(o);
}
public static void println(object o){
if(null==o)
system.out.println();
else
system.out.println(o);
}
public static arraylist<integer> toarraylist(int[] ints){
if(ints.length==0)
return null;
arraylist<integer> al=new arraylist<integer>();
for(int i=0;i<ints.length;i++){
al.add(ints[i]);
}
return al;
}
}
miaosha360buy.java
package jingdong;
public class miaosha360buy {
java.util.concurrent.countdownlatch t= new java.util.concurrent.countdownlatch(1);
/**
* @param args
*/
public static void main(string[] args) {
// todo auto-generated method stub
system.out.println(thread.currentthread().getname() + "开始");
miaosha360buy ms360=new miaosha360buy();
new threadone360buy(ms360.t).start();
while(true){
try {
ms360.t.await();
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
try {
thread.sleep(1000*60);//间隔1分钟调用一次?
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
ms360.t=new java.util.concurrent.countdownlatch(1);
new threadone360buy(ms360.t).start();
system.out.println("new tread in while..");
}
}
}
miaosha360buy.java
package jingdong;
public class miaosha360buy {
java.util.concurrent.countdownlatch t= new java.util.concurrent.countdownlatch(1);
/**
* @param args
*/
public static void main(string[] args) {
// todo auto-generated method stub
system.out.println(thread.currentthread().getname() + "开始");
miaosha360buy ms360=new miaosha360buy();
new threadone360buy(ms360.t).start();
while(true){
try {
ms360.t.await();
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
try {
thread.sleep(1000*60);//间隔1分钟调用一次?
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
ms360.t=new java.util.concurrent.countdownlatch(1);
new threadone360buy(ms360.t).start();
system.out.println("new tread in while..");
}
}
}
threadone360buy.java
package jingdong;
import java.io.ioexception;
import java.util.arraylist;
import java.util.hashmap;
import java.util.list;
import java.util.regex.matcher;
import java.util.regex.pattern;
import org.apache.http.httpentity;
import org.apache.http.httpresponse;
import org.apache.http.client.clientprotocolexception;
import org.apache.http.client.methods.httpget;
import org.apache.http.impl.client.defaulthttpclient;
import org.apache.http.util.entityutils;
import org.jsoup.jsoup;
import org.jsoup.nodes.document;
import org.jsoup.nodes.element;
import org.jsoup.select.elements;
import view.util.util;
public class threadone360buy extends thread{
java.util.concurrent.countdownlatch c;
arraylist al;//记录秒杀产品页面
float price=0.0f;//商品价格
float discount=0.0f;//商品折扣
//用于保存线程信息,在这个项目里用处不大
private static list<thread> runningthreads = new arraylist<thread>();
//这个是一个计数器(不太会用,线程这方面一直感觉是比较复杂的)
public threadone360buy(java.util.concurrent.countdownlatch c) {
this.c=c;
}
@override
public void run() {
regist(this);// 线程开始时注册
// 打印开始标记
system.out.println(thread.currentthread().getname() + "开始...");
try {
//抓取京东手机秒杀页面
this.getmessage("http://sale.360buy.com/act/8vthfgr10cjmdyz.html#01");
} catch (clientprotocolexception e) {
// todo auto-generated catch block
e.printstacktrace();
c.countdown();
} catch (ioexception e) {
// todo auto-generated catch block
e.printstacktrace();
c.countdown();
}
c.countdown();
unregist(this);// 线程结束时取消注册
// 打印结束标记
system.out.println(thread.currentthread().getname() + "结束.");
}
public void regist(thread t) {
synchronized (runningthreads) {
runningthreads.add(t);
}
}
public void unregist(thread t) {
synchronized (runningthreads) {
runningthreads.remove(t);
}
}
public static boolean hasthreadrunning() {
// 通过判断runningthreads是否为空就能知道是否还有线程未执行完
return (runningthreads.size() > 0);
}
/**
* 从手机秒杀页面获取 prodcut链接,product skuid,skuidkey,price,store信息
* @param url:手机秒杀页面
* @throws clientprotocolexception
* @throws ioexception
*/
public void getmessage(string url) throws clientprotocolexception, ioexception{
al=getmainurl(down(url));
util.println(al);
if(al.size()==0){
c.countdown();
system.exit(0);
return;
}
for(int i=0;i<al.size();i++){
stringbuffer sb=new stringbuffer();
stringbuffer openurl = new stringbuffer();
openurl.append("http://www.360buy.com/product/");
openurl.append(al.get(i).tostring().subsequence(al.get(i).tostring().lastindexof('/')+1, al.get(i).tostring().lastindexof('.')));
openurl.append(".html");
// 557673
sb.append("http://d.360buy.com/fittinginfo/get?skuid=");
sb.append(al.get(i).tostring().subsequence(al.get(i).tostring().lastindexof('/')+1, al.get(i).tostring().lastindexof('.')));
sb.append("&callback=recommend.cbrecofittings");
util.println(sb.tostring());
//map中保存的是产品name,price,折扣信息
util.println("al("+i+") down:"+sb.tostring());
hashmap<string, string> hm=parseproduct(down(sb.tostring()));
//用来匹配价格信息。匹配库存信息
filter(hm,openurl.tostring());//过滤价格,如果条件符合就打开浏览器
}
}
/**
* 一个验证方法
* @param hm 保存着价格信息
* @param url 产品页面
*/
public void filter(hashmap<string, string> hm,string url){//url既是产品页面
// view.util.oencmd.openwinexe(null,url);
// 是不是应该先查看库存?
string skuidkey=parseskuidkey(url);
if(!hasstore(skuidkey)){
util.println("-------------------------------------");
util.println("没有库存了!");
util.println("-------------------------------------");
//减掉计数,以便主线程判断
c.countdown();
//应该结束子线程哦?
return;
}
if(hm.get("skuid").equals("201602")){//判断//摩托罗拉skuid=201602
//这里的价格是写死了,运行前得改过来才行。
this.setprice(499.0f);
//是不是应该打开控制台?
if(float.parsefloat(hm.get("price"))<=this.getprice()){
view.util.oencmd.openwinexe(null,url);
}
}else if(hm.get("skuid").equals("675647")){//天语skuid=675647
// //这里的价格是写死了,运行前得改过来才行。
// this.setprice(699.0f);
// //是不是应该打开控制台?
// if(float.parsefloat(hm.get("price"))<=this.getprice()){
// view.util.oencmd.openwinexe(null,url);
// }
}
}
/**
* 解析了产品页面中name,skuid,price信息
* @param doc
* @return
*/
public static hashmap<string, string> parseproduct(document doc){
string text=doc.text();
string docc=text.substring(text.indexof("master")+9,text.indexof("fittings")-3).replaceall("[\\s]", "");
string[] ss=docc.split(",");
hashmap<string, string> hm=new hashmap<string, string>();
for(string it: ss){
string string=it.replaceall("\"", "");
if(string.contains("\\u"))
string=unicodedecode(string);
string[] str=string.split(":");
hm.put(str[0], str[1]);
}
util.println(hm);
return hm;
}
/**
* 处理unicode字符,转换成显示字符(汉字),不太通用
* @param it: \u6a5d
* @return
*/
public static string unicodedecode(string it){//有个缺点,就是前面的字符无法去掉
util.println(it);
string regex="(\\\\u[0-9a-f]{4})";
pattern pt= pattern.compile(regex);
matcher mc;
stringbuffer sb;
stringbuffer sba=new stringbuffer();
mc=pt.matcher(it);
while(mc.find()){
sb=new stringbuffer();
mc.appendreplacement(sba,sb.append((char )integer.parseint((mc.group(1).substring(2)), 16)).tostring());
}
return sba.tostring();
}
/**
* 返回文档对象(下载内容)
* @param url 下载页面
* @return
* @throws clientprotocolexception
* @throws ioexception
*/
public static document down(string url) throws clientprotocolexception, ioexception{
document doc = null;
defaulthttpclient httpclient=new defaulthttpclient();
util.println("download:"+url);
httpget get=new httpget(url);
httpresponse response;
response = httpclient.execute(get);
httpentity entity = response.getentity();
doc = jsoup.parse(entity.getcontent(), "utf-8","");
//释放资源
entityutils.consume(entity);
//关闭连接
httpclient.getconnectionmanager().shutdown();
return doc;
}
/**
* 加入了编码控制信息
* @param url 待下载页面
* @param code 编码
* @return
* @throws clientprotocolexception
* @throws ioexception
*/
public static document down(string url,string code) throws clientprotocolexception, ioexception{
document doc = null;
defaulthttpclient httpclient=new defaulthttpclient();
util.println("download:"+url);
httpget get=new httpget(url);
httpresponse response;
response = httpclient.execute(get);
httpentity entity = response.getentity();
doc = jsoup.parse(entity.getcontent(), code,"");
//释放资源
entityutils.consume(entity);
//关闭连接
httpclient.getconnectionmanager().shutdown();
return doc;
}
/**
* 用来解析 秒杀页面中的产品(收集)链接
* @param doc
* @return
*/
public static arraylist<string> getmainurl(document doc){
if(doc.equals("")||doc==null)
return null;
try {
thread.sleep(50);
} catch (interruptedexception e1) {
// todo auto-generated catch block
e1.printstacktrace();
}
arraylist<string> urls=new arraylist<string>();
string rule="map[name=map] >area[href~=product]";
/**
* 开始解析
*/
elements elements=doc.select(rule);
for (element e : elements) {
// util.println(e.absurl("abs:href"));
urls.add(e.absurl("abs:href"));
}
return urls;
}
/**
* 获取skuidkey,用于查询商品库存信息
* @param url
* @return
*/
public static string parseskuidkey(string url){
document doc=null;
try {
doc=down(url,"gb2312");
} catch (clientprotocolexception e) {
// todo auto-generated catch block
e.printstacktrace();
} catch (ioexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
// util.println(doc.select("script"));
string text = null;
for(element e : doc.select("script")){
if(e.data().contains("skuidkey:")){
text=e.data();
break;
}
}
//skuidkey:'7d45919ea8242511daa5cc7c6d7b351c'
text=text.substring(text.indexof("skuidkey:")+10, text.indexof("skuidkey:")+42);
util.println("---------------------------------");
util.println(text);
return text;
}
/**
* 查看库存信息
* @param skuidkey
* @return
*/
public static boolean hasstore(string skuidkey){//这个地方没有处理,直接提取浏览器中的信息
string address = null;
boolean hasstore=false;
if(skuidkey!=null && !"".equals(skuidkey))
address="http://price.360buy.com/stocksoa/stockhandler.ashx?callback=getprovincestockcallback&type=pcastock&skuid="+skuidkey+"&provinceid=1&cityid=2800&areaid=2850";
else{
util.println("解析skuidkey错误");
}
try {
if(parsestore(down(address))){
hasstore=true;
}
} catch (clientprotocolexception e) {
// todo auto-generated catch block
e.printstacktrace();
} catch (ioexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
return hasstore;
}
/* if(array[1]=="34"||array[1]=="18"){
changecart(false);
djdarea.stockinfodom.html("<strong class='store-over'>无货</strong>");
}
else if(array[1]=="0"){
changecart(false);
djdarea.stockinfodom.html("<strong class='store-over'>无货</strong>");
}
else if(array[2]=="0"&&array[4]!="2"){
changecart(false);
djdarea.stockinfodom.html("很抱歉,该商品无法送至您选择的区域");
}
else if(array[1]=="33"||array[1]=="5"){
changecart(true);
djdarea.stockinfodom.html("<strong>现货</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
else if(array[1]=="36"){
changecart(true);
djdarea.stockinfodom.html("<strong>预订</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
else if(array[1]=="39"){
changecart(true);
djdarea.stockinfodom.html("<strong>在途</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
else if(array[1]=="40"){
changecart(true);
djdarea.stockinfodom.html("<strong>可配货</strong>"+(array[4]=="1"?",该区域"+(array[3]=="0"?"不":"")+"支持货到付款":"")+cashdesc);
}
*/
/**
* 解析库存信息
* @param doc
* @return
*/
public static boolean parsestore(document doc){
string text=doc.text();
string docc=text.substring(text.indexof("-")-1,text.lastindexof(",")-1);
util.println(docc);
string[] store=docc.split("-");
if(store[1].equals("34") || store[1].equals("18")){
//无货
util.println("此地无货");
return false;
}else if(store[1].equals("33") || store[1].equals("5")){
//现货
util.println("此地现货");
return true;
}
util.println(store[1]);
return false;
}
//几个bean方法
public float getprice() {
return price;
}
public void setprice(float price) {
this.price = price;
}
public float getdiscount() {
return discount;
}
public void setdiscount(float discount) {
this.discount = discount;
}
}
oencmd.java
package view.util;
public class oencmd {
// public static void main(string[] args) {
//// openwinexe(null);
// openexe(null,"http://www.baidu.com");
// }
//用 java 调用windows系统的exe文件,比如notepad,calc之类
public static void openwinexe(string command,string url) {
if(command==null ||command.equals("")){
command = "chrome "+url;
}
runtime rn = runtime.getruntime();
process p = null;
try {
p = rn.exec(command);
} catch (exception e) {
system.out.println("error win exec!");
}
}
//调用其他的可执行文件,例如:自己制作的exe,或是 下载 安装的软件.
public static void openexe(string pathandname,string url) {
if(pathandname==null || pathandname.equals("")){
pathandname="c:\\users\\administrator\\appdata\\local\\google\\chrome\\application\\chrome.exe";
}
if(url!=null && !url.equals("")){
pathandname+=" ";
pathandname+=url;
}
runtime rn = runtime.getruntime();
process p = null;
try {
p = rn.exec(pathandname);
} catch (exception e) {
system.out.println("error exec!");
}
}
}
上一篇: Java连接redis及基本操作示例