Briefly introduce the functions
1. Extract the product (mobile phone) link from the JD Mobile Daily Flash Sale page every once in a while (such as 1 minute).
http://sale.360buy.com/act/8VTHFGr10CjMDyZ.html#01
2. Send data to the backend based on the extracted product link to obtain product price, description, discount, inventory (whether in stock) and other information.
3. Make judgments based on the information obtained.
If the conditions are met, the browser will be automatically called (provided that chrome is added to the environment variable, or the code is changed to add the browser.exe path to the code, and the program is modified) to open the product ordering page.
4. In fact, this solves a problem: you no longer need to refresh the web page frequently or check it yourself;
Logging in and submitting orders must be solved by the browser (it seems that these functional points are more complicated and have not been processed)
The program is not perfect:
There are several places that need to be modified before running:
1. Environment variables: chrome adds browser variables for easy calling. . Or modify the source code yourself and open it in other ways.
2. The price information of each product in the activity needs to be set. This is not good, the source code must be modified.
The modification is in the filter() function.
3. Another place that needs to be modified is
hasStore(String skuidkey)
address="http://price.360buy.com/stocksoa/StockHandler.ashx?callback=getProvinceStockCallback&type=pcastock&skuid="+skuidkey+"&provinceid=1&cityid=2800&areaid=2850";
The cityid=2800&areaid=...location information of this place. This was not processed. You need to figure it out yourself from the mobile phone product page.
It's actually relatively simple. chrome+F12, after modifying the "city", region and other information, you will see a get request sent to the background. This link contains the required information. (http://price.360buy.com/stocksoa/StockHandler.ashx?callback=getProvinceStockCallback&type=pcastock&skuid=64EBD0F20F593D95C72C6EED59B64658&provinceid=1&cityid=2805&areaid=2854) Modify appropriately.
Util.java
Copy the code code as follows:
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
Copy the code code as follows:
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() + "start");
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); // Called every 1 minute?
} 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
Copy the code code as follows:
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() + "start");
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); // Called every 1 minute?
} 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
Copy the code code as follows:
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;//Record flash sale product page
float price=0.0f;//product price
float discount=0.0f;//Product discount
//Used to save thread information, not very useful in this project
private static List<Thread> runningThreads = new ArrayList<Thread>();
//This is a counter (not very good at using it, threads have always felt more complicated)
public ThreadOne360buy(java.util.concurrent.CountDownLatch c) {
this.c=c;
}
@Override
public void run() {
register(this);//Register when the thread starts
// print start tag
System.out.println(Thread.currentThread().getName() + "Start...");
try {
//Catch the Jingdong mobile phone flash sale page
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);//Unregister when the thread ends
// print end tag
System.out.println(Thread.currentThread().getName() + "End.");
}
public void register(Thread t) {
synchronized (runningThreads) {
runningThreads.add(t);
}
}
public void unRegist(Thread t) {
synchronized (runningThreads) {
runningThreads.remove(t);
}
}
public static boolean hasThreadRunning() {
// By judging whether runningThreads is empty, you can know whether there are any threads that have not yet been executed.
return (runningThreads.size() > 0);
}
/**
* Obtain the prodcut link, product skuid, skuidkey, price, and store information from the mobile flash sale page
* @param url: mobile flash sale page
* @throws ClientProtocolException
* @throwsIOException
*/
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());
//What is saved in the map is the product name, price, and discount information.
Util.println("Al("+i+") down:"+sb.toString());
HashMap<String, String> hm=parseProduct(down(sb.toString()));
//Used to match price information. Match inventory information
filter(hm,openUrl.toString());//Filter the price and open the browser if the conditions are met
}
}
/**
* A verification method
* @param hm holds price information
* @param url product page
*/
public void filter(HashMap<String, String> hm,String url){//url is the product page
//view.Util.oenCMD.openWinExe(null,url);
//Should we check the inventory first?
String skuidkey=parseSkuidkey(url);
if(!hasStore(skuidkey)){
Util.println("----------------------------------------");
Util.println("Out of stock!");
Util.println("----------------------------------------");
//Decrease the count so that the main thread can judge
c.countDown();
//Should we end the child thread?
return;
}
if(hm.get("skuid").equals("201602")){//Judgement//Motorola skuid=201602
//The price here is hard-coded and needs to be changed before running.
this.setPrice(499.0f);
//Should the console be opened?
if(Float.parseFloat(hm.get("price"))<=this.getPrice()){
view.Util.oenCMD.openWinExe(null,url);
}
}else if(hm.get("skuid").equals("675647")){//Tianyu skuid=675647
////The price here is hard-coded and needs to be changed before running.
//this.setPrice(699.0f);
////Should the console be opened?
//if(Float.parseFloat(hm.get("price"))<=this.getPrice()){
//view.Util.oenCMD.openWinExe(null,url);
//}
}
}
/**
* Parsed the name, skuid, price information in the product page
* @paramdoc
* @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;
}
/**
* Process unicode characters and convert them into display characters (Chinese characters), which is not very versatile.
* @param it: /u6a5d
* @return
*/
public static String unicodeDecode(String it){//One disadvantage is that the previous characters cannot be removed
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();
}
/**
* Return document object (download content)
* @param url download page
* @return
* @throws ClientProtocolException
* @throwsIOException
*/
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","");
//Release resources
EntityUtils.consume(entity);
//Close the connection
httpClient.getConnectionManager().shutdown();
return doc;
}
/**
* Added encoding control information
* @param url page to be downloaded
* @param code encoding
* @return
* @throws ClientProtocolException
* @throwsIOException
*/
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,"");
//Release resources
EntityUtils.consume(entity);
//Close the connection
httpClient.getConnectionManager().shutdown();
return doc;
}
/**
* Used to parse product (collection) links in flash sale pages
* @paramdoc
* @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]";
/**
* Start parsing
*/
Elements elements=doc.select(rule);
for (Element e : elements) {
//Util.println(e.absUrl("abs:href"));
urls.add(e.absUrl("abs:href"));
}
return urls;
}
/**
* Obtain skuidkey for querying product inventory information
* @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;
}
/**
* View inventory information
* @param skuidkey
* @return
*/
public static boolean hasStore(String skuidkey){//This place is not processed, directly extract the information in the browser
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("Error in parsing 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'>Out of stock</strong>");
}
else if(array[1]=="0"){
changeCart(false);
djdarea.stockInfoDom.html("<strong class='store-over'>Out of stock</strong>");
}
else if(array[2]=="0"&&array[4]!="2"){
changeCart(false);
djdarea.stockInfoDom.html("Sorry, this product cannot be delivered to the area you selected");
}
else if(array[1]=="33"||array[1]=="5"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>Spot</strong>"+(array[4]=="1"?", the area"+(array[3]=="0"?"No":" ")+"Support cash on delivery":"")+cashdesc);
}
else if(array[1]=="36"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>Booking</strong>"+(array[4]=="1"?", the area"+(array[3]=="0"?"No":" ")+"Support cash on delivery":"")+cashdesc);
}
else if(array[1]=="39"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>In transit</strong>"+(array[4]=="1"?", the area"+(array[3]=="0"?"No":" ")+"Support cash on delivery":"")+cashdesc);
}
else if(array[1]=="40"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>Available for distribution</strong>"+(array[4]=="1"?", this area"+(array[3]=="0"?"No" :"")+"Support cash on delivery":"")+cashdesc);
}
*/
/**
* Parse inventory information
* @paramdoc
* @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")){
//out of stock
Util.println("Out of stock here");
return false;
}else if(store[1].equals("33") || store[1].equals("5")){
//Spot goods
Util.println("In stock here");
return true;
}
Util.println(store[1]);
return false;
}
//Several bean methods
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
Copy the code code as follows:
package view.Util;
public class oenCMD {
//public static void main(String[] args) {
//// openWinExe(null);
// openExe(null,"http://www.baidu.com");
// }
//Use Java to call the exe file of the windows system, such as notepad, calc, etc.
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!");
}
}
//Call other executable files, such as exe made by yourself, or downloaded and installed software.
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!");
}
}
}