package com.yeshi.fanli.job;
|
|
import java.math.BigDecimal;
|
import java.text.SimpleDateFormat;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
|
import javax.annotation.Resource;
|
|
import org.quartz.Job;
|
import org.quartz.JobDataMap;
|
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionException;
|
|
import com.yeshi.fanli.entity.bus.lable.BoutiqueAutoRule;
|
import com.yeshi.fanli.entity.bus.lable.Label;
|
import com.yeshi.fanli.entity.bus.lable.QualityFactory;
|
import com.yeshi.fanli.entity.common.AdminUser;
|
import com.yeshi.fanli.entity.taobao.SearchFilter;
|
import com.yeshi.fanli.entity.taobao.TaoBaoGoodsBrief;
|
import com.yeshi.fanli.entity.taobao.TaoBaoSearchResult;
|
import com.yeshi.fanli.log.LogHelper;
|
import com.yeshi.fanli.service.inter.goods.TaoBaoGoodsBriefService;
|
import com.yeshi.fanli.service.inter.lable.LabelService;
|
import com.yeshi.fanli.service.inter.lable.QualityFactoryService;
|
import com.yeshi.fanli.service.inter.taobao.TaoBaoGoodsUpdateService;
|
import com.yeshi.fanli.tag.PageEntity;
|
import com.yeshi.fanli.util.StringUtil;
|
import com.yeshi.fanli.util.taobao.TaoBaoUtil;
|
import com.yeshi.fanli.util.taobao.TaoKeApiUtil;
|
|
import net.sf.json.JSONObject;
|
|
/**
|
* 精选商品自动入库
|
*
|
* @author yj
|
*
|
*/
|
// @Component
|
public class QualityFactoryJob implements Job {
|
|
// 9.9 19.9 29.9 49.9 筛选
|
public final static String IS_9K9 = "IS_9K9";
|
|
// 限时抢购
|
public final static String FLASH_SALE = "IS_XSQG";
|
|
@Resource
|
private LabelService labelService;
|
@Resource
|
private QualityFactoryService qualityFactoryService;
|
@Resource
|
private TaoBaoGoodsUpdateService taoBaoGoodsUpdateService;
|
@Resource
|
private TaoBaoGoodsBriefService taoBaoGoodsBriefService;
|
|
|
public QualityFactoryJob() {
|
System.out.println("--UpdateQualityFactoryJob 构造函数--");
|
}
|
|
@Override
|
public void execute(JobExecutionContext context) throws JobExecutionException {
|
// 爬取商品信息
|
searchGoods(context);
|
}
|
|
public void searchGoods(JobExecutionContext context) {
|
try {
|
|
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
|
|
BoutiqueAutoRule autoRule = new BoutiqueAutoRule();
|
|
/* 规则id */
|
if (jobDataMap.get("ruleId") != null && !StringUtil.isNullOrEmpty(jobDataMap.get("ruleId").toString())) {
|
Long ruleId = Long.parseLong(jobDataMap.get("ruleId").toString());
|
autoRule.setId(ruleId);
|
}
|
|
/* 筛选条件 */
|
JSONObject jsonData = null;
|
if (jobDataMap.get("searchContent") != null) {
|
String jsonContent = jobDataMap.get("searchContent").toString();
|
jsonData = JSONObject.fromObject(jsonContent);
|
}
|
|
if (jsonData == null) {
|
jsonData = new JSONObject();
|
}
|
|
/* 来源名称 */
|
if (jsonData.get("sourceCalss") != null
|
&& !StringUtil.isNullOrEmpty(jsonData.get("sourceCalss").toString())) {
|
String sourceCalss = jsonData.get("sourceCalss").toString();
|
autoRule.setSourceCalss(sourceCalss);
|
}
|
|
/* 规则名称 */
|
String title = "";
|
if (jsonData.get("title") != null && !StringUtil.isNullOrEmpty(jsonData.get("title").toString())) {
|
title = jsonData.get("title").toString();
|
}
|
autoRule.setTitle(title);
|
|
/* 系统类目id */
|
String systemCid = "";
|
if (jsonData.get("systemCid") != null && !StringUtil.isNullOrEmpty(jsonData.get("systemCid").toString())) {
|
systemCid = jsonData.get("systemCid").toString();
|
}
|
autoRule.setSystemCid(systemCid);
|
|
/* 操作人: 开发账号 */
|
AdminUser admin = new AdminUser(2L);
|
autoRule.setAdminUser(admin);
|
|
/* 标签列表 */
|
List<Label> listLabs = new ArrayList<Label>();
|
|
if (jsonData.get("lableNames") != null
|
&& !StringUtil.isNullOrEmpty(jsonData.get("lableNames").toString())) {
|
|
// 空格隔开
|
String[] arrtitles = jsonData.get("lableNames").toString().split("\\s+");
|
|
// 获取标签属性
|
for (String name : arrtitles) {
|
Label label = labelService.getByTitleCache("labKey", name.trim());
|
if (label == null) {
|
label = insertLabel(name, admin);
|
}
|
listLabs.add(label);
|
}
|
}
|
|
int source = Integer.parseInt(jobDataMap.get("source").toString());
|
|
autoRule.setSource(QualityFactory.SOURCE_TAOBAO);
|
// 1、来源淘宝普通接口
|
if (BoutiqueAutoRule.TB_OPTIONAL == source) {
|
autoRule.setGoodsSource(QualityFactory.SOURCE_TAOBAO);
|
searchTaoBao(jsonData, listLabs, autoRule);
|
}
|
|
// 2、淘宝推荐
|
if (BoutiqueAutoRule.TB_MATERIAL == source) {
|
autoRule.setGoodsSource(QualityFactory.SOURCE_TAOBAO_MATERIAL);
|
searchMaterial(jsonData, listLabs, autoRule);
|
}
|
|
} catch (Exception e) {
|
try {
|
LogHelper.test("--searchGoods--执行异常----");
|
LogHelper.errorDetailInfo(e);
|
} catch (Exception e1) {
|
e1.printStackTrace();
|
}
|
}
|
|
}
|
|
/**
|
* 淘宝api 接口数据爬取
|
*
|
* @param jobDataMap
|
*/
|
private void searchTaoBao(JSONObject jsonData, List<Label> listLabs, BoutiqueAutoRule autoRule) {
|
try {
|
String formatDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
|
|
// 页大小,默认100条
|
int pageSize = 100;
|
|
boolean isCrawl = true;
|
// 权重起始
|
int startWeight = 0;
|
// 权重结束
|
int endWeight = 0;
|
|
// 是否加入限时抢购
|
boolean isFlashSale = false;
|
String title = autoRule.getTitle();
|
if (title.contains(FLASH_SALE)) {
|
isFlashSale = true;
|
}
|
autoRule.setFlashSale(isFlashSale);
|
|
// 最多爬取页码
|
int pageMax = 200;
|
if (jsonData.get("maxPage") != null) {
|
pageMax = Integer.parseInt(jsonData.get("maxPage").toString());
|
}
|
|
/* 参数处理 */
|
SearchFilter filter = getSearchFilter(jsonData);
|
// 展示条目
|
filter.setPageSize(pageSize);
|
|
for (int page = 1; page <= pageMax; page++) {
|
filter.setPage(page);
|
TaoBaoSearchResult result = TaoKeApiUtil.searchWuLiao(filter);
|
|
// 结果为空 结束请求
|
if (result == null) {
|
LogHelper.test(title + "searchWuLiao返回 result为空");
|
break;
|
}
|
|
// 结果数据处理
|
List<TaoBaoGoodsBrief> listGoods = result.getTaoBaoGoodsBriefs();
|
if (listGoods == null || listGoods.size() == 0) {
|
LogHelper.test(title + "searchWuLiao返回ListGoods 结果为空");
|
return;
|
}
|
|
/* 权重范围 */
|
if (page < 3) {
|
startWeight = 4000;
|
endWeight = 6000;
|
} else {
|
startWeight = 10;
|
endWeight = 3000;
|
}
|
|
autoRule.setStartWeight(startWeight);
|
autoRule.setEndWeight(endWeight);
|
|
// 筛选入库
|
screen(listGoods, jsonData, filter, listLabs, autoRule);
|
|
|
|
/* 销售量小值 */
|
int minSales = 0;
|
if (jsonData.get("startSales") != null) {
|
minSales = (int) jsonData.get("startSales");
|
}
|
|
/* 销售量大值 */
|
int maxSales = 0;
|
if (jsonData.get("endSales") != null) {
|
maxSales = (int) jsonData.get("endSales");
|
}
|
|
// 销量控制
|
for (TaoBaoGoodsBrief goodsBrief : listGoods) {
|
|
int biz30day = goodsBrief.getBiz30day();
|
/* 验证销售量 -- 结束爬取数据 */
|
if (maxSales > 0 && minSales > 0 && (biz30day < minSales || biz30day > maxSales)) {
|
isCrawl = false;
|
} else if (maxSales > 0 && biz30day > maxSales) {
|
isCrawl = false;
|
} else if (minSales > 0 && biz30day < minSales) {
|
isCrawl = false;
|
}
|
}
|
|
// 总页数爬取完成
|
PageEntity pageEntity = result.getPageEntity();
|
int totalPage = pageEntity.getTotalPage();
|
LogHelper.test(title + "总页码" + totalPage);
|
|
// 最后一页数据爬取完成
|
if (page == totalPage)
|
isCrawl = false;
|
|
if (!isCrawl) {
|
LogHelper.test("----" + title + "--正常结束-------");
|
break;// 结束爬取数据
|
}
|
}
|
|
// 9k9 限时抢购 不操作删除
|
if (!StringUtil.isNullOrEmpty(title) && (title.contains(IS_9K9) || title.contains(FLASH_SALE))) {
|
return;
|
}
|
|
/* 更新完成后清理之前创建的数据 */
|
if (jsonData.get("systemCid") != null && !StringUtil.isNullOrEmpty(jsonData.get("systemCid").toString())) {
|
Long systemCid = Long.parseLong(jsonData.get("systemCid").toString());
|
qualityFactoryService.deleteNotUpdateGoods(systemCid, formatDate, autoRule.getGoodsSource());
|
}
|
|
} catch (Exception e) {
|
try {
|
LogHelper.errorDetailInfo(e);
|
} catch (Exception e1) {
|
e1.printStackTrace();
|
}
|
}
|
|
}
|
|
/**
|
* 淘宝api 接口数据爬取
|
*
|
* @param jobDataMap
|
*/
|
private void searchMaterial(JSONObject jsonData, List<Label> listLabs, BoutiqueAutoRule autoRule) {
|
|
try {
|
String formatDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
|
|
// 默认20条
|
int pageSize = 20;
|
boolean isCrawl = true;
|
// 权重起始
|
int startWeight = 1000;
|
// 权重结束
|
int endWeight = 3000;
|
autoRule.setStartWeight(startWeight);
|
autoRule.setEndWeight(endWeight);
|
|
// 是否加入限时抢购
|
boolean isFlashSale = false;
|
String title = autoRule.getTitle();
|
if (title.contains(FLASH_SALE)) {
|
isFlashSale = true;
|
}
|
autoRule.setFlashSale(isFlashSale);
|
|
// 最多爬取页码
|
int pageMax = 200;
|
if (jsonData.get("maxPage") != null) {
|
pageMax = Integer.parseInt(jsonData.get("maxPage").toString());
|
}
|
|
/* 参数处理 */
|
SearchFilter filter = getSearchFilter(jsonData);
|
|
for (int page = 1; page <= pageMax; page++) {
|
|
int materialId = 0;
|
String cateIds = filter.getCateIds();
|
if (!StringUtil.isNullOrEmpty(cateIds)) {
|
materialId = Integer.parseInt(cateIds);
|
}
|
|
// 请求官方推荐商品库
|
TaoBaoSearchResult result = TaoKeApiUtil.getMaterialByMaterialId(materialId, page, pageSize);
|
|
// 结果为空 时不再请求
|
if (result == null) {
|
LogHelper.test(title + "searchMaterial返回 result为空");
|
return;
|
}
|
|
// 结果数据处理
|
List<TaoBaoGoodsBrief> listGoods = result.getTaoBaoGoodsBriefs();
|
if (listGoods == null || listGoods.size() == 0) {
|
LogHelper.test(title + "searchMaterial返回ListGoods 结果为空");
|
return;
|
}
|
|
// 筛选入库
|
screen(listGoods, jsonData, filter, listLabs, autoRule);
|
|
|
// 总页数爬取完成
|
PageEntity pageEntity = result.getPageEntity();
|
long count = pageEntity.getTotalCount();
|
int totalPage = (int) (count % pageSize == 0 ? count / pageSize : count / pageSize + 1);
|
|
// 最后一页数据爬取完成
|
if (page == totalPage)
|
isCrawl = false;
|
|
if (!isCrawl) {
|
LogHelper.test("----" + title + "--结束-------");
|
break;// 结束爬取数据
|
}
|
}
|
|
// 9k9 限时抢购 不操作删除
|
if (!StringUtil.isNullOrEmpty(title) && (title.contains(IS_9K9) || title.contains(FLASH_SALE))) {
|
return;
|
}
|
|
/* 更新完成后清理之前创建的数据 */
|
if (jsonData.get("systemCid") != null && !StringUtil.isNullOrEmpty(jsonData.get("systemCid").toString())) {
|
Long systemCid = Long.parseLong(jsonData.get("systemCid").toString());
|
qualityFactoryService.deleteNotUpdateGoods(systemCid, formatDate, autoRule.getGoodsSource());
|
}
|
|
} catch (Exception e) {
|
try {
|
LogHelper.errorDetailInfo(e);
|
} catch (Exception e1) {
|
e1.printStackTrace();
|
}
|
}
|
|
}
|
|
/**
|
* 参数处理加工
|
*
|
* @param jobDataMap
|
* @return
|
*/
|
public SearchFilter getSearchFilter(JSONObject jsonData) {
|
SearchFilter filter = new SearchFilter();
|
|
// 排序字段 销量高到低(默认)
|
filter.setSort(TaoBaoUtil.SORT_SALE_HIGH_TO_LOW);
|
|
if (jsonData.get("key") != null) {
|
String key = jsonData.get("key").toString();
|
if (!StringUtil.isNullOrEmpty(key)) {
|
// 搜索关键词
|
filter.setKey(key);
|
}
|
}
|
|
if (jsonData.get("cateIds") != null) {
|
// 官方推荐商品库投放ID;淘宝类目id集合
|
filter.setCateIds(jsonData.get("cateIds").toString());
|
}
|
|
if (jsonData.get("startZkPrice") != null) {
|
// 在售价范围小值
|
Double startZkPrice = Double.valueOf(jsonData.get("startZkPrice").toString());
|
filter.setStartPrice(new BigDecimal(startZkPrice));
|
}
|
|
if (jsonData.get("endZkPrice") != null) {
|
// 在售价范围大值
|
Double endZxPrice = Double.valueOf(jsonData.get("endZkPrice").toString());
|
filter.setEndPrice(new BigDecimal(endZxPrice));
|
}
|
|
if (jsonData.get("startTkRate") != null) {
|
// 佣金范围小值
|
BigDecimal b = new BigDecimal(jsonData.get("startTkRate").toString());
|
double df = b.setScale(2, BigDecimal.ROUND_FLOOR).doubleValue();
|
int tkRate = (int) (df * 100);
|
filter.setStartTkRate(tkRate);
|
}
|
|
if (jsonData.get("endTkRate") != null) {
|
// 佣金范围大值
|
BigDecimal b = new BigDecimal(jsonData.get("endTkRate").toString());
|
double df = b.setScale(2, BigDecimal.ROUND_FLOOR).doubleValue();
|
int tkRate = (int) (df * 100);
|
filter.setEndTkRate(tkRate);
|
}
|
|
if (jsonData.get("isTmall") != null && jsonData.get("isTmall").toString().equals("1")) {
|
// 是否天猫if ("1".equals(isTmall)) {
|
filter.setTmall(true);
|
}
|
|
if (jsonData.get("hasCoupon") != null && jsonData.get("hasCoupon").toString().equals("1")) {
|
// 是否有券:1 有 0 无
|
filter.setQuan(1);
|
}
|
|
if (jsonData.get("freeShipment") != null && jsonData.get("freeShipment").toString().equals("1")) {
|
// 是否包邮:1 有 0 无
|
filter.setBaoYou(true);
|
// ip地址
|
// filter.setIp("113.251.22.10");// 重庆
|
filter.setIp("218.72.111.105");// 杭州
|
}
|
|
if (jsonData.get("needPrepay") != null && jsonData.get("needPrepay").toString().equals("1")) {
|
// 是否消费保障:1有 0 无
|
filter.setNeedPrepay(true);
|
}
|
|
if (jsonData.get("npxLevel") != null) {
|
// 牛皮癣程度,取值:1:不限,2:无,3:轻微
|
filter.setNpxLevel((int) jsonData.get("npxLevel"));
|
}
|
|
if (jsonData.get("includePayRate30") != null && jsonData.get("includePayRate30").toString().equals("1")) {
|
// 成交转化是否高于行业均值
|
filter.setIncludePayRate30(true);
|
}
|
|
if (jsonData.get("includeGoodRate") != null && jsonData.get("includeGoodRate").toString().equals("1")) {
|
// 好评率是否高于行业均值 1 有 0 无
|
filter.setIncludeGoodRate(true);
|
}
|
|
if (jsonData.get("includeRfdRate") != null && jsonData.get("includeRfdRate").toString().equals("1")) {
|
// 退款率是否低于行业均值 1 有 0 无
|
filter.setIncludeRfdRate(true);
|
}
|
return filter;
|
}
|
|
|
|
/**
|
* 筛选符合条件的商品
|
*
|
* @param taoBaoGoodsBriefs
|
* @param jsonData
|
* @param filter
|
* @param listLabs
|
* @param autoRule
|
* @throws Exception
|
*/
|
public void screen(List<TaoBaoGoodsBrief> taoBaoGoodsBriefs, JSONObject jsonData, SearchFilter filter,
|
List<Label> listLabs, BoutiqueAutoRule autoRule) {
|
try {
|
List<TaoBaoGoodsBrief> listGoods = new ArrayList<TaoBaoGoodsBrief>();
|
for (TaoBaoGoodsBrief goodsBrief : taoBaoGoodsBriefs) {
|
// 验证是否符合要求
|
if (validate(filter, jsonData, goodsBrief, 1)) {
|
listGoods.add(goodsBrief);
|
}
|
}
|
qualityFactoryService.autoInsertOrUpadateStorage(autoRule, listGoods, listLabs);
|
} catch (Exception e) {
|
LogHelper.errorDetailInfo(e);
|
}
|
|
}
|
|
/**
|
* 验证是否满足条件
|
*
|
* @return
|
*/
|
public boolean validate(SearchFilter filter, JSONObject jsonData, TaoBaoGoodsBrief goodsBrief, int source) {
|
/* 销售量小值 */
|
int minSales = 0;
|
if (jsonData.get("startSales") != null) {
|
minSales = (int) jsonData.get("startSales");
|
}
|
|
/* 销售量大值 */
|
int maxSales = 0;
|
if (jsonData.get("endSales") != null) {
|
maxSales = (int) jsonData.get("endSales");
|
}
|
|
int biz30day = goodsBrief.getBiz30day();
|
|
/* 验证销售量 */
|
if (maxSales > 0 && minSales > 0 && (biz30day < minSales || biz30day > maxSales)) {
|
return false;
|
} else if (maxSales > 0 && biz30day > maxSales) {
|
return false;
|
} else if (minSales > 0 && biz30day < minSales) {
|
return false;
|
}
|
|
/* 验证比例 */
|
if (BoutiqueAutoRule.TB_MATERIAL == source) {
|
|
int startTkRate = filter.getStartTkRate();
|
int endTkRate = filter.getEndTkRate();
|
|
BigDecimal tkRate = goodsBrief.getTkRate();
|
|
if (startTkRate > 0 && endTkRate > 0 && (tkRate.compareTo(new BigDecimal(startTkRate / 100)) < 0
|
|| tkRate.compareTo(new BigDecimal(endTkRate / 100)) > 0)) {
|
return false;
|
} else if (endTkRate > 0 && tkRate.compareTo(new BigDecimal(endTkRate / 100)) > 0) {
|
return false;
|
} else if (startTkRate > 0 && tkRate.compareTo(new BigDecimal(startTkRate / 100)) < 0) {
|
return false;
|
}
|
}
|
|
/* 券后价范围下限 */
|
BigDecimal startPrice = null;
|
if (jsonData.get("startPrice") != null) {
|
startPrice = new BigDecimal(jsonData.get("startPrice").toString());
|
}
|
|
/* 券后价范围上限 */
|
BigDecimal endPrice = null;
|
if (jsonData.get("endPrice") != null) {
|
endPrice = new BigDecimal(jsonData.get("endPrice").toString());
|
}
|
|
/* 券后价--计算 */
|
BigDecimal couponPrice = TaoBaoUtil.getAfterUseCouplePrice(goodsBrief);
|
|
/* 验证在券后价 */
|
if (startPrice != null && endPrice != null
|
&& (couponPrice.compareTo(startPrice) < 0 || couponPrice.compareTo(endPrice) > 0)) {
|
return false;
|
} else if (endPrice != null && couponPrice.compareTo(endPrice) > 0) {
|
return false;
|
} else if (startPrice != null && couponPrice.compareTo(startPrice) < 0) {
|
return false;
|
}
|
|
/* 验证在是否有券 */
|
if (filter.getQuan() > 0) {
|
String couponInfo = goodsBrief.getCouponInfo();
|
if (StringUtil.isNullOrEmpty(couponInfo)) {
|
return false;
|
}
|
}
|
|
return true;
|
}
|
|
/**
|
* 插入新的标签
|
*
|
* @param title
|
* @param admin
|
* @return
|
* @throws Exception
|
*/
|
public Label insertLabel(String title, AdminUser admin) throws Exception {
|
// 新增
|
Label label = new Label();
|
label.setTitle(title);// 名称
|
label.setEntrymode(Label.MODE_SYSTEM);
|
label.setCreatetime(new Date());
|
label.setUpdatetime(new Date());
|
label.setCreateUser(admin);
|
label.setIosClick(0l);
|
label.setAndroidClick(0l);
|
labelService.insertSelective(label);
|
return label;
|
}
|
|
}
|