| | |
| | | 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;
|
| | |
|
| | | /**
|
| | | * 精选商品自动入库
|
| | | * |
| | | * @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();
|
| | | Object object = jobDataMap.get("key");
|
| | | if (object == null) {
|
| | | return;
|
| | | }
|
| | | |
| | | BoutiqueAutoRule autoRule = (BoutiqueAutoRule) object;
|
| | | /* 操作人: 开发账号 */
|
| | | AdminUser admin = new AdminUser(2L);
|
| | | autoRule.setAdminUser(admin);
|
| | | |
| | | /* 标签列表 */
|
| | | List<Label> listLabs = new ArrayList<Label>();
|
| | | String lableNames = autoRule.getLableNames();
|
| | | if (!StringUtil.isNullOrEmpty(lableNames)) {
|
| | | String[] arrtitles = lableNames.split("\\s+"); // 空格隔开
|
| | | for (String name : arrtitles) {
|
| | | Label label = labelService.getByTitleCache("labKey", name.trim());
|
| | | if (label == null) {
|
| | | label = insertLabel(name, admin);
|
| | | }
|
| | | listLabs.add(label);
|
| | | }
|
| | | }
|
| | | |
| | | if (BoutiqueAutoRule.TB_OPTIONAL == autoRule.getSource()) { // 1、来源淘宝普通接口
|
| | | autoRule.setGoodsSource(QualityFactory.SOURCE_TAOBAO);
|
| | | searchTaoBao(listLabs, autoRule);
|
| | | } else if (BoutiqueAutoRule.TB_MATERIAL == autoRule.getSource()) { // 2、淘宝推荐
|
| | | autoRule.setGoodsSource(QualityFactory.SOURCE_TAOBAO_MATERIAL);
|
| | | searchMaterial(listLabs, autoRule);
|
| | | }
|
| | |
|
| | | } catch (Exception e) {
|
| | | try {
|
| | | LogHelper.test("--searchGoods--执行异常----");
|
| | | LogHelper.errorDetailInfo(e);
|
| | | } catch (Exception e1) {
|
| | | e1.printStackTrace();
|
| | | }
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | | * 淘宝api 接口数据爬取
|
| | | * |
| | | * @param jobDataMap
|
| | | */
|
| | | private void searchTaoBao(List<Label> listLabs, BoutiqueAutoRule autoRule) {
|
| | | try {
|
| | | String formatDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
|
| | | 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 (autoRule.getMaxPage() != null) {
|
| | | pageMax = autoRule.getMaxPage();
|
| | | }
|
| | |
|
| | | /* 参数处理 */
|
| | | SearchFilter filter = getSearchFilter(autoRule);
|
| | | filter.setPageSize(100);
|
| | |
|
| | | 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, filter, listLabs, autoRule);
|
| | | |
| | | /* 销售量小值 */
|
| | | int minSales = 0;
|
| | | if (autoRule.getStartSales() != null) {
|
| | | minSales = autoRule.getStartSales();
|
| | | }
|
| | |
|
| | | /* 销售量大值 */
|
| | | int maxSales = 0;
|
| | | if (autoRule.getEndSales() != null) {
|
| | | maxSales = autoRule.getEndSales();
|
| | | }
|
| | |
|
| | | // 销量控制
|
| | | 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 (!StringUtil.isNullOrEmpty(autoRule.getSystemCid())) {
|
| | | Long systemCid = Long.parseLong(autoRule.getSystemCid());
|
| | | qualityFactoryService.deleteNotUpdateGoods(systemCid, formatDate, autoRule.getGoodsSource());
|
| | | }
|
| | |
|
| | | } catch (Exception e) {
|
| | | try {
|
| | | LogHelper.errorDetailInfo(e);
|
| | | } catch (Exception e1) {
|
| | | e1.printStackTrace();
|
| | | }
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | | * 淘宝api 接口数据爬取
|
| | | * |
| | | * @param jobDataMap
|
| | | */
|
| | | private void searchMaterial(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 (autoRule.getMaxPage() != null)
|
| | | pageMax = autoRule.getMaxPage();
|
| | |
|
| | | /* 参数处理 */
|
| | | SearchFilter filter = getSearchFilter(autoRule);
|
| | |
|
| | | 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, 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 (!StringUtil.isNullOrEmpty(autoRule.getSystemCid())) {
|
| | | Long systemCid = Long.parseLong(autoRule.getSystemCid());
|
| | | qualityFactoryService.deleteNotUpdateGoods(systemCid, formatDate, autoRule.getGoodsSource());
|
| | | }
|
| | |
|
| | | } catch (Exception e) {
|
| | | try {
|
| | | LogHelper.errorDetailInfo(e);
|
| | | } catch (Exception e1) {
|
| | | e1.printStackTrace();
|
| | | }
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | | * 参数处理加工
|
| | | * |
| | | * @param jobDataMap
|
| | | * @return
|
| | | */
|
| | | public SearchFilter getSearchFilter(BoutiqueAutoRule autoRule) {
|
| | | SearchFilter filter = new SearchFilter();
|
| | | // 排序字段 销量高到低(默认)
|
| | | filter.setSort(TaoBaoUtil.SORT_SALE_HIGH_TO_LOW);
|
| | | // 搜索关键词
|
| | | filter.setKey(autoRule.getKey());
|
| | | // 官方推荐商品库投放ID;淘宝类目id集合
|
| | | filter.setCateIds(autoRule.getCateIds());
|
| | |
|
| | | // 在售价范围小值
|
| | | if (autoRule.getStartZkPrice() != null) {
|
| | | filter.setStartPrice(new BigDecimal(autoRule.getStartPrice()));
|
| | | }
|
| | |
|
| | | // 在售价范围大值
|
| | | if (autoRule.getEndZkPrice() != null) {
|
| | | filter.setEndPrice(new BigDecimal(autoRule.getEndZkPrice()));
|
| | | }
|
| | |
|
| | | // 佣金范围小值
|
| | | if (autoRule.getStartTkRate() != null) {
|
| | | BigDecimal b = new BigDecimal(autoRule.getStartTkRate());
|
| | | double df = b.setScale(2, BigDecimal.ROUND_FLOOR).doubleValue();
|
| | | int tkRate = (int) (df * 100);
|
| | | filter.setStartTkRate(tkRate);
|
| | | }
|
| | |
|
| | | // 佣金范围大值
|
| | | if (autoRule.getEndTkRate() != null) {
|
| | | BigDecimal b = new BigDecimal(autoRule.getEndTkRate());
|
| | | double df = b.setScale(2, BigDecimal.ROUND_FLOOR).doubleValue();
|
| | | int tkRate = (int) (df * 100);
|
| | | filter.setEndTkRate(tkRate);
|
| | | }
|
| | |
|
| | | // 是否天猫
|
| | | if (autoRule.getIsTmall() != null && autoRule.getIsTmall() == 1) {
|
| | | filter.setTmall(true);
|
| | | }
|
| | | |
| | | // 是否有券:1 有 0 无
|
| | | if (autoRule.getHasCoupon() != null && autoRule.getHasCoupon() == 1) {
|
| | | filter.setQuan(1);
|
| | | }
|
| | | |
| | | // 是否包邮:1 有 0 无
|
| | | if (autoRule.getFreeShipment() != null && autoRule.getFreeShipment() == 1) {
|
| | | filter.setBaoYou(true);
|
| | | filter.setIp("218.72.111.105");// 杭州
|
| | | }
|
| | | |
| | | // 是否消费保障:1有 0 无
|
| | | if (autoRule.getNeedPrepay() != null && autoRule.getNeedPrepay() == 1) {
|
| | | filter.setNeedPrepay(true);
|
| | | }
|
| | |
|
| | | // 牛皮癣程度,取值:1:不限,2:无,3:轻微
|
| | | if (autoRule.getNpxLevel() != null && autoRule.getNpxLevel() == 1) {
|
| | | filter.setNpxLevel(autoRule.getNpxLevel());
|
| | | }
|
| | | |
| | | // 成交转化是否高于行业均值
|
| | | if (autoRule.getIncludePayRate30() != null && autoRule.getIncludePayRate30() == 1) {
|
| | | filter.setIncludePayRate30(true);
|
| | | }
|
| | |
|
| | | // 好评率是否高于行业均值 1 有 0 无
|
| | | if (autoRule.getIncludeGoodRate() != null && autoRule.getIncludeGoodRate() == 1) {
|
| | | filter.setIncludeGoodRate(true);
|
| | | }
|
| | |
|
| | | // 退款率是否低于行业均值 1 有 0 无
|
| | | if (autoRule.getIncludeRfdRate() != null && autoRule.getIncludeRfdRate() == 1) {
|
| | | filter.setIncludeRfdRate(true);
|
| | | }
|
| | | return filter;
|
| | | }
|
| | |
|
| | | |
| | |
|
| | | /**
|
| | | * 筛选符合条件的商品
|
| | | * |
| | | * @param taoBaoGoodsBriefs
|
| | | * @param jsonData
|
| | | * @param filter
|
| | | * @param listLabs
|
| | | * @param autoRule
|
| | | * @throws Exception
|
| | | */
|
| | | public void screen(List<TaoBaoGoodsBrief> taoBaoGoodsBriefs, SearchFilter filter,
|
| | | List<Label> listLabs, BoutiqueAutoRule autoRule) {
|
| | | try {
|
| | | List<TaoBaoGoodsBrief> listGoods = new ArrayList<TaoBaoGoodsBrief>();
|
| | | for (TaoBaoGoodsBrief goodsBrief : taoBaoGoodsBriefs) {
|
| | | // 验证是否符合要求
|
| | | if (validate(filter, autoRule, goodsBrief, 1)) {
|
| | | listGoods.add(goodsBrief);
|
| | | }
|
| | | }
|
| | | qualityFactoryService.autoInsertOrUpadateStorage(autoRule, listGoods, listLabs);
|
| | | } catch (Exception e) {
|
| | | LogHelper.errorDetailInfo(e);
|
| | | }
|
| | | |
| | | }
|
| | |
|
| | | /**
|
| | | * 验证是否满足条件
|
| | | * |
| | | * @return
|
| | | */
|
| | | public boolean validate(SearchFilter filter, BoutiqueAutoRule autoRule, TaoBaoGoodsBrief goodsBrief, int source) {
|
| | | int minSales = 0;
|
| | | if (autoRule.getStartSales() != null)
|
| | | minSales = autoRule.getStartSales();
|
| | |
|
| | | int maxSales = 0;
|
| | | if (autoRule.getEndSales() != null)
|
| | | maxSales = autoRule.getEndSales();
|
| | |
|
| | | /* 验证销售量 */
|
| | | if (maxSales == 0 && minSales ==0) {
|
| | | |
| | | } else {
|
| | | 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 (autoRule.getStartPrice() != null)
|
| | | startPrice = new BigDecimal(autoRule.getStartPrice().toString());
|
| | | /* 券后价范围上限 */
|
| | | BigDecimal endPrice = null;
|
| | | if (autoRule.getEndPrice() != null)
|
| | | endPrice = new BigDecimal(autoRule.getEndPrice().toString());
|
| | |
|
| | | if (startPrice == null && endPrice == null) {
|
| | | |
| | | } else {
|
| | | 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;
|
| | | }
|
| | |
|
| | | }
|
| | | 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.goods.facade.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.common.entity.PageEntity; |
| | | import com.yeshi.fanli.util.StringUtil; |
| | | import com.yeshi.fanli.util.taobao.TaoBaoUtil; |
| | | import com.yeshi.fanli.util.taobao.TaoKeApiUtil; |
| | | |
| | | /** |
| | | * 精选商品自动入库 |
| | | * |
| | | * @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(); |
| | | Object object = jobDataMap.get("key"); |
| | | if (object == null) { |
| | | return; |
| | | } |
| | | |
| | | BoutiqueAutoRule autoRule = (BoutiqueAutoRule) object; |
| | | /* 操作人: 开发账号 */ |
| | | AdminUser admin = new AdminUser(2L); |
| | | autoRule.setAdminUser(admin); |
| | | |
| | | /* 标签列表 */ |
| | | List<Label> listLabs = new ArrayList<Label>(); |
| | | String lableNames = autoRule.getLableNames(); |
| | | if (!StringUtil.isNullOrEmpty(lableNames)) { |
| | | String[] arrtitles = lableNames.split("\\s+"); // 空格隔开 |
| | | for (String name : arrtitles) { |
| | | Label label = labelService.getByTitleCache("labKey", name.trim()); |
| | | if (label == null) { |
| | | label = insertLabel(name, admin); |
| | | } |
| | | listLabs.add(label); |
| | | } |
| | | } |
| | | |
| | | if (BoutiqueAutoRule.TB_OPTIONAL == autoRule.getSource()) { // 1、来源淘宝普通接口 |
| | | autoRule.setGoodsSource(QualityFactory.SOURCE_TAOBAO); |
| | | searchTaoBao(listLabs, autoRule); |
| | | } else if (BoutiqueAutoRule.TB_MATERIAL == autoRule.getSource()) { // 2、淘宝推荐 |
| | | autoRule.setGoodsSource(QualityFactory.SOURCE_TAOBAO_MATERIAL); |
| | | searchMaterial(listLabs, autoRule); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | try { |
| | | LogHelper.test("--searchGoods--执行异常----"); |
| | | LogHelper.errorDetailInfo(e); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 淘宝api 接口数据爬取 |
| | | * |
| | | * @param jobDataMap |
| | | */ |
| | | private void searchTaoBao(List<Label> listLabs, BoutiqueAutoRule autoRule) { |
| | | try { |
| | | String formatDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()); |
| | | 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 (autoRule.getMaxPage() != null) { |
| | | pageMax = autoRule.getMaxPage(); |
| | | } |
| | | |
| | | /* 参数处理 */ |
| | | SearchFilter filter = getSearchFilter(autoRule); |
| | | filter.setPageSize(100); |
| | | |
| | | for (int page = 1; page <= pageMax; page++) { |
| | | filter.setPage(page); |
| | | TaoBaoSearchResult result = TaoKeApiUtil.searchWuLiaoNew(filter,null,null); |
| | | |
| | | // 结果为空 结束请求 |
| | | 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, filter, listLabs, autoRule); |
| | | |
| | | /* 销售量小值 */ |
| | | int minSales = 0; |
| | | if (autoRule.getStartSales() != null) { |
| | | minSales = autoRule.getStartSales(); |
| | | } |
| | | |
| | | /* 销售量大值 */ |
| | | int maxSales = 0; |
| | | if (autoRule.getEndSales() != null) { |
| | | maxSales = autoRule.getEndSales(); |
| | | } |
| | | |
| | | // 销量控制 |
| | | 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 (!StringUtil.isNullOrEmpty(autoRule.getSystemCid())) { |
| | | Long systemCid = Long.parseLong(autoRule.getSystemCid()); |
| | | qualityFactoryService.deleteNotUpdateGoods(systemCid, formatDate, autoRule.getGoodsSource()); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | try { |
| | | LogHelper.errorDetailInfo(e); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 淘宝api 接口数据爬取 |
| | | * |
| | | * @param jobDataMap |
| | | */ |
| | | private void searchMaterial(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 (autoRule.getMaxPage() != null) |
| | | pageMax = autoRule.getMaxPage(); |
| | | |
| | | /* 参数处理 */ |
| | | SearchFilter filter = getSearchFilter(autoRule); |
| | | |
| | | 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, 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 (!StringUtil.isNullOrEmpty(autoRule.getSystemCid())) { |
| | | Long systemCid = Long.parseLong(autoRule.getSystemCid()); |
| | | qualityFactoryService.deleteNotUpdateGoods(systemCid, formatDate, autoRule.getGoodsSource()); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | try { |
| | | LogHelper.errorDetailInfo(e); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 参数处理加工 |
| | | * |
| | | * @param jobDataMap |
| | | * @return |
| | | */ |
| | | public SearchFilter getSearchFilter(BoutiqueAutoRule autoRule) { |
| | | SearchFilter filter = new SearchFilter(); |
| | | // 排序字段 销量高到低(默认) |
| | | filter.setSort(TaoBaoUtil.SORT_SALE_HIGH_TO_LOW); |
| | | // 搜索关键词 |
| | | filter.setKey(autoRule.getKey()); |
| | | // 官方推荐商品库投放ID;淘宝类目id集合 |
| | | filter.setCateIds(autoRule.getCateIds()); |
| | | |
| | | // 在售价范围小值 |
| | | if (autoRule.getStartZkPrice() != null) { |
| | | filter.setStartPrice(new BigDecimal(autoRule.getStartPrice())); |
| | | } |
| | | |
| | | // 在售价范围大值 |
| | | if (autoRule.getEndZkPrice() != null) { |
| | | filter.setEndPrice(new BigDecimal(autoRule.getEndZkPrice())); |
| | | } |
| | | |
| | | // 佣金范围小值 |
| | | if (autoRule.getStartTkRate() != null) { |
| | | BigDecimal b = new BigDecimal(autoRule.getStartTkRate()); |
| | | double df = b.setScale(2, BigDecimal.ROUND_FLOOR).doubleValue(); |
| | | int tkRate = (int) (df * 100); |
| | | filter.setStartTkRate(tkRate); |
| | | } |
| | | |
| | | // 佣金范围大值 |
| | | if (autoRule.getEndTkRate() != null) { |
| | | BigDecimal b = new BigDecimal(autoRule.getEndTkRate()); |
| | | double df = b.setScale(2, BigDecimal.ROUND_FLOOR).doubleValue(); |
| | | int tkRate = (int) (df * 100); |
| | | filter.setEndTkRate(tkRate); |
| | | } |
| | | |
| | | // 是否天猫 |
| | | if (autoRule.getIsTmall() != null && autoRule.getIsTmall() == 1) { |
| | | filter.setTmall(true); |
| | | } |
| | | |
| | | // 是否有券:1 有 0 无 |
| | | if (autoRule.getHasCoupon() != null && autoRule.getHasCoupon() == 1) { |
| | | filter.setQuan(1); |
| | | } |
| | | |
| | | // 是否包邮:1 有 0 无 |
| | | if (autoRule.getFreeShipment() != null && autoRule.getFreeShipment() == 1) { |
| | | filter.setBaoYou(true); |
| | | filter.setIp("218.72.111.105");// 杭州 |
| | | } |
| | | |
| | | // 是否消费保障:1有 0 无 |
| | | if (autoRule.getNeedPrepay() != null && autoRule.getNeedPrepay() == 1) { |
| | | filter.setNeedPrepay(true); |
| | | } |
| | | |
| | | // 牛皮癣程度,取值:1:不限,2:无,3:轻微 |
| | | if (autoRule.getNpxLevel() != null && autoRule.getNpxLevel() == 1) { |
| | | filter.setNpxLevel(autoRule.getNpxLevel()); |
| | | } |
| | | |
| | | // 成交转化是否高于行业均值 |
| | | if (autoRule.getIncludePayRate30() != null && autoRule.getIncludePayRate30() == 1) { |
| | | filter.setIncludePayRate30(true); |
| | | } |
| | | |
| | | // 好评率是否高于行业均值 1 有 0 无 |
| | | if (autoRule.getIncludeGoodRate() != null && autoRule.getIncludeGoodRate() == 1) { |
| | | filter.setIncludeGoodRate(true); |
| | | } |
| | | |
| | | // 退款率是否低于行业均值 1 有 0 无 |
| | | if (autoRule.getIncludeRfdRate() != null && autoRule.getIncludeRfdRate() == 1) { |
| | | filter.setIncludeRfdRate(true); |
| | | } |
| | | return filter; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 筛选符合条件的商品 |
| | | * |
| | | * @param taoBaoGoodsBriefs |
| | | * @param jsonData |
| | | * @param filter |
| | | * @param listLabs |
| | | * @param autoRule |
| | | * @throws Exception |
| | | */ |
| | | public void screen(List<TaoBaoGoodsBrief> taoBaoGoodsBriefs, SearchFilter filter, |
| | | List<Label> listLabs, BoutiqueAutoRule autoRule) { |
| | | try { |
| | | List<TaoBaoGoodsBrief> listGoods = new ArrayList<TaoBaoGoodsBrief>(); |
| | | for (TaoBaoGoodsBrief goodsBrief : taoBaoGoodsBriefs) { |
| | | // 验证是否符合要求 |
| | | if (validate(filter, autoRule, goodsBrief, 1)) { |
| | | listGoods.add(goodsBrief); |
| | | } |
| | | } |
| | | qualityFactoryService.autoInsertOrUpadateStorage(autoRule, listGoods, listLabs); |
| | | } catch (Exception e) { |
| | | LogHelper.errorDetailInfo(e); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 验证是否满足条件 |
| | | * |
| | | * @return |
| | | */ |
| | | public boolean validate(SearchFilter filter, BoutiqueAutoRule autoRule, TaoBaoGoodsBrief goodsBrief, int source) { |
| | | int minSales = 0; |
| | | if (autoRule.getStartSales() != null) |
| | | minSales = autoRule.getStartSales(); |
| | | |
| | | int maxSales = 0; |
| | | if (autoRule.getEndSales() != null) |
| | | maxSales = autoRule.getEndSales(); |
| | | |
| | | /* 验证销售量 */ |
| | | if (maxSales == 0 && minSales ==0) { |
| | | |
| | | } else { |
| | | 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 (autoRule.getStartPrice() != null) |
| | | startPrice = new BigDecimal(autoRule.getStartPrice().toString()); |
| | | /* 券后价范围上限 */ |
| | | BigDecimal endPrice = null; |
| | | if (autoRule.getEndPrice() != null) |
| | | endPrice = new BigDecimal(autoRule.getEndPrice().toString()); |
| | | |
| | | if (startPrice == null && endPrice == null) { |
| | | |
| | | } else { |
| | | BigDecimal couponPrice = TaoBaoUtil.getCouponPrice(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; |
| | | } |
| | | |
| | | } |