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)适当修改。
源码如下:
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;
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;
public class ThreadOne extends Thread {
private static List<Thread> runningThreads = new ArrayList<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 ThreadOne(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("很抱歉,该商品无法送至您选择的区域");
}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;
}
}