Кратко представим функции
1. Время от времени (например, 1 минуту) извлекайте ссылку на продукт (мобильный телефон) со страницы JD Mobile Daily Flash Sale.
http://sale.360buy.com/act/8VTHFGr10CjMDyZ.html#01
2. Отправьте данные на серверную часть на основе извлеченной ссылки на продукт, чтобы получить цену продукта, описание, скидку, инвентарь (наличие ли на складе) и другую информацию.
3. Делайте выводы на основе полученной информации.
Если условия выполнены, будет автоматически вызван браузер (при условии, что в переменную окружения добавлен chrome или изменен код с добавлением в код пути браузера.exe, а также модифицирована программа) для открытия заказа товара. страница.
4. Фактически это решает проблему: вам больше не нужно часто обновлять веб-страницу или проверять ее самостоятельно;
Вход в систему и отправку заказов должен решаться браузером (кажется, эти функциональные моменты более сложны и не обработаны)
Программа не идеальна:
Есть несколько мест, которые необходимо изменить перед запуском:
1. Переменные среды: Chrome добавляет переменные браузера для удобства вызова. . Либо самостоятельно модифицируйте исходный код и откройте его другими способами.
2. Необходимо установить информацию о цене каждого продукта в действии. Это нехорошо, исходный код надо модифицировать.
Модификация находится в функции filter().
3. Еще одно место, которое необходимо изменить:
hasStore (строка skuidkey)
адрес="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
Скопируйте код кода следующим образом:
представление пакета.Util;
импортировать java.util.ArrayList;
общественный класс Util {
public static void print(Object o){
System.out.print(о);
}
public static void println(Object o){
если (нуль == о)
Система.out.println();
еще
System.out.println(о);
}
public static ArrayList<Integer> toArrayList(int[] ints){
если (ints.length == 0)
вернуть ноль;
ArrayList<Integer> al=new ArrayList<Integer>();
for(int i=0;i<ints.length;i++){
al.add(ints[i]);
}
вернуть аль;
}
}
Миаоша360buy.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() + «старт»);
Miaosha360buy ms360=новый Miaosha360buy();
новый ThreadOne360buy(ms360.t).start();
в то время как (правда) {
пытаться {
ms360.t.await();
} catch (InterruptedException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
}
пытаться {
Thread.sleep(1000*60); // Вызывается каждую минуту?
} catch (InterruptedException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
}
ms360.t = новый java.util.concurrent.CountDownLatch(1);
новый ThreadOne360buy(ms360.t).start();
System.out.println("Новый шаг через некоторое время..");
}
}
}
Миаоша360buy.java
Скопируйте код кода следующим образом:
пакет Jingdong;
общественный класс 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() + "старт");
Miaosha360buy ms360=новый Miaosha360buy();
новый ThreadOne360buy(ms360.t).start();
в то время как (правда) {
пытаться {
ms360.t.await();
} catch (InterruptedException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
}
пытаться {
Thread.sleep(1000*60); // Вызывается каждую минуту?
} catch (InterruptedException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
}
ms360.t = новый java.util.concurrent.CountDownLatch(1);
новый 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;
импортировать представление.Util.Util;
публичный класс ThreadOne360buy расширяет Thread{
java.util.concurrent.CountDownLatch c;
ArrayList al;//Запись страницы флэш-распродажи продукта
плавающая цена=0.0f;//цена продукта
float Discount=0.0f;//Скидка на товар
//Используется для сохранения информации о потоке, в этом проекте это не очень полезно
частный статический List<Thread> RunningThreads = новый ArrayList<Thread>();
//Это счетчик (не очень хорошо его использовать, потоки всегда казались более сложными)
public ThreadOne360buy(java.util.concurrent.CountDownLatch c) {
это.с=с;
}
@Override
общественный недействительный запуск () {
Register(this);//Регистрируемся при запуске потока
// печатаем начальный тег
System.out.println(Thread.currentThread().getName() + "Начать...");
пытаться {
//Посмотрите страницу флэш-продажи мобильного телефона Jingdong
this.getMessage("http://sale.360buy.com/act/8VTHFGr10CjMDyZ.html#01");
} catch (ClientProtocolException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
в.countDown();
} catch (IOException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
в.countDown();
}
в.countDown();
unRegist(this);//Отменяем регистрацию, когда поток заканчивается
// печатаем закрывающий тег
System.out.println(Thread.currentThread().getName() + "Конец.");
}
публичный недействительный регистр (Тема t) {
синхронизировано (runningThreads) {
RunningThreads.add(т);
}
}
public void unRegist(Thread t) {
синхронизировано (runningThreads) {
RunningThreads.remove (т);
}
}
public static boolean hasThreadRunning() {
// Оценивая, пуст ли RunningThreads, вы можете узнать, есть ли еще невыполненные потоки.
возврат (runningThreads.size() > 0);
}
/**
* Получите ссылку на продукт, номер продукта, ключ skuidkey, цену и информацию о магазине со страницы продажи мобильных флэш-памяти.
* URL-адрес @param: страница продажи флэш-памяти для мобильных устройств.
* @throws ClientProtocolException
* @throwsIOException
*/
public void getMessage (String url) выдает ClientProtocolException, IOException {
аль = getMainUrl (вниз (URL));
Util.println(ал);
если(al.size()==0){
в.countDown();
Система.выход(0);
возвращаться;
}
for(int i=0;i<al.size();i++){
StringBuffer sb = новый StringBuffer ();
StringBuffer openUrl = новый 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+") down:"+sb.toString());
HashMap<String, String> hm=parseProduct(down(sb.toString()));
//Используется для сопоставления информации о цене. Сопоставить информацию об инвентаре
filter(hm,openUrl.toString());//Фильтруем цену и открываем браузер, если условия выполнены
}
}
/**
* Метод проверки
* @param хм содержит информацию о ценах
* @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("----------------------------------------");
//Уменьшаем счетчик, чтобы основной поток мог оценить
в.countDown();
//Должны ли мы завершить дочерний поток?
возвращаться;
}
if(hm.get("skuid").equals("201602")){//Judgement//Motorola 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")){//Tianyu skuid=675647
////Цена здесь жестко запрограммирована, и ее необходимо изменить перед запуском.
//this.setPrice(699.0f);
////Нужно ли открывать консоль?
//if(Float.parseFloat(hm.get("price"))<=this.getPrice()){
//view.Util.oenCMD.openWinExe(null,url);
//}
}
}
/**
* Разобрал название, скуид, информацию о цене на странице товара
* @paramdoc
* @возвращаться
*/
public static HashMap<String, String> parseProduct(Document doc){
Строка text=doc.text();
String docc=text.substring(text.indexOf("master")+9,text.indexOf("фитинги")-3).replaceAll("[//s]", "");
String[] ss=docc.split(",");
HashMap<String, String> hm=new HashMap<String, String>();
for(String it: ss){
String string=it.replaceAll("/"", "");
если(string.contains("//u"))
строка = unicodeDecode (строка);
String[] str=string.split(":");
хм.пут(стр[0], стр[1]);
}
Util.println(хм);
вернись, хм;
}
/**
* Обработка символов Юникода и преобразование их в отображаемые символы (китайские символы), что не очень универсально.
* @param it: /u6a5d
* @возвращаться
*/
public static String unicodeDecode(String it){//Одним из недостатков является то, что предыдущие символы невозможно удалить.
Util.println(оно);
Строковое регулярное выражение="(////u[0-9a-f]{4})";
Шаблон pt= Pattern.compile(регулярное выражение);
Матчер MC;
StringBuffer сб;
StringBuffer sba = новый StringBuffer ();
MC = pt.matcher (оно);
в то время как (mc.find()) {
сб = новый StringBuffer ();
mc.appendReplacement(sba,sb.append((char)Integer.parseInt((mc.group(1).substring(2)), 16)).toString());
}
вернуть sba.toString();
}
/**
* Возврат объекта документа (загрузка содержимого)
* @param URL-адрес страницы загрузки
* @возвращаться
* @throws ClientProtocolException
* @throwsIOException
*/
общедоступный статический документ вниз (String url) выдает ClientProtocolException, IOException {
Документ документа = ноль;
DefaultHttpClient httpClient=новый DefaultHttpClient();
Util.println("Загрузка:"+url);
HttpGet get = новый HttpGet (url);
Ответ HttpResponse;
ответ = httpClient.execute(получить);
Объект HttpEntity = response.getEntity();
doc = Jsoup.parse(entity.getContent(), "utf-8","");
//Освобождаем ресурсы
EntityUtils.consume(сущность);
//Закрываем соединение
httpClient.getConnectionManager().shutdown();
вернуть документ;
}
/**
* Добавлена информация по управлению кодированием.
* @param URL-адрес страницы для загрузки
* Кодировка кода @param
* @возвращаться
* @throws ClientProtocolException
* @throwsIOException
*/
общедоступный статический документ вниз (String url, String code) выдает ClientProtocolException, IOException {
Документ документа = ноль;
DefaultHttpClient httpClient=новый DefaultHttpClient();
Util.println("Загрузка:"+url);
HttpGet get = новый HttpGet (url);
Ответ HttpResponse;
ответ = httpClient.execute(получить);
Объект HttpEntity = response.getEntity();
doc = Jsoup.parse(entity.getContent(), code, "");
//Освобождаем ресурсы
EntityUtils.consume(сущность);
//Закрываем соединение
httpClient.getConnectionManager().shutdown();
вернуть документ;
}
/**
* Используется для анализа ссылок на товары (коллекции) на страницах флеш-продаж.
* @paramdoc
* @возвращаться
*/
public static ArrayList<String> getMainUrl(Document doc){
if(doc.equals("")||doc==null)
вернуть ноль;
пытаться {
Thread.sleep(50);
} catch (InterruptedException e1) {
// TODO Автоматически сгенерированный блок catch
e1.printStackTrace();
}
ArrayList<String> urls = новый ArrayList<String>();
String rule="map[name=Map] >area[href~=product]";
/**
* Начать разбор
*/
Элементы elements=doc.select(правило);
for (Элемент e: элементы) {
//Util.println(e.absUrl("abs:href"));
urls.add(e.absUrl("abs:href"));
}
обратные URL-адреса;
}
/**
* Получите skuidkey для запроса информации о запасах продуктов.
* URL-адрес @param
* @возвращаться
*/
публичная статическая строка parseSkuidkey (URL-адрес строки) {
Документ док=ноль;
пытаться {
документ = вниз (url, «gb2312»);
} catch (ClientProtocolException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
} catch (IOException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
}
//Util.println(doc.select("script"));
Строковый текст = ноль;
for(Элемент e: doc.select("script")){
if(e.data().contains("skuidkey:")){
текст = е.данные ();
перерыв;
}
}
//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){//Это место не обрабатывается, извлекайте информацию напрямую в браузере
Строковый адрес = ноль;
логическое значение hasStore = false;
if(skuidkey!=null && !"".equals(skuidkey))
адрес="http://price.360buy.com/stocksoa/StockHandler.ashx?callback=getProvinceStockCallback&type=pcastock&skuid="+skuidkey+"&provinceid=1&cityid=2800&areaid=2850";
еще{
Util.println("Ошибка при разборе skuidkey");
}
пытаться {
если(parseStore(вниз(адрес))){
имеетStore = истина;
}
} catch (ClientProtocolException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
} catch (IOException e) {
// TODO Автоматически сгенерированный блок catch
е.printStackTrace();
}
вернуть hasStore;
}
/* if(array[1]=="34"||array[1]=="18"){
изменитьКарта (ложь);
djdarea.stockInfoDom.html("<strong class='store-over'>Нет в наличии</strong>");
}
иначе если(массив[1]=="0"){
изменитьКарта (ложь);
djdarea.stockInfoDom.html("<strong class='store-over'>Нет в наличии</strong>");
}
иначе if(array[2]=="0"&&array[4]!="2"){
изменитьКарта (ложь);
djdarea.stockInfoDom.html("К сожалению, этот товар не может быть доставлен в выбранный вами регион");
}
иначе if(array[1]=="33"||array[1]=="5"){
ChangeCart (истина);
djdarea.stockInfoDom.html("<strong>Точка</strong>"+(array[4]=="1"?", область"+(array[3]=="0"?"Нет":" ")+"Поддержка наложенного платежа":"")+cashdesc);
}
иначе если(массив[1]=="36"){
ChangeCart (истина);
djdarea.stockInfoDom.html("<strong>Бронирование</strong>"+(array[4]=="1"?", область"+(array[3]=="0"?"Нет":" ")+"Поддержка наложенного платежа":"")+cashdesc);
}
иначе если(массив[1]=="39"){
ChangeCart (истина);
djdarea.stockInfoDom.html("<strong>В пути</strong>"+(array[4]=="1"?", область"+(array[3]=="0"?"Нет": " ")+"Поддержка наложенного платежа":"")+cashdesc);
}
иначе если(массив[1]=="40"){
ChangeCart (истина);
djdarea.stockInfoDom.html("<strong>Доступно для распространения</strong>"+(array[4]=="1"?", эта область"+(array[3]=="0"?"Нет" :"")+"Поддержка наложенным платежом":"")+cashdesc);
}
*/
/**
* Анализ инвентарной информации
* @paramdoc
* @возвращаться
*/
public static boolean parseStore(Document doc){
Строка text=doc.text();
String docc=text.substring(text.indexOf("-")-1,text.lastIndexOf(",")-1);
Util.println(документ);
String[] store=docc.split("-");
if(store[1].equals("34") || store[1].equals("18")){
//распродано
Util.println("Здесь нет в наличии");
вернуть ложь;
}else if(store[1].equals("33") || store[1].equals("5")){
//Спотовые товары
Util.println("В наличии здесь");
вернуть истину;
}
Util.println(магазин[1]);
вернуть ложь;
}
//Несколько методов компонента
общедоступное число с плавающей запятой getPrice() {
цена возврата;
}
public void setPrice(плавающая цена) {
this.price = цена;
}
общедоступное число с плавающей запятой getDiscount() {
возвратная скидка;
}
public void setDiscount(плавающая скидка) {
this.discount = скидка;
}
}
oenCMD.java
Скопируйте код кода следующим образом:
представление пакета.Util;
публичный класс oenCMD {
//public static void main(String[] args) {
//// openWinExe(null);
// openExe(null, "http://www.baidu.com");
// }
//Используйте Java для вызова exe-файла системы Windows, например блокнота, калькулятора и т. д.
public static void openWinExe (команда String, URL-адрес строки) {
if(command==null ||command.equals("")){
команда = "хром" + URL;
}
Время выполнения rn = Runtime.getRuntime();
Процесс p = ноль;
пытаться {
р = rn.exec (команда);
} catch (Исключение е) {
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 = ноль;
пытаться {
р = rn.exec(pathAndName);
} catch (Исключение е) {
System.out.println("Ошибка выполнения!");
}
}
}