java实现京东秒杀功能分享,过滤无关网页

简单介绍下功能

相关技术:上一篇+队列

1.每隔一段时间(比如1分钟)在京东手机每日一秒杀页面提取产品(手机)链接。

2.根据提取到得产品链接给后台发送数据,以便获取产品价格,描述,折扣,库存(是否有货)等信息。
3.根据得到的信息,进行判断。

思路分析:将主网站添加进队列,根据httpClent解析该网站,的奥对应的链接,判断链接是否有效,如果有效判断是否是目标,是目标,进行相关操作,不是目标添加进队列,在次解析队列,通过这种方式解析整个网站。

若符合条件自动调用浏览器(前提是chrome加入环境变量,或者改代码将浏览器.exe路径加入代码,修改程序)打开产品订购页面。
4.其实也就解决了一个问题:不用自己频繁的刷新网页了,不用自己查看;
登陆,提交订单还得浏览器解决(貌似这几个功能点比较复杂,没做处理)

 

程序做的不太完善:
运行前需要修改几个地方:
1.环境变量:chrome
加入浏览器变量,以便调用。。或者自己修改源代码用其它方式打开。
2.活动中每个产品的价格信息需要设置。这个比较不好,必须修改源代码。
修改的地方在filter()这个函数里。
3.另外一个需要修改的地方是
hasStore(String skuidkey)

package com.open111.crawler;

address=””;
这个地方的cityid=2800&areaid=…地里位置信息。这个没做处理。需要从手机产品页自己搞出来。
其实也比较简单。chrome+F12
,修改“城市”,区域等信息后,会看到一个get请求发送到后台,这个链接里面包含了需要的信息。(

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

Util.java

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
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;

复制代码 代码如下:

/**
*
* 爬虫起始类
* @author user
*
*/
public class StartCrawler {

package view.Util;

public static String[] excludeUrl=new String[]{ “.pom”, “.xml”,
“.md5”, “.sha1”, “.asc”, “.gz”, “.zip”, “../”}; // 要过滤的url后缀

import java.util.ArrayList;

public static Queue<String> waitForCrawlerUrls=new
LinkedList<String>(); // 等待爬取的url

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;
 }
}

private static int total=0;

Miaosha360buy.java

/**
* 解析网页内容
* @param webPageContent
*/
public static void parseWebPage(String webPageContent,String
realPath){
if(“”.equals(webPageContent)){
return;
}
Document doc=Jsoup.parse(webPageContent);
Elements links=doc.select(“a”); // 获取所有超链接元素
for(int i=0;i<links.size();i++){
Element link=links.get(i);
String url=link.attr(“href”);
System.out.println(“提取的url:”+(realPath+url));
boolean f=true;
for(int j=0;j<excludeUrl.length;j++){
if(url.endsWith(excludeUrl[j])){
f=false;
break;
}
}
if(f){ // 是我们需要的url
if(url.endsWith(“.jar”)){ // 目标地址
total++;
System.out.println(“发现第”+total+”个目标:”+(realPath+url));
}else{ // 要继续解析的Url
addUrl(realPath+url);
}
}
}
}

复制代码 代码如下:

/**
* 添加url到爬虫队列,假如队列中存在 就不添加
* @param string
*/
private static void addUrl(String url) {
if(url==null || “”.equals(url)){
return;
}
if(!waitForCrawlerUrls.contains(url)){
waitForCrawlerUrls.add(url);
System.out.println(url+”添加到爬虫队列”);
}
}

package jingdong;

/**
* 解析网页请求
* @param url 请求的url
*/
public static void parseUrl(){
while(waitForCrawlerUrls.size()>0){
String url=waitForCrawlerUrls.poll(); // 摘取第一个元素

public class Miaosha360buy {
 java.util.concurrent.CountDownLatch t= new
java.util.concurrent.CountDownLatch(1);

CloseableHttpClient httpClient=HttpClients.createDefault(); //
创建httpclient实例
HttpGet httpGet=new HttpGet(url); // 创建httpget实例
CloseableHttpResponse response=null;
try {
response=httpClient.execute(httpGet);
HttpEntity entity=response.getEntity(); // 获取返回实体
System.out.println(“内容类型:”+entity.getContentType().getValue());
if(“text/html”.equals(entity.getContentType().getValue())){
String webPageContent=EntityUtils.toString(entity, “utf-8”);
//System.out.println(“网页内容:”+webPageContent);
parseWebPage(webPageContent,url);
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(response!=null){
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
httpClient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

 /**
  * @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..”);
  }
 }

try {
Thread.sleep(1000); // 休息2秒钟
System.out.println(“休息1秒”);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

}

Miaosha360buy.java

private static void init(){
addUrl(“”);
addUrl(“”);
parseUrl();
}

复制代码 代码如下:

public static void main(String[] args) {
init();
}
}

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(“”);

  } 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(“”);
   openUrl.append(al.get(i).toString().subSequence(al.get(i).toString().lastIndexOf(‘/’)+1,
al.get(i).toString().lastIndexOf(‘.’)));
   openUrl.append(“.html”);
//   557673
   sb.append(“”);
   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=””;
  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,””);
//    }
    //用 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!”);
    }
    }
}

您可能感兴趣的文章:

  • php结合redis实现高并发下的抢购、秒杀功能的实例
  • Docker + Nodejs + Kafka + Redis +
    MySQL搭建简单秒杀环境
  • Javascript实现商品秒杀倒计时(时间与服务器时间同步)
  • PHP 类商品秒杀计时实现代码
  • 限时抢购秒杀系统架构分析与实战
  • jquery
    倒计时效果实现秒杀思路
  • Android开发必备:秒杀真机超快模拟器Genymotion介绍
  • PHP+JS实现的商品秒杀倒计时用法示例
  • 基于jQuery倒计时插件实现团购秒杀效果
  • Redis瞬时高并发秒杀方案总结

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注