機能を簡単に紹介
1. JD Mobile Daily Flash Sale ページから製品 (携帯電話) リンクを時々 (1 分など) 抽出します。
http://sale.360buy.com/act/8VTHFGr10CjMDyZ.html#01
2. 抽出された製品リンクに基づいてデータをバックエンドに送信し、製品の価格、説明、割引、在庫 (在庫があるかどうか) などの情報を取得します。
3. 得られた情報に基づいて判断する。
条件が満たされると、ブラウザが自動的に呼び出され (環境変数に chrome が追加されているか、コードに browser.exe パスが追加されるようにコードが変更され、プログラムが変更されている場合に限ります)、製品の注文画面が開きます。ページ。
4. 実際、これにより問題が解決されます。Web ページを頻繁に更新したり、自分で確認したりする必要がなくなりました。
ログインと注文の送信はブラウザーで解決する必要があります (これらの機能点はより複雑であり、処理されていないようです)
プログラムは完璧ではありません:
実行前に変更する必要がある場所がいくつかあります。
1. 環境変数: chrome は、簡単に呼び出せるようにブラウザ変数を追加します。 。または、ソース コードを自分で変更して、他の方法で開きます。
2. アクティビティ内の各製品の価格情報を設定する必要があります。これは良くありません。ソース コードを変更する必要があります。
変更は filter() 関数内にあります。
3. 変更が必要なもう 1 つの場所は次のとおりです。
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 を押すと、「都市」、地域、その他の情報を変更した後、バックグラウンドに送信された取得リクエストが表示されます。このリンクには必要な情報が含まれています。 (http://price.360buy.com/stocksoa/StockHandler.ashx?callback=getProvinceStockCallback&type=pcastock&skuid=64EBD0F20F593D95C72C6EED59B64658&provinceid=1&cityid=2805&areaid=2854) 適切に変更します。
ユーティリティ.java
次のようにコードをコピーします。
パッケージビュー。ユーティリティ;
java.util.ArrayListをインポートします。
パブリック クラス ユーティリティ {
public static void print(Object o){
System.out.print(o);
}
public static void println(Object o){
if(null==o)
System.out.println();
それ以外
System.out.println(o);
}
public static ArrayList<Integer> toArrayList(int[] ints){
if(ints.length==0)
null を返します。
ArrayList<整数> al=new ArrayList<整数>();
for(int i=0;i<ints.length;i++){
al.add(ints[i]);
}
アルを返します。
}
}
Miaosha360buy.java
次のようにコードをコピーします。
パッケージ京東;
パブリック クラス Miaosha360buy {
java.util.concurrent.CountDownLatch t= 新しい java.util.concurrent.CountDownLatch(1);
/**
* @param 引数
*/
public static void main(String[] args) {
// TODO 自動生成されたメソッド スタブ
System.out.println(Thread.currentThread().getName() + "start");
Miaosha360buy ms360=new Miaosha360buy();
new ThreadOne360buy(ms360.t).start();
while(true){
試す {
ms360.t.await();
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
試す {
Thread.sleep(1000*60); // 1 分ごとに呼び出されますか?
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
ms360.t=新しい java.util.concurrent.CountDownLatch(1);
new ThreadOne360buy(ms360.t).start();
System.out.println("しばらくの間新しいトレッド..");
}
}
}
Miaosha360buy.java
次のようにコードをコピーします。
パッケージ京東;
パブリック クラス Miaosha360buy {
java.util.concurrent.CountDownLatch t= 新しい java.util.concurrent.CountDownLatch(1);
/**
* @param 引数
*/
public static void main(String[] args) {
// TODO 自動生成されたメソッド スタブ
System.out.println(Thread.currentThread().getName() + "start");
Miaosha360buy ms360=new Miaosha360buy();
new ThreadOne360buy(ms360.t).start();
while(true){
試す {
ms360.t.await();
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
試す {
Thread.sleep(1000*60); // 1 分ごとに呼び出されますか?
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
ms360.t=新しい java.util.concurrent.CountDownLatch(1);
new ThreadOne360buy(ms360.t).start();
System.out.println("しばらくの間新しいトレッド..");
}
}
}
ThreadOne360buy.java
次のようにコードをコピーします。
パッケージ京東;
インポート java.io.IOException;
java.util.ArrayListをインポートします。
java.util.HashMapをインポートします。
java.util.Listをインポートします。
java.util.regex.Matcherをインポートします。
java.util.regex.Patternをインポートします。
org.apache.http.HttpEntity をインポートします。
org.apache.http.HttpResponse をインポートします。
org.apache.http.client.ClientProtocolException をインポートします。
org.apache.http.client.methods.HttpGet をインポートします。
org.apache.http.impl.client.DefaultHttpClientをインポートします。
org.apache.http.util.EntityUtils をインポートします。
org.jsoup.Jsoup をインポートします。
org.jsoup.nodes.Document をインポートします。
org.jsoup.nodes.Element をインポートします。
org.jsoup.select.Elements をインポートします。
インポート view.Util.Util;
public class ThreadOne360buy extends Thread{
java.util.concurrent.CountDownLatch c;
ArrayList al;//フラッシュセール商品ページを記録
float Price=0.0f;//商品価格
floatdiscount=0.0f;//製品割引
//スレッド情報を保存するために使用されますが、このプロジェクトではあまり役に立ちません
private static List<Thread> runningThreads = new ArrayList<Thread>();
// これはカウンターです (使い方があまり上手ではありません。スレッドはいつもより複雑に感じられます)
public ThreadOne360buy(java.util.concurrent.CountDownLatch c) {
これ.c=c;
}
@オーバーライド
public void run() {
register(this);//スレッドの開始時に登録します
// 開始タグを出力します
System.out.println(Thread.currentThread().getName() + "開始...");
試す {
//京東の携帯電話フラッシュセールページをキャッチ
this.getMessage("http://sale.360buy.com/act/8VTHFGr10CjMDyZ.html#01");
} catch (ClientProtocolException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
c.countDown();
} キャッチ (IOException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
c.countDown();
}
c.countDown();
unRegist(this);//スレッドが終了したら登録を解除する
// 終了タグを出力します
System.out.println(Thread.currentThread().getName() + "終了");
}
public void register(スレッド t) {
同期済み (runningThreads) {
runningThreads.add(t);
}
}
public void unRegist(Thread t) {
同期済み (runningThreads) {
runningThreads.remove(t);
}
}
public static boolean hasThreadRunning() {
// runningThreads が空かどうかを判断することで、まだ実行されていないスレッドがあるかどうかを知ることができます。
return (runningThreads.size() > 0);
}
/**
※モバイルフラッシュセールページから製品リンク、製品skuid、skuidkey、価格、店舗情報を取得します
* @param URL: モバイルフラッシュセールページ
* @throws ClientProtocolException
* @throwsIOException
*/
public void getMessage(String url) throws ClientProtocolException, IOException{
al=getMainUrl(ダウン(url));
Util.println(al);
if(al.size()==0){
c.countDown();
System.exit(0);
戻る;
}
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());
//マップに保存されるのは商品名、価格、割引情報です。
Util.println("Al("+i+") ダウン:"+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);
// まず在庫を確認しましょうか?
文字列 skuidkey=parseSkuidkey(url);
if(!hasStore(skuidkey)){
Util.println("----------------------------------------");
Util.println("在庫切れ!");
Util.println("----------------------------------------");
//メインスレッドが判断できるようにカウントを減らす
c.countDown();
// 子スレッドを終了する必要がありますか?
戻る;
}
if(hm.get("skuid").equals("201602")){//判断//モトローラ skuid=201602
//ここの価格はハードコーディングされているため、実行前に変更する必要があります。
this.setPrice(499.0f);
// コンソールを開く必要がありますか?
if(Float.parseFloat(hm.get("価格"))<=this.getPrice()){
view.Util.oenCMD.openWinExe(null,url);
}
}else if(hm.get("skuid").equals("675647")){//Tianyu skuid=675647
////ここの価格はハードコーディングされているため、実行前に変更する必要があります。
//this.setPrice(699.0f);
////コンソールを開く必要がありますか?
//if(Float.parseFloat(hm.get("価格"))<=this.getPrice()){
//view.Util.oenCMD.openWinExe(null,url);
//}
}
}
/**
* 製品ページの名前、skuid、価格情報を解析しました
* @paramdoc
* @戻る
*/
public static HashMap<String, String> parseProduct(Document doc){
文字列テキスト=doc.text();
String docc=text.substring(text.indexOf("マスター")+9,text.indexOf("継手")-3).replaceAll("[//s]", "");
String[] ss=doc.split(",");
HashMap<String, String> hm=new HashMap<String, String>();
for(文字列: ss){
文字列 string=it.replaceAll("/"", "");
if(string.contains("//u"))
文字列=unicodeDecode(文字列);
String[] str=string.split(":");
hm.put(str[0], str[1]);
}
Util.println(hm);
うーん、返してください。
}
/**
※ Unicode 文字を処理して表示文字(漢字)に変換しますが、汎用性は高くありません。
* @param it: /u6a5d
* @戻る
*/
public static String unicodeDecode(String it){//1 つの欠点は、前の文字を削除できないことです。
Util.println(it);
文字列正規表現="(////u[0-9a-f]{4})";
パターン pt= Pattern.compile(regex);
マッチャーMC;
文字列バッファsb;
StringBuffer sba=new StringBuffer();
mc=pt.matcher(it);
while(mc.find()){
sb=新しいStringBuffer();
mc.appendReplacement(sba,sb.append((char )Integer.parseInt((mc.group(1).substring(2)), 16)).toString());
}
sba.toString() を返します。
}
/**
* ドキュメント オブジェクト (ダウンロード コンテンツ) を返す
* @param URL ダウンロードページ
* @戻る
* @throws ClientProtocolException
* @throwsIOException
*/
public static Document down(String url) throws ClientProtocolException、IOException{
ドキュメント doc = null;
DefaultHttpClient httpClient=new DefaultHttpClient();
Util.println("DownLoad:"+url);
HttpGet get=new HttpGet(url);
HttpResponse 応答;
応答 = httpClient.execute(get);
HttpEntity エンティティ = response.getEntity();
doc = Jsoup.parse(entity.getContent(), "utf-8","");
//リソースを解放する
EntityUtils.consume(エンティティ);
//接続を閉じます
httpClient.getConnectionManager().shutdown();
ドキュメントを返します。
}
/**
* エンコード制御情報を追加
* @param ダウンロードするURLページ
* @param コードエンコーディング
* @戻る
* @throws ClientProtocolException
* @throwsIOException
*/
public static Document down(String url,String code) throws ClientProtocolException, IOException{
ドキュメント doc = null;
DefaultHttpClient httpClient=new DefaultHttpClient();
Util.println("DownLoad:"+url);
HttpGet get=new HttpGet(url);
HttpResponse 応答;
応答 = httpClient.execute(get);
HttpEntity エンティティ = response.getEntity();
doc = Jsoup.parse(entity.getContent(), コード,"");
//リソースを解放する
EntityUtils.consume(エンティティ);
//接続を閉じます
httpClient.getConnectionManager().shutdown();
ドキュメントを返します。
}
/**
* フラッシュ セール ページの製品 (コレクション) リンクを解析するために使用されます
* @paramdoc
* @戻る
*/
public static ArrayList<String> getMainUrl(Document doc){
if(doc.equals("")||doc==null)
null を返します。
試す {
Thread.sleep(50);
} catch (InterruptedException e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}
ArrayList<String> urls=new ArrayList<String>();
文字列ルール="マップ[名前=マップ] >エリア[href~=製品]";
/**
* 解析を開始します
*/
要素 elements=doc.select(rule);
for (要素 e : 要素) {
//Util.println(e.absUrl("abs:href"));
urls.add(e.absUrl("abs:href"));
}
URLを返します。
}
/**
* 製品の在庫情報を照会するための skuidkey を取得します
* @param URL
* @戻る
*/
public static String parseSkuidkey(String url){
ドキュメント doc=null;
試す {
doc=down(url,"gb2312");
} catch (ClientProtocolException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
} キャッチ (IOException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
//Util.println(doc.select("script"));
文字列テキスト = null;
for(要素 e : doc.select("スクリプト")){
if(e.data().contains("skuidkey:")){
テキスト=e.data();
壊す;
}
}
//skuidkey:'7D45919EA8242511DAA5CC7C6D7B351C'
text=text.substring(text.indexOf("skuidkey:")+10, text.indexOf("skuidkey:")+42);
Util.println("--------------------------------");
Util.println(テキスト);
テキストを返します。
}
/**
※在庫情報を見る
* @param skuidkey
* @戻る
*/
public static boolean hasStore(String skuidkey){//この場所は処理されず、ブラウザ内の情報を直接抽出します
文字列アドレス = null;
ブール値 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";
それ以外{
Util.println("skuidkey の解析中にエラーが発生しました");
}
試す {
if(parseStore(down(アドレス))){
hasStore=true;
}
} catch (ClientProtocolException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
} キャッチ (IOException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
hasStore を返します。
}
/* if(配列[1]=="34"||配列[1]=="18"){
changeCart(false);
djdarea.stockInfoDom.html("<strong class='store-over'>在庫切れ</strong>");
}
else if(配列[1]=="0"){
changeCart(false);
djdarea.stockInfoDom.html("<strong class='store-over'>在庫切れ</strong>");
}
else if(配列[2]=="0"&&配列[4]!="2"){
changeCart(false);
djdarea.stockInfoDom.html("申し訳ありませんが、この商品は選択した地域には配送できません");
}
else if(配列[1]=="33"||配列[1]=="5"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>スポット</strong>"+(配列[4]=="1"?", エリア"+(配列[3]=="0"?"いいえ":" ")+"代金引換をサポート":"")+cashdesc);
}
else if(配列[1]=="36"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>予約</strong>"+(array[4]=="1"?", エリア"+(array[3]=="0"?"いいえ":" ")+"代金引換をサポート":"")+cashdesc);
}
else if(配列[1]=="39"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>輸送中</strong>"+(array[4]=="1"?", エリア"+(array[3]=="0"?"No": " ")+"代金引換サポート":"")+cashdesc);
}
else if(配列[1]=="40"){
changeCart(true);
djdarea.stockInfoDom.html("<strong>配布可能</strong>"+(array[4]=="1"?", このエリアは"+(array[3]=="0"?"いいえ" :"")+"代金引換サポート":"")+cashdesc);
}
*/
/**
* インベントリ情報を解析します
* @paramdoc
* @戻る
*/
public static boolean parseStore(Document doc){
文字列テキスト=doc.text();
文字列 docc=text.substring(text.indexOf("-")-1,text.lastIndexOf(",")-1);
Util.println(docc);
String[] ストア=docc.split("-");
if(store[1].equals("34") || store[1].equals("18")){
//在庫切れ
Util.println("ここは在庫切れです");
false を返します。
}else if(store[1].equals("33") || store[1].equals("5")){
//スポットグッズ
Util.println("在庫はここにあります");
true を返します。
}
Util.println(ストア[1]);
false を返します。
}
//いくつかの Bean メソッド
public float getPrice() {
返品価格。
}
public void setPrice(浮動価格) {
this.price = 価格;
}
public float getDiscount() {
返品割引;
}
public void setDiscount(Float 割引) {
this.discount = 割引;
}
}
oenCMD.java
次のようにコードをコピーします。
パッケージビュー。ユーティリティ;
パブリック クラス oenCMD {
//public static void main(String[] args) {
//// openWinExe(null);
// openExe(null,"http://www.baidu.com");
// }
//Java を使用して、メモ帳、計算機などの Windows システムの exe ファイルを呼び出します。
public static void openWinExe(文字列コマンド,文字列URL) {
if(command==null ||command.equals("")){
コマンド = "クロム"+url;
}
ランタイム rn = Runtime.getRuntime();
プロセス p = null;
試す {
p = rn.exec(コマンド);
} catch (例外 e) {
System.out.println("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("")){
パスと名前+=" ";
パスと名前+=url;
}
ランタイム rn = Runtime.getRuntime();
プロセス p = null;
試す {
p = rn.exec(パスと名前);
} catch (例外 e) {
System.out.println("実行エラー!");
}
}
}