admin
2021-03-26 351b317c56487676b4f5a60b5bc3710a383d7a7b
全网搜腾讯完善
27个文件已修改
8个文件已添加
1346 ■■■■ 已修改文件
src/main/java/com/yeshi/buwan/controller/parser/HomeParser.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/controller/parser/UserParser.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/dao/juhe/tencent/TencentCoverVideoDao.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/dao/juhe/tencent/TencentSearchVideoMapDao.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/domain/video/InternetSearchVideo.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/job/video/MogoTVVideoUpdate.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/job/video/TencentVideoUpdate.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/mogotv/MogoTVApiUtil.java 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/mogotv/MogoTVUtil.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/imp/SearchService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/imp/juhe/InternetSearchVideoServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/imp/juhe/MogoTVServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/imp/juhe/TencentVideoServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/imp/juhe/YouKuServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/inter/juhe/InternetSearchVideoService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/inter/juhe/MogoTVService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/inter/juhe/TencentVideoService.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/inter/juhe/YouKuService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/manager/SolrAlbumVideoDataManager.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/service/manager/SolrInternetSearchVideoDataManager.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/tencent/TencentVideoApiUtil.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/tencent/TencentVideoUtil.java 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/tencent/entity/TencentCoverInfo.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/tencent/entity/TencentCoverVideo.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/util/CompareStrSimUtil.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/util/SpringContext.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/util/factory/InternetSearchVideoFactory.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/util/mq/CMQManager.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/util/video/VideoDetailUtil.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/hxh/spring/test/DES.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/hxh/spring/test/GeneralTest.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/hxh/spring/test/SolrTest.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/hxh/spring/test/video/MogoTest.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/hxh/spring/test/video/TencentTest.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/hxh/spring/test/video/YouKuTest.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/yeshi/buwan/controller/parser/HomeParser.java
@@ -18,6 +18,7 @@
import com.yeshi.buwan.domain.video.InternetSearchVideo;
import com.yeshi.buwan.domain.video.VideoWatchHistory;
import com.yeshi.buwan.dto.log.BaseLog;
import com.yeshi.buwan.mogotv.MogoTVUtil;
import com.yeshi.buwan.pptv.PPTVUtil;
import com.yeshi.buwan.pptv.entity.PPTVSeries;
import com.yeshi.buwan.service.imp.*;
@@ -26,6 +27,7 @@
import com.yeshi.buwan.service.inter.juhe.YouKuService;
import com.yeshi.buwan.service.inter.recommend.HomeRecommendSpecialService;
import com.yeshi.buwan.service.inter.video.VideoWatchHistoryService;
import com.yeshi.buwan.tencent.TencentVideoUtil;
import com.yeshi.buwan.util.*;
import com.yeshi.buwan.util.annotation.RequireUid;
import com.yeshi.buwan.util.factory.VideoInfoFactory;
@@ -360,6 +362,12 @@
    @Resource
    private YouKuUtil youKuUtil;
    @Resource
    private MogoTVUtil mogoTVUtil;
    @Resource
    private TencentVideoUtil tencentVideoUtil;
    public void getVideoDetailForInternetSearch(AcceptData acceptData, String videoId, HttpServletRequest request, PrintWriter out) {
        InternetSearchVideo internetSearchVideo = internetSearchVideoService.selectByPrimaryKey(videoId);
@@ -367,9 +375,8 @@
        if (StringUtil.isNullOrEmpty(resourceId)) {
            resourceId = internetSearchVideo.getResourceIds().split(",")[0];
        }
        if (Integer.parseInt(resourceId) == YouKuUtil.RESOURCE_ID) {
            VideoInfo info = null;
        if (Integer.parseInt(resourceId) == YouKuUtil.RESOURCE_ID) {
            try {
                info = youKuUtil.getVideoInfo(internetSearchVideo);
            } catch (Exception e) {
@@ -377,11 +384,28 @@
                return;
            }
        } else if (Integer.parseInt(resourceId) == MogoTVUtil.RESOURCE_ID) {
            try {
                info = mogoTVUtil.getVideoInfo(internetSearchVideo);
            } catch (Exception e) {
                out.print(JsonUtil.loadFalseAdmin(e.getMessage()));
                return;
            }
        } else if (Integer.parseInt(resourceId) == TencentVideoUtil.RESOURCE_ID) {
            try {
                info = tencentVideoUtil.getVideoInfo(internetSearchVideo);
            } catch (Exception e) {
                out.print(JsonUtil.loadFalseAdmin(e.getMessage()));
                return;
            }
        }
        info.setWatchCount("" + (int) (Math.random() * 1000));
            JSONArray array = new JSONArray();
            JSONObject obj = new JSONObject();
            out.print(JsonUtil.loadTrueJson(StringUtil.outPutResultJson(Utils.convertVideo(info)), array.toString(),
                    obj.toString()));
        }
    }
    @RequireUid
src/main/java/com/yeshi/buwan/controller/parser/UserParser.java
@@ -16,6 +16,7 @@
import com.yeshi.buwan.service.imp.*;
import com.yeshi.buwan.service.inter.juhe.InternetSearchVideoService;
import com.yeshi.buwan.service.manager.SolrAlbumVideoDataManager;
import com.yeshi.buwan.service.manager.SolrInternetSearchVideoDataManager;
import com.yeshi.buwan.util.*;
import com.yeshi.buwan.util.JuHe.VideoResourceUtil;
import com.yeshi.buwan.util.annotation.RequireUid;
@@ -67,6 +68,8 @@
    private VideoInfoService videoInfoService;
    @Resource
    private SolrAlbumVideoDataManager solrDataManager;
    @Resource
    private SolrInternetSearchVideoDataManager solrInternetSearchVideoDataManager;
    @Resource
    private ConfigParser configParser;
@@ -197,6 +200,13 @@
                }
            }
        }
        if (list == null || list.size() < 3) {
            List<String> list1 = solrInternetSearchVideoDataManager.getSuggestKeyList(key);
            if (list1 != null) {
                list.addAll(list1);
            }
        }
        JSONObject object = new JSONObject();
        object.put("count", list.size() + "");
        JSONArray array = new JSONArray();
src/main/java/com/yeshi/buwan/dao/juhe/tencent/TencentCoverVideoDao.java
New file
@@ -0,0 +1,35 @@
package com.yeshi.buwan.dao.juhe.tencent;
import com.yeshi.buwan.dao.base.MongodbBaseDao;
import com.yeshi.buwan.tencent.entity.TencentCoverVideo;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import java.util.Date;
@Repository
public class TencentCoverVideoDao extends MongodbBaseDao<TencentCoverVideo> {
    public void updateSelective(TencentCoverVideo bean) {
        Query query = new Query();
        Update update = new Update();
        query.addCriteria(Criteria.where("videoId").is(bean.getVideoId()));
        if (bean.getCoverId() != null) {
            update.set("coverId", bean.getCoverId());
        }
        if (bean.getStage() != null) {
            update.set("stage", bean.getStage());
        }
        if (bean.getPosition() != null) {
            update.set("position", bean.getPosition());
        }
        if (bean.getDate() != null) {
            update.set("date", bean.getDate());
        }
        update.set("updateTime", new Date());
        update(query, update);
    }
}
src/main/java/com/yeshi/buwan/dao/juhe/tencent/TencentSearchVideoMapDao.java
New file
@@ -0,0 +1,32 @@
package com.yeshi.buwan.dao.juhe.tencent;
import com.yeshi.buwan.tencent.entity.TencentSearchVideoMap;
import com.yeshi.buwan.dao.base.MongodbBaseDao;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;
import java.util.Date;
@Repository
public class TencentSearchVideoMapDao extends MongodbBaseDao<TencentSearchVideoMap> {
    public void updateSelective(TencentSearchVideoMap bean) {
        Query query = new Query();
        Update update = new Update();
        query.addCriteria(Criteria.where("videoId").is(bean.getVideoId()));
        if (bean.getCoverId() != null) {
            update.set("coverId", bean.getCoverId());
        }
        if (bean.getCreateTime() != null) {
            update.set("createTime", bean.getCreateTime());
        }
        update.set("updateTime", new Date());
        update(query, update);
    }
    public TencentSearchVideoMap selectByVideoId(String videoId) {
        return get(videoId);
    }
}
src/main/java/com/yeshi/buwan/domain/video/InternetSearchVideo.java
@@ -2,9 +2,8 @@
import com.yeshi.buwan.util.StringUtil;
import org.apache.solr.client.solrj.beans.Field;
import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.solr.core.mapping.Indexed;
@@ -16,19 +15,19 @@
@Document(collection = "internetSearchVideo")
public class InternetSearchVideo {
    @NotEmpty(message = "id不能为空")
    @NotBlank(message = "id不能为空")
    @Id
    @Field
    private String id;
    @NotEmpty(message = "名称不能为空")
    @NotBlank(message = "名称不能为空")
    @Field
    private String name;
    @Field
    private String nameStr;
    @NotEmpty(message = "竖图不能为空")
    @NotBlank(message = "竖图不能为空")
    @Field
    private String vpicture;
    @NotEmpty(message = "横图不能为空")
//    @NotBlank(message = "横图不能为空")
    @Field
    private String hpicture;
    @Field
src/main/java/com/yeshi/buwan/job/video/MogoTVVideoUpdate.java
New file
@@ -0,0 +1,113 @@
package com.yeshi.buwan.job.video;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yeshi.buwan.mogotv.MogoTVApiUtil;
import com.yeshi.buwan.mogotv.entity.MogoTVClipInfo;
import com.yeshi.buwan.mogotv.entity.MogoTVVideo;
import com.yeshi.buwan.service.inter.juhe.MogoTVService;
import com.yeshi.buwan.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Component
public class MogoTVVideoUpdate {
    private final static Logger logger = LoggerFactory.getLogger(MogoTVVideoUpdate.class);
    @Resource
    private MogoTVService mogoTVService;
    private MogoTVClipInfo getClipDetail(MogoTVClipInfo clipInfo) {
        MogoTVClipInfo detail = MogoTVApiUtil.getClipDetail(clipInfo);
        List<MogoTVVideo> videoList = MogoTVApiUtil.getVideoList(clipInfo.getPlayPartId());
        detail.setVideoList(videoList);
        detail.setVideoCount(videoList.size());
        return detail;
    }
    private void updateCategory(int channelId) {
        int pageSize = 80;
        MogoTVApiUtil.ListResultDTO dto = MogoTVApiUtil.getClipList(channelId, 1, 20);
        if (dto != null) {
            int totalPage = dto.getTotal() % pageSize == 0 ? dto.getTotal() / pageSize : dto.getTotal() / pageSize + 1;
            for (int i = 0; i < totalPage; i++) {
                dto = MogoTVApiUtil.getClipList(channelId, i + 1, pageSize);
                for (MogoTVClipInfo clipInfo : (List<MogoTVClipInfo>) dto.getList()) {
                    System.out.println(clipInfo.getTitle() + ":" + clipInfo.getClipId());
                    try {
                        MogoTVClipInfo detail = getClipDetail(clipInfo);
                        mogoTVService.save(detail);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    private int getChannelId(String cate) throws Exception {
        switch (cate) {
            case "综艺":
                return 1;
            case "电影":
                return 3;
            case "电视剧":
                return 2;
            case "动漫":
                return 50;
        }
        throw new Exception("类型不匹配");
    }
    /**
     * 更新最近几天的视频
     *
     * @param param
     * @return
     * @throws Exception
     */
    @XxlJob("video-update-mogotv-updateVideo")
    public ReturnT<String> updateLatestVideo(String param) throws Exception {
        String[] types = new String[]{
                "电影", "电视剧", "动漫", "综艺"
        };
        if (!StringUtil.isNullOrEmpty(param)) {
            updateCategory(getChannelId(param));
        } else {
            for (String type : types) {
                updateCategory(getChannelId(type));
            }
        }
        return ReturnT.SUCCESS;
    }
    /**
     * 更新单个视频
     *
     * @param param
     * @return
     * @throws Exception
     */
    @XxlJob("video-update-mogotv-updateSingleVideo")
    public ReturnT<String> updateSingleVideo(String param) throws Exception {
        String[] cids = param.split(",");
        for (String cid : cids) {
            MogoTVClipInfo clipInfo = mogoTVService.getSimpleClipDetail(cid);
            if (clipInfo != null) {
                MogoTVClipInfo info = getClipDetail(clipInfo);
                mogoTVService.save(info);
            }
        }
        return ReturnT.SUCCESS;
    }
}
src/main/java/com/yeshi/buwan/job/video/TencentVideoUpdate.java
New file
@@ -0,0 +1,110 @@
package com.yeshi.buwan.job.video;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.yeshi.buwan.mogotv.MogoTVApiUtil;
import com.yeshi.buwan.mogotv.entity.MogoTVClipInfo;
import com.yeshi.buwan.mogotv.entity.MogoTVVideo;
import com.yeshi.buwan.service.inter.juhe.MogoTVService;
import com.yeshi.buwan.service.inter.juhe.TencentVideoService;
import com.yeshi.buwan.tencent.TencentVideoApiUtil;
import com.yeshi.buwan.tencent.TencentVideoUtil;
import com.yeshi.buwan.tencent.entity.TencentCoverInfo;
import com.yeshi.buwan.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Component
public class TencentVideoUpdate {
    private final static Logger logger = LoggerFactory.getLogger(TencentVideoUpdate.class);
    @Resource
    private TencentVideoService tencentVideoService;
    private TencentCoverInfo getCoverDetail(String coverId) throws Exception {
        TencentCoverInfo detail = TencentVideoApiUtil.getCoverInfo(String.format("https://v.qq.com/x/cover/%s.html", coverId));
        return detail;
    }
    private void updateCategory(String channel) {
        int totalPage = 50;
        for (int i = 0; i < totalPage; i++) {
            List<TencentCoverInfo> coverInfoList = TencentVideoApiUtil.getVideoListByCategory(channel, i + 1);
            for (TencentCoverInfo coverInfo : coverInfoList) {
                System.out.println(coverInfo.getTitle()+":"+coverInfo.getCover_id());
                try {
                    tencentVideoService.save(coverInfo);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private String getChannel(String cate) throws Exception {
        switch (cate) {
            case "综艺":
                return "variety";
            case "电影":
                return "movie";
            case "电视剧":
                return "tv";
            case "动漫":
                return "cartoon";
        }
        throw new Exception("类型不匹配");
    }
    /**
     * 更新最近几天的视频
     *
     * @param param
     * @return
     * @throws Exception
     */
    @XxlJob("video-update-tencent-updateVideo")
    public ReturnT<String> updateLatestVideo(String param) throws Exception {
        String[] types = new String[]{
                "电视剧", "动漫"
        };
        if (!StringUtil.isNullOrEmpty(param)) {
            updateCategory(getChannel(param));
        } else {
            for (String type : types) {
                updateCategory(getChannel(type));
            }
        }
        return ReturnT.SUCCESS;
    }
    /**
     * 更新单个视频
     *
     * @param param
     * @return
     * @throws Exception
     */
    @XxlJob("video-update-tencent-updateSingleVideo")
    public ReturnT<String> updateSingleVideo(String param) throws Exception {
        String[] cids = param.split(",");
        for (String cid : cids) {
            try {
                TencentCoverInfo detail = getCoverDetail(cid);
                tencentVideoService.save(detail);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return ReturnT.SUCCESS;
    }
}
src/main/java/com/yeshi/buwan/mogotv/MogoTVApiUtil.java
@@ -4,21 +4,15 @@
import com.google.gson.reflect.TypeToken;
import com.yeshi.buwan.mogotv.entity.MogoTVClipInfo;
import com.yeshi.buwan.mogotv.entity.MogoTVVideo;
import com.yeshi.buwan.youku.entity.YouKuShowDetail;
import com.yeshi.buwan.youku.entity.YouKuShowSimple;
import com.yeshi.buwan.youku.entity.YouKuVideo;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.yeshi.utils.HttpUtil;
import org.yeshi.utils.StringUtil;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.util.*;
public class MogoTVApiUtil {
@@ -33,12 +27,6 @@
//    https://pcweb.api.mgtv.com/episode/list?src=intelmgtv&abroad=0&_support=10000000&version=5.5.35&video_id=11026579&page=0&size=30&abroad=0&src=intelmgtv&callback=jsonp_1616648013585_27530
//
//    isIntact:1表示正片
    private final static String APP_ID = "758bef946d0050ef";
    private final static String APP_SECRET = "e113a131d49e1f837402e2807f2daf58";
    private static ScriptEngine jsEngine;
@@ -59,8 +47,7 @@
            String script = "function getData(){ return " + result + ";}\n";
            script += String.format("function %s(t){return t;}", callback);
            jsEngine.eval(script);
        } catch (
                ScriptException e) {
        } catch (ScriptException e) {
            e.printStackTrace();
        }
@@ -94,10 +81,21 @@
            data = data.optJSONObject("data");
            int totalPage = data.optInt("total_page");
            JSONArray list = data.optJSONArray("list");
            JSONObject list = data.optJSONObject("list");
            JSONArray array = null;
            if (list.isArray()) {
                array = data.optJSONArray("list");
            } else {
                array = new JSONArray();
                for (Iterator<String> its = list.keys(); its.hasNext(); ) {
                    String key = its.next();
                    array.add(list.optJSONObject(key));
                }
            }
            Type type = new TypeToken<List<MogoTVVideo>>() {
            }.getType();
            List<MogoTVVideo> videoList = new Gson().fromJson(list.toString(), type);
            List<MogoTVVideo> videoList = new Gson().fromJson(array.toString(), type);
            for (int i = 0; i < videoList.size(); i++) {
                if (videoList.get(i).getIsIntact() != 1) {
                    videoList.remove(i--);
@@ -169,6 +167,11 @@
            clipInfo.setLanguage(detail.optString("language"));
            clipInfo.setFstlvlType(detail.optString("fstlvlType"));
            clipInfo.setStory(detail.optString("story"));
            String updateInfo = detail.optString("updateInfo");
            updateInfo = updateInfo.replace("更新到", "更新至");
            if (updateInfo.contains(","))
                updateInfo = updateInfo.split(",")[updateInfo.split(",").length - 1];
            clipInfo.setUpdateInfo(updateInfo);
            return clipInfo;
        }
        return null;
src/main/java/com/yeshi/buwan/mogotv/MogoTVUtil.java
@@ -66,7 +66,7 @@
        }
        MogoTVClipInfo showDetail = mogoTVService.getSimpleClipDetail(map.getClipId());
        showDetail.setVideoList(mogoTVService.getVideoList(showDetail.getClipId(), 1, 100));
        showDetail.setVideoList(mogoTVService.getVideoList(showDetail.getClipId(), 1, 100,"综艺".equalsIgnoreCase(showDetail.getFstlvlType())?false:true));
        VideoInfo info = VideoInfoFactory.create(internetSearchVideo);
        info.setIntroduction(showDetail.getStory());
        info.setVideoDetailList(MogoTVUtil.convertToDetail(showDetail.getVideoList(), showDetail));
@@ -126,7 +126,7 @@
        VideoResource videoResource = videoResourceService.getResource(resourceid + "");
        playUrl.setResource(videoResource);
        MogoTVVideo mogoTVVideo = mogoTVService.getVideoDetail(id);
        playUrl.setUrl("https://www.mgtv.com"+mogoTVVideo.getUrl());
        playUrl.setUrl("https://m.mgtv.com"+mogoTVVideo.getUrl());
        playUrl.setPlayType(1);
        playUrl.setParams("");
        return playUrl;
src/main/java/com/yeshi/buwan/service/imp/SearchService.java
@@ -316,12 +316,15 @@
            }
        }
        //第一页而且不为高清时搜索
        //第一页,不为高清,主搜索引擎无法搜索到内容时搜索
        if (page == 1 && videoType != Constant.SEARCH_RESULT_TYPE_HIGH_DEFINITION) {
            //page为1时 全网搜
            SolrResultDTO internetSearchResultDTO = solrInternetSearchVideoDataManager.find(filter, 1, 20);
            if (internetSearchResultDTO != null && internetSearchResultDTO.getVideoList().size() > 0) {
                List<InternetSearchVideo> isvList = internetSearchResultDTO.getVideoList();
                List<InternetSearchVideo> iList = internetSearchResultDTO.getVideoList();
                List<InternetSearchVideo> isvList = new ArrayList<>();
                if (iList != null && iList.size() > 0)
                    isvList.addAll(iList);
                //删除前面有的数据,根据rootType与名称筛选
                for (int i = 0; i < isvList.size(); i++) {
                    String uniqueId = isvList.get(i).getName() + "#" + isvList.get(i).getRootType();
@@ -333,11 +336,27 @@
                for (InternetSearchVideo sv : isvList) {
                    VideoInfo video = VideoInfoFactory.create(sv);
                    video = loadAlbumData(video);
                    if (albumCount < 3) {
                        localList.add(video);
                    } else {
                        if (video.getName().equalsIgnoreCase(key))
                    localList.add(video);
                }
            }
            }
            //todo 按关键词的匹配度排序
            Comparator<VideoInfo> cm = new Comparator<VideoInfo>() {
                @Override
                public int compare(VideoInfo o1, VideoInfo o2) {
                    float s1 = CompareStrSimUtil.getSimilarityRatio(o1.getName(), key, true);
                    float s2 = CompareStrSimUtil.getSimilarityRatio(o2.getName(), key, true);
                    return s2 > s1 ? 1 : -1;
                }
            };
            Collections.sort(localList,cm);
        }
        return new SearchResult(albumCount, localList);
    }
src/main/java/com/yeshi/buwan/service/imp/juhe/InternetSearchVideoServiceImpl.java
@@ -2,8 +2,10 @@
import com.yeshi.buwan.dao.juhe.youku.InternetSearchVideoDao;
import com.yeshi.buwan.domain.video.InternetSearchVideo;
import com.yeshi.buwan.dto.mq.InternetSearchVideoMQMsg;
import com.yeshi.buwan.exception.ParamsException;
import com.yeshi.buwan.service.inter.juhe.InternetSearchVideoService;
import com.yeshi.buwan.util.mq.CMQManager;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -25,7 +27,8 @@
    public void save(@Valid InternetSearchVideo video) throws ParamsException, Exception {
        InternetSearchVideo oldVideo = internetSearchVideoDao.get(video.getId());
        Set<Integer> resourceIds = listResourceId(video);
        resourceIds.add(Integer.parseInt(video.getResourceIds()));
        int resourceId = Integer.parseInt(video.getResourceIds());
        resourceIds.add(resourceId);
        Integer[] rids = new Integer[resourceIds.size()];
        resourceIds.toArray(rids);
        video.setResourceIds(StringUtil.concat(rids, ","));
@@ -35,6 +38,11 @@
        } else {
            internetSearchVideoDao.updateSelective(video);
        }
        InternetSearchVideoMQMsg msg = new InternetSearchVideoMQMsg();
        msg.setId(video.getId());
        msg.setResourceId(resourceId);
        CMQManager.getInstance().addInternetSearchVideoUpdateMsg(msg);
    }
    private Set<Integer> listResourceId(InternetSearchVideo video) {
src/main/java/com/yeshi/buwan/service/imp/juhe/MogoTVServiceImpl.java
@@ -36,7 +36,7 @@
    private InternetSearchVideoService internetSearchVideoService;
    @Override
    public void save(MogoTVClipInfo detail) {
    public void save(MogoTVClipInfo detail) throws Exception {
        if (detail.getUpdateTime() == null)
            detail.setUpdateTime(new Date());
        mogoTVClipInfoDao.save(detail);
@@ -47,6 +47,7 @@
                }
                mogoTVVideoDao.save(video);
            }
        internetSearchVideoService.save(InternetSearchVideoFactory.create(detail));
    }
    @Override
@@ -69,10 +70,10 @@
    }
    @Override
    public List<MogoTVVideo> getVideoList(String clipId, int page, int pageSize) {
    public List<MogoTVVideo> getVideoList(String clipId, int page, int pageSize, boolean asc) {
        Query query = new Query();
        query.addCriteria(Criteria.where("clipId").is(clipId));
        query.with(new Sort(new Sort.Order(Sort.Direction.ASC, "t1")));
        query.addCriteria(Criteria.where("clip_id").is(clipId));
        query.with(new Sort(new Sort.Order(asc ? Sort.Direction.ASC : Sort.Direction.DESC, "t1")));
        query.skip((page - 1) * pageSize);
        query.limit(pageSize);
        List<MogoTVVideo> videoList = mogoTVVideoDao.findList(query);
@@ -81,7 +82,9 @@
    @Override
    public MogoTVVideo getVideoDetail(String id) {
        return mogoTVVideoDao.get(id);
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        return mogoTVVideoDao.findOne(query);
    }
@@ -110,7 +113,7 @@
            return null;
        MogoTVClipInfo clipInfo = mogoTVClipInfoDao.get(map.getClipId());
        return MogoTVUtil.convertToDetail(getVideoList(map.getClipId(), page, pageSize), clipInfo);
        return MogoTVUtil.convertToDetail(getVideoList(map.getClipId(), page, pageSize, "综艺".equalsIgnoreCase(clipInfo.getFstlvlType()) ? false : true), clipInfo);
    }
    @Override
src/main/java/com/yeshi/buwan/service/imp/juhe/TencentVideoServiceImpl.java
@@ -1,16 +1,24 @@
package com.yeshi.buwan.service.imp.juhe;
import com.yeshi.buwan.dao.juhe.tencent.TencentCoverInfoDao;
import com.yeshi.buwan.dao.juhe.tencent.TencentCoverVideoDao;
import com.yeshi.buwan.dao.juhe.tencent.TencentSearchVideoMapDao;
import com.yeshi.buwan.domain.VideoDetailInfo;
import com.yeshi.buwan.domain.video.InternetSearchVideo;
import com.yeshi.buwan.service.inter.juhe.InternetSearchVideoService;
import com.yeshi.buwan.service.inter.juhe.TencentVideoService;
import com.yeshi.buwan.tencent.TencentVideoUtil;
import com.yeshi.buwan.tencent.entity.TencentCoverInfo;
import com.yeshi.buwan.youku.entity.YouKuShowDetail;
import com.yeshi.buwan.youku.entity.YouKuVideo;
import com.yeshi.buwan.tencent.entity.TencentCoverVideo;
import com.yeshi.buwan.tencent.entity.TencentSearchVideoMap;
import com.yeshi.buwan.util.factory.InternetSearchVideoFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -18,36 +26,125 @@
public class TencentVideoServiceImpl implements TencentVideoService {
    @Resource
    private TencentSearchVideoMapDao tencentSearchVideoMapDao;
    @Resource
    private TencentCoverInfoDao tencentCoverInfoDao;
    @Resource
    private TencentCoverVideoDao tencentCoverVideoDao;
    @Resource
    private InternetSearchVideoService internetSearchVideoService;
    @Override
    public void save(TencentCoverInfo detail) {
    public void save(TencentCoverInfo detail) throws Exception {
        List<TencentCoverVideo> videoList = new ArrayList<>();
        for (TencentCoverInfo.VipIdsBean idsBean : detail.getVip_ids()) {
            TencentCoverVideo video = new TencentCoverVideo();
            video.setCoverId(detail.getCover_id());
            video.setPosition(idsBean.getP());
            video.setStage(idsBean.getP() + 1);
            video.setVideoId(idsBean.getV());
            video.setLink(String.format("https://v.qq.com/x/cover/%s/%s.html", detail.getCover_id(), idsBean.getV()));
            if (idsBean.getF() == 2 || idsBean.getF() == 7)
                videoList.add(video);
        }
        detail.setVideoList(videoList);
        if (detail.getUpdateTime() == null)
            detail.setUpdateTime(new Date());
        tencentCoverInfoDao.save(detail);
        if (detail.getVideoList() != null)
            for (TencentCoverVideo video : detail.getVideoList()) {
                if (video.getUpdateTime() == null) {
                    video.setUpdateTime(new Date());
                }
                tencentCoverVideoDao.save(video);
            }
        internetSearchVideoService.save(InternetSearchVideoFactory.create(detail));
    }
    @Override
    public TencentCoverInfo getConverDetail(String id) {
        TencentCoverInfo detail = tencentCoverInfoDao.get(id);
    public TencentCoverInfo getCoverDetail(String coverId) {
        TencentCoverInfo detail = tencentCoverInfoDao.get(coverId);
        Query query = new Query();
        if (detail != null) {
            query.addCriteria(Criteria.where("coverId").is(coverId));
        }
        query.with(new Sort(new Sort.Order(Sort.Direction.ASC, "show_videoseq")));
        List<TencentCoverVideo> videoList = tencentCoverVideoDao.findList(query);
        detail.setVideoList(videoList);
        return detail;
    }
    @Override
    public long count(String type) {
    public TencentCoverInfo getSimpleCoverDetail(String coverId) {
        TencentCoverInfo detail = tencentCoverInfoDao.get(coverId);
        return detail;
    }
    @Override
    public List<TencentCoverVideo> getVideoList(String coverId, int page, int pageSize) {
        Query query = new Query();
        if (type != null)
            query.addCriteria(Criteria.where("type").is(type));
        query.addCriteria(Criteria.where("coverId").is(coverId));
        query.with(new Sort(new Sort.Order(Sort.Direction.ASC, "position")));
        query.skip((page - 1) * pageSize);
        query.limit(pageSize);
        List<TencentCoverVideo> videoList = tencentCoverVideoDao.findList(query);
        return videoList;
    }
    @Override
    public TencentCoverVideo getVideoDetail(String id) {
        return tencentCoverVideoDao.get(id);
    }
    @Override
    public long count(String category) {
        Query query = new Query();
        if (category != null)
            query.addCriteria(Criteria.where("type_name").is(category));
        return tencentCoverInfoDao.count(query);
    }
    @Override
    public List<TencentCoverInfo> list(String type, int page, int pageSize) {
    public List<TencentCoverInfo> list(String category, int page, int pageSize) {
        Query query = new Query();
        if (type != null)
            query.addCriteria(Criteria.where("type").is(type));
        if (category != null)
            query.addCriteria(Criteria.where("type_name").is(category));
        query.limit(pageSize);
        query.skip((page - 1) * pageSize);
        return tencentCoverInfoDao.findList(query);
    }
    @Override
    public List<VideoDetailInfo> getVideoDetailList(String videoid, int page, int pageSize) {
        TencentSearchVideoMap map = tencentSearchVideoMapDao.selectByVideoId(videoid);
        if (map == null)
            return null;
        TencentCoverInfo coverInfo = tencentCoverInfoDao.get(map.getCoverId());
        return TencentVideoUtil.convertToDetail(getVideoList(map.getCoverId(), page, pageSize), coverInfo);
    }
    @Override
    public TencentSearchVideoMap selectMapByVideoId(String videoId) {
        TencentSearchVideoMap map = tencentSearchVideoMapDao.selectByVideoId(videoId);
        return map;
    }
    @Override
    public void addToInternetSearch(TencentCoverInfo showDetail) throws Exception {
        InternetSearchVideo video = InternetSearchVideoFactory.create(showDetail);
        internetSearchVideoService.save(video);
        TencentSearchVideoMap map = new TencentSearchVideoMap();
        map.setCoverId(showDetail.getId());
        map.setVideoId(video.getId());
        map.setCreateTime(new Date());
        tencentSearchVideoMapDao.save(map);
    }
}
src/main/java/com/yeshi/buwan/service/imp/juhe/YouKuServiceImpl.java
@@ -35,7 +35,7 @@
    private InternetSearchVideoService internetSearchVideoService;
    @Override
    public void save(YouKuShowDetail detail) {
    public void save(YouKuShowDetail detail) throws Exception {
        if (detail.getUpdateTime() == null)
            detail.setUpdateTime(new Date());
        youKuShowDetailDao.save(detail);
@@ -46,6 +46,8 @@
                }
                youKuVideoDao.save(video);
            }
        internetSearchVideoService.save(InternetSearchVideoFactory.create(detail));
    }
    @Override
src/main/java/com/yeshi/buwan/service/inter/juhe/InternetSearchVideoService.java
@@ -19,5 +19,4 @@
    public InternetSearchVideo selectByPrimaryKey(String id);
}
src/main/java/com/yeshi/buwan/service/inter/juhe/MogoTVService.java
@@ -16,14 +16,14 @@
     * @param detail
     */
    
    public void save(MogoTVClipInfo detail);
    public void save(MogoTVClipInfo detail) throws Exception;
    public MogoTVClipInfo getClipDetail(String clipId);
    public MogoTVClipInfo getSimpleClipDetail(String clipId);
    
    public List<MogoTVVideo> getVideoList(String clipId, int page, int pageSize);
    public List<MogoTVVideo> getVideoList(String clipId, int page, int pageSize,boolean asc);
    public MogoTVVideo getVideoDetail(String id);
src/main/java/com/yeshi/buwan/service/inter/juhe/TencentVideoService.java
@@ -1,7 +1,9 @@
package com.yeshi.buwan.service.inter.juhe;
import com.yeshi.buwan.domain.VideoDetailInfo;
import com.yeshi.buwan.tencent.entity.TencentCoverInfo;
import com.yeshi.buwan.youku.entity.YouKuShowDetail;
import com.yeshi.buwan.tencent.entity.TencentCoverVideo;
import com.yeshi.buwan.tencent.entity.TencentSearchVideoMap;
import java.util.List;
@@ -12,12 +14,30 @@
     *
     * @param detail
     */
    public void save(TencentCoverInfo detail);
    public TencentCoverInfo getConverDetail(String id);
    public void save(TencentCoverInfo detail) throws Exception;
    public long count(String type);
    public TencentCoverInfo getCoverDetail(String coverId);
    public List<TencentCoverInfo> list(String type, int page, int pageSize);
    public TencentCoverInfo getSimpleCoverDetail(String coverId);
    public List<TencentCoverVideo> getVideoList(String coverId, int page, int pageSize);
    public TencentCoverVideo getVideoDetail(String id);
    public long count(String category);
    public List<TencentCoverInfo> list(String category, int page, int pageSize);
    public List<VideoDetailInfo> getVideoDetailList(final String videoid, int page, int pageSize);
    public TencentSearchVideoMap selectMapByVideoId(String videoId);
    /**
     * 添加到全网搜
     *
     * @param showDetail
     */
    public void addToInternetSearch(TencentCoverInfo showDetail) throws Exception;
}
src/main/java/com/yeshi/buwan/service/inter/juhe/YouKuService.java
@@ -14,7 +14,7 @@
     *
     * @param detail
     */
    public void save(YouKuShowDetail detail);
    public void save(YouKuShowDetail detail) throws Exception;
    public YouKuShowDetail getShowDetail(String showId);
src/main/java/com/yeshi/buwan/service/manager/SolrAlbumVideoDataManager.java
@@ -18,6 +18,7 @@
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
@@ -138,7 +139,11 @@
            if (filter.isFuzzy()) {
                query = new SimpleQuery(new Criteria("name").expression(filter.getKey()));
            } else {
                try {
                query = new SimpleQuery(new Criteria("nameStr").startsWith(filter.getKey()).or("mainactor").expression("\"" + filter.getKey() + "\""));
                } catch (InvalidDataAccessApiUsageException e) {
                    query = new SimpleQuery(new Criteria("nameStr").expression("\""+filter.getKey()+"\"").or("mainactor").expression("\"" + filter.getKey() + "\""));
                }
            }
        } else if (!StringUtil.isNullOrEmpty(filter.getActor())) {
            query = new SimpleQuery(new Criteria("mainactor").expression("\"" + filter.getActor() + "\""));
src/main/java/com/yeshi/buwan/service/manager/SolrInternetSearchVideoDataManager.java
@@ -8,6 +8,7 @@
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
@@ -94,10 +95,16 @@
            filter.setKey("");
        }
        logger.info(filter.getKey() + "#" + page);
        String key = filter.getKey();//.replace(" ", "\\ ");
        Query query = null;
        if (!StringUtil.isNullOrEmpty(filter.getKey())) {
            //solr精准检索需要带引号
            query = new SimpleQuery(new Criteria("nameStr").startsWith(filter.getKey()).or("actors").expression("\"" + filter.getKey() + "\""));
            try {
                query = new SimpleQuery(new Criteria("nameStr").startsWith(key).or("actors").expression("\"" + key + "\""));
            } catch (InvalidDataAccessApiUsageException e) {
                query = new SimpleQuery(new Criteria("name").expression("\""+key+"\""));
            }
        } else if (!StringUtil.isNullOrEmpty(filter.getActor())) {
            query = new SimpleQuery(new Criteria("actors").expression("\"" + filter.getActor() + "\""));
        } else if (!StringUtil.isNullOrEmpty(filter.getDirector())) {
src/main/java/com/yeshi/buwan/tencent/TencentVideoApiUtil.java
New file
@@ -0,0 +1,191 @@
package com.yeshi.buwan.tencent;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yeshi.buwan.tencent.entity.TencentCoverInfo;
import net.sf.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class TencentVideoApiUtil {
    static ScriptEngine jsEngine = null;
//    static {
//        if (jdGoodsJs == null)
//            jdGoodsJs = getJDGoodsJS();
//        ScriptEngineManager manager = new ScriptEngineManager();
//        jsEngine = manager.getEngineByName("javascript");
//        try {
//            jsEngine.eval(jdGoodsJs);
//        } catch (ScriptException e) {
//            e.printStackTrace();
//        }
//
//        if (jsEngine instanceof Invocable) {
//            Invocable in = (Invocable) jsEngine;
//            Object goodsId = in.invokeFunction("getGoodsId", link);
//            if (goodsId != null)
//                return goodsId.toString().trim();
//        }
//
//    }
    private static List<String> objToArray(JSONObject root, String key) {
        if (root.optJSONObject(key) == null) {
            return null;
        }
        Gson gson = new Gson();
        List<String> directors = new ArrayList<>();
        if (root.optJSONObject(key).isArray()) {
            Type type = new TypeToken<List<String>>() {
            }.getType();
            directors = gson.fromJson(root.optJSONArray(key).toString(), type);
        } else {
            JSONObject director = root.optJSONObject(key);
            for (Iterator<String> its = director.keys(); its.hasNext(); ) {
                String p = its.next();
                directors.add(director.optString(p));
            }
        }
        root.remove(key);
        return directors;
    }
    public static TencentCoverInfo getCoverInfo(String url) throws Exception {
        String script = null;
        Document doc = Jsoup.connect(url).timeout(10000).userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36").get();
        Elements els = doc.getElementsByTag("script");
        for (int i = 0; i < els.size(); i++) {
            if (els.get(i).html().indexOf("var COVER_INFO") > -1) {
                script = els.get(i).html();
                break;
            }
        }
        script = script.replace("window.", "_window.");
        script = " var _window={};" + "var document={getElementsByTagName:function(tag){return [''];}};" + script;
        script += "\n function getCoverInfo(){return COVER_INFO }; function getVideoInfo(){return VIDEO_INFO}";
        ScriptEngineManager manager = new ScriptEngineManager();
        jsEngine = manager.getEngineByName("javascript");
        try {
            jsEngine.eval(script);
        } catch (ScriptException e) {
            e.printStackTrace();
        }
        Gson gson = new Gson();
        if (jsEngine instanceof Invocable) {
            Invocable in = (Invocable) jsEngine;
            Object coverInfo = in.invokeFunction("getCoverInfo");
            JSONObject root = JSONObject.fromObject(gson.toJson(coverInfo));
            System.out.println(root.toString());
            List<TencentCoverInfo.VipIdsBean> vipIdsBeans = new ArrayList<>();
            if (root.optJSONObject("vip_ids").isArray()) {
                Type type = new TypeToken<List<TencentCoverInfo.VipIdsBean>>() {
                }.getType();
                vipIdsBeans = gson.fromJson(root.optJSONArray("vip_ids").toString(), type);
            } else {
                JSONObject vipIds = root.optJSONObject("vip_ids");
                for (Iterator<String> its = vipIds.keys(); its.hasNext(); ) {
                    String p = its.next();
                    TencentCoverInfo.VipIdsBean idsBean = gson.fromJson(vipIds.optJSONObject(p).toString(), TencentCoverInfo.VipIdsBean.class);
                    idsBean.setP(Integer.parseInt(p));
                    vipIdsBeans.add(idsBean);
                }
            }
            root.remove("vip_ids");
            try {
                List<String> subTypes = objToArray(root, "subtype");
                List<String> directors = objToArray(root, "director");
                List<String> leadingActor = objToArray(root, "leading_actor");
                List<String> subGenre = objToArray(root, "sub_genre");
                TencentCoverInfo coverInfoBean = gson.fromJson(root.toString(), TencentCoverInfo.class);
                coverInfoBean.setVip_ids(vipIdsBeans);
                coverInfoBean.setSubtype(subTypes);
                coverInfoBean.setDirector(directors);
                coverInfoBean.setLeading_actor(leadingActor);
                coverInfoBean.setSub_genre(subGenre);
                return coverInfoBean;
            } catch (Exception e) {
                e.printStackTrace();
            }
//            System.out.println(coverInfoBean);
        }
        return null;
    }
    private static List<TencentCoverInfo> parseList(String url) {
        List<TencentCoverInfo> coverInfoList = new ArrayList<>();
        try {
            Document document = Jsoup.connect(url).timeout(5000).get();
            Elements els = document.getElementsByAttributeValue("class", "list_item");
            for (int i = 0; i < els.size(); i++) {
                String href = els.get(i).getElementsByTag("a").get(0).attr("href");
                String img = els.get(i).getElementsByTag("img").get(0).attr("src");
                img = img.startsWith("http") ? img : "http:" + img;
                try {
                    TencentCoverInfo coverInfo = getCoverInfo(href);
                    coverInfo.setVertical_pic_url(img);
                    coverInfoList.add(coverInfo);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return coverInfoList;
    }
    public static List<TencentCoverInfo> getVideoListByCategory(String channel, int page) {
        return parseList(String.format("https://v.qq.com/x/bu/pagesheet/list?_all=1&append=1&channel=%s&ipay=2&listpage=%s&offset=%s&pagesize=30&sort=18", channel, page, (page - 1) * 30));
    }
    public static void main(String[] args) throws Exception {
//        try {
        TencentCoverInfo info = getCoverInfo("https://v.qq.com/x/cover/7q544xyrava3vxf.html");
        System.out.println(info);
//
//            info = getCoverInfo("https://v.qq.com/x/cover/mzc00200s0ii272/r0036xibgw2.html");
//            info = getCoverInfo("https://v.qq.com/x/cover/ylgl3m6wo0sypou/w0036x9c5c7.html");
//            info = getCoverInfo("https://v.qq.com/x/cover/ylgl3m6wo0sypou/w0036x9c5c7.html");
//            //
//            info = getCoverInfo("https://v.qq.com/x/cover/mzc00200tlv15ub.html");
//            System.out.println(info);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        int page = 1;
        List<TencentCoverInfo> list = getVideoListByCategory("cartoon", 1);
        System.out.println(list);
    }
}
src/main/java/com/yeshi/buwan/tencent/TencentVideoUtil.java
@@ -1,186 +1,137 @@
package com.yeshi.buwan.tencent;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yeshi.buwan.domain.VideoDetailInfo;
import com.yeshi.buwan.domain.VideoInfo;
import com.yeshi.buwan.domain.VideoResource;
import com.yeshi.buwan.domain.entity.PlayUrl;
import com.yeshi.buwan.domain.video.InternetSearchVideo;
import com.yeshi.buwan.service.imp.VideoResourceService;
import com.yeshi.buwan.service.imp.VideoTypeService;
import com.yeshi.buwan.service.inter.juhe.InternetSearchVideoService;
import com.yeshi.buwan.service.inter.juhe.TencentVideoService;
import com.yeshi.buwan.tencent.entity.TencentCoverInfo;
import net.sf.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.yeshi.utils.HttpUtil;
import com.yeshi.buwan.tencent.entity.TencentCoverVideo;
import com.yeshi.buwan.tencent.entity.TencentSearchVideoMap;
import com.yeshi.buwan.util.factory.VideoInfoFactory;
import com.yeshi.buwan.util.video.VideoConstant;
import com.yeshi.buwan.youku.YouKuUtil;
import org.springframework.stereotype.Component;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Component
public class TencentVideoUtil {
    static ScriptEngine jsEngine = null;
//    static {
//        if (jdGoodsJs == null)
//            jdGoodsJs = getJDGoodsJS();
//        ScriptEngineManager manager = new ScriptEngineManager();
//        jsEngine = manager.getEngineByName("javascript");
//        try {
//            jsEngine.eval(jdGoodsJs);
//        } catch (ScriptException e) {
//            e.printStackTrace();
//        }
//
//        if (jsEngine instanceof Invocable) {
//            Invocable in = (Invocable) jsEngine;
//            Object goodsId = in.invokeFunction("getGoodsId", link);
//            if (goodsId != null)
//                return goodsId.toString().trim();
//        }
//
//    }
    @Resource
    private InternetSearchVideoService internetSearchVideoService;
    @Resource
    private TencentVideoService tencentVideoService;
    private static List<String> objToArray(JSONObject root, String key) {
    @Resource
    private VideoResourceService videoResourceService;
        if (root.optJSONObject(key) == null) {
            return null;
        }
    @Resource
    private VideoTypeService videoTypeService;
        Gson gson = new Gson();
    public final static int RESOURCE_ID = 17;
        List<String> directors = new ArrayList<>();
        if (root.optJSONObject(key).isArray()) {
            Type type = new TypeToken<List<String>>() {
            }.getType();
            directors = gson.fromJson(root.optJSONArray(key).toString(), type);
        } else {
            JSONObject director = root.optJSONObject(key);
            for (Iterator<String> its = director.keys(); its.hasNext(); ) {
                String p = its.next();
                directors.add(director.optString(p));
            }
        }
        root.remove(key);
        return directors;
    }
    public static TencentCoverInfo getCoverInfo(String url) throws Exception {
        String script = null;
        Document doc = Jsoup.connect(url).timeout(10000).userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36").get();
        Elements els = doc.getElementsByTag("script");
        for (int i = 0; i < els.size(); i++) {
            if (els.get(i).html().indexOf("var COVER_INFO") > -1) {
                script = els.get(i).html();
    public static VideoDetailInfo convertToDetail(TencentCoverVideo tencentCoverVideo, TencentCoverInfo coverInfo) {
        VideoDetailInfo detail = new VideoDetailInfo();
        switch (coverInfo.getType_name()) {
            case "电影":
                detail.setTag(coverInfo.getTitle());
                break;
            case "电视剧":
            case "动漫":
                detail.setTag(tencentCoverVideo.getStage() + "");
                break;
            case "综艺":
                detail.setTag(tencentCoverVideo.getDate());
                break;
            }
        detail.setName(coverInfo.getTitle());
        detail.setExtraId(tencentCoverVideo.getVideoId());
        detail.setType("url");
        return detail;
        }
        script = script.replace("window.", "_window.");
        script = " var _window={};" + "var document={getElementsByTagName:function(tag){return [''];}};" + script;
        script += "\n function getCoverInfo(){return COVER_INFO }; function getVideoInfo(){return VIDEO_INFO}";
        ScriptEngineManager manager = new ScriptEngineManager();
        jsEngine = manager.getEngineByName("javascript");
        try {
            jsEngine.eval(script);
        } catch (ScriptException e) {
            e.printStackTrace();
    public VideoInfo getVideoInfo(InternetSearchVideo internetSearchVideo) throws Exception {
        TencentSearchVideoMap map = tencentVideoService.selectMapByVideoId(internetSearchVideo.getId());
        if (map == null) {
            throw new Exception("视频源不存在");
        }
        Gson gson = new Gson();
        if (jsEngine instanceof Invocable) {
            Invocable in = (Invocable) jsEngine;
            Object coverInfo = in.invokeFunction("getCoverInfo");
            JSONObject root = JSONObject.fromObject(gson.toJson(coverInfo));
            System.out.println(root.toString());
            List<TencentCoverInfo.VipIdsBean> vipIdsBeans = new ArrayList<>();
            if (root.optJSONObject("vip_ids").isArray()) {
                Type type = new TypeToken<List<TencentCoverInfo.VipIdsBean>>() {
                }.getType();
                vipIdsBeans = gson.fromJson(root.optJSONArray("vip_ids").toString(), type);
            } else {
                JSONObject vipIds = root.optJSONObject("vip_ids");
                for (Iterator<String> its = vipIds.keys(); its.hasNext(); ) {
                    String p = its.next();
                    TencentCoverInfo.VipIdsBean idsBean = gson.fromJson(vipIds.optJSONObject(p).toString(), TencentCoverInfo.VipIdsBean.class);
                    idsBean.setP(Integer.parseInt(p));
                    vipIdsBeans.add(idsBean);
        TencentCoverInfo showDetail = tencentVideoService.getSimpleCoverDetail(map.getCoverId());
        showDetail.setVideoList(tencentVideoService.getVideoList(showDetail.getId(), 1, 100));
        VideoInfo info = VideoInfoFactory.create(internetSearchVideo);
        info.setIntroduction(showDetail.getDescription());
        info.setVideoDetailList(convertToDetail(showDetail.getVideoList(), showDetail));
        info.setPlayPicture(info.getHpicture());
        //获取资源列表
        List<String> rids = Arrays.asList(internetSearchVideo.getResourceIds().split(","));
        List<VideoResource> resourceList = videoResourceService.getResource(rids);
        for (VideoResource vr : resourceList) {
            if (vr.getId().equalsIgnoreCase(RESOURCE_ID + ""))
                vr.setChecked(true);
                }
            }
            root.remove("vip_ids");
        info.setResourceList(resourceList);
        info.setShowType(YouKuUtil.getShowType(internetSearchVideo));
        info.setScore(new BigDecimal(showDetail.getScore().getScore()).setScale(1).toString());
            try {
                List<String> subTypes = objToArray(root, "subtype");
                List<String> directors = objToArray(root, "director");
                List<String> leadingActor = objToArray(root, "leading_actor");
                List<String> subGenre = objToArray(root, "sub_genre");
        //获取分类详情
        info.setVideoType(videoTypeService.getVideoType(info.getVideoType().getId()));
        info.setCommentCount(0);
        info.setVideocount((int) (Math.random() * 1000));
                TencentCoverInfo coverInfoBean = gson.fromJson(root.toString(), TencentCoverInfo.class);
                coverInfoBean.setVip_ids(vipIdsBeans);
                coverInfoBean.setSubtype(subTypes);
                coverInfoBean.setDirector(directors);
                coverInfoBean.setLeading_actor(leadingActor);
                coverInfoBean.setSub_genre(subGenre);
                return coverInfoBean;
            } catch (Exception e) {
                e.printStackTrace();
            }
//            System.out.println(coverInfoBean);
        }
        return null;
        return info;
    }
    private static void parseList(String url) {
        try {
            Document document = Jsoup.connect(url).timeout(5000).get();
            Elements els = document.getElementsByAttributeValue("class", "list_item");
            for (int i = 0; i < els.size(); i++) {
                String href = els.get(i).getElementsByTag("a").get(0).attr("href");
                String img = els.get(i).getElementsByTag("img").get(0).attr("src");
                img = img.startsWith("http") ? img : "http:" + img;
                try {
                    TencentCoverInfo coverInfo = getCoverInfo(href);
                    coverInfo.setVertical_pic_url(img);
                    System.out.println(coverInfo);
                } catch (Exception e) {
                    e.printStackTrace();
    public static List<VideoDetailInfo> convertToDetail(List<TencentCoverVideo> tencentCoverVideoList, TencentCoverInfo coverInfo) {
        List<VideoDetailInfo> detailList = new ArrayList<>();
        for (TencentCoverVideo video : tencentCoverVideoList) {
            detailList.add(convertToDetail(video, coverInfo));
                }
        return detailList;
            }
        } catch (IOException e) {
            e.printStackTrace();
    public static int getShowType(InternetSearchVideo video) {
        if (video == null)
            return 2;
        switch (video.getRootType()) {
            case VideoConstant
                    .VIDEO_CATEGORY_DIANYING:
                return 1;
            case VideoConstant
                    .VIDEO_CATEGORY_DIANSHIJU:
            case VideoConstant
                    .VIDEO_CATEGORY_DONGMAN:
                return 2;
            case VideoConstant
                    .VIDEO_CATEGORY_ZONGYI:
                return 1;
        }
        return 2;
        }
    public PlayUrl getPlayUrl(String detailSystemId, String id, String type, int resourceid, String videoid) {
        PlayUrl playUrl = new PlayUrl();
        VideoResource videoResource = videoResourceService.getResource(resourceid + "");
        playUrl.setResource(videoResource);
        TencentCoverVideo tencentCoverVideo = tencentVideoService.getVideoDetail(id);
        playUrl.setUrl(tencentCoverVideo.getLink());
        playUrl.setPlayType(1);
        playUrl.setParams("");
        return playUrl;
    }
    public static void main(String[] args) {
//        try {
//            TencentCoverInfo info = getCoverInfo("https://v.qq.com/x/cover/mzc00200fw94jce.html");
//
//            info = getCoverInfo("https://v.qq.com/x/cover/mzc00200s0ii272/r0036xibgw2.html");
//            info = getCoverInfo("https://v.qq.com/x/cover/ylgl3m6wo0sypou/w0036x9c5c7.html");
//            info = getCoverInfo("https://v.qq.com/x/cover/ylgl3m6wo0sypou/w0036x9c5c7.html");
//            //
//            info = getCoverInfo("https://v.qq.com/x/cover/mzc00200tlv15ub.html");
//            System.out.println(info);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        int page = 1;
        parseList(String.format("https://v.qq.com/x/bu/pagesheet/list?_all=1&append=1&channel=cartoon&ipay=2&listpage=%s&offset=%s&pagesize=30&sort=18", page, (page - 1) * 30));
    }
}
src/main/java/com/yeshi/buwan/tencent/entity/TencentCoverInfo.java
@@ -1,6 +1,7 @@
package com.yeshi.buwan.tencent.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.Date;
@@ -65,6 +66,9 @@
    private List<String> sub_genre;
    private Date createTime;
    private Date updateTime;
    @Transient
    private List<TencentCoverVideo> videoList;
    public Date getCreateTime() {
        return createTime;
@@ -275,6 +279,15 @@
        this.sub_genre = sub_genre;
    }
    public List<TencentCoverVideo> getVideoList() {
        return videoList;
    }
    public void setVideoList(List<TencentCoverVideo> videoList) {
        this.videoList = videoList;
    }
    public static class ScoreBean {
        /**
         * c_mix_score : 8.4
src/main/java/com/yeshi/buwan/tencent/entity/TencentCoverVideo.java
@@ -13,9 +13,10 @@
    private String videoId;
    @Indexed
    private String coverId;
    private int stage;//集数
    private int position;//position
    private Integer stage;//集数
    private Integer position;//position
    private String date;//date 时间
    private String link;
    private Date createTime;
    private Date updateTime;
@@ -35,19 +36,19 @@
        this.coverId = coverId;
    }
    public int getStage() {
    public Integer getStage() {
        return stage;
    }
    public void setStage(int stage) {
    public void setStage(Integer stage) {
        this.stage = stage;
    }
    public int getPosition() {
    public Integer getPosition() {
        return position;
    }
    public void setPosition(int position) {
    public void setPosition(Integer position) {
        this.position = position;
    }
@@ -74,4 +75,12 @@
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    public String getLink() {
        return link;
    }
    public void setLink(String link) {
        this.link = link;
    }
}
src/main/java/com/yeshi/buwan/util/CompareStrSimUtil.java
New file
@@ -0,0 +1,78 @@
package com.yeshi.buwan.util;
public class CompareStrSimUtil {
    private static int compare(String str, String target, boolean isIgnore) {
        int d[][]; // 矩阵
        int n = str.length();
        int m = target.length();
        int i; // 遍历str的
        int j; // 遍历target的
        char ch1; // str的
        char ch2; // target的
        int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        if (n == 0) {
            return m;
        }
        if (m == 0) {
            return n;
        }
        d = new int[n + 1][m + 1];
        for (i = 0; i <= n; i++) { // 初始化第一列
            d[i][0] = i;
        }
        for (j = 0; j <= m; j++) { // 初始化第一行
            d[0][j] = j;
        }
        for (i = 1; i <= n; i++) { // 遍历str
            ch1 = str.charAt(i - 1);
            // 去匹配target
            for (j = 1; j <= m; j++) {
                ch2 = target.charAt(j - 1);
                if (isIgnore) {
                    if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
                        temp = 0;
                    } else {
                        temp = 1;
                    }
                } else {
                    if (ch1 == ch2) {
                        temp = 0;
                    } else {
                        temp = 1;
                    }
                }
                // 左边+1,上边+1, 左上角+temp取最小
                d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
            }
        }
        return d[n][m];
    }
    private static int min(int one, int two, int three) {
        return (one = one < two ? one : two) < three ? one : three;
    }
    public static float getSimilarityRatio(String str, String target, boolean isIgnore) {
        float ret = 0;
        if (Math.max(str.length(), target.length()) == 0) {
            ret = 1;
        } else {
            ret = 1 - (float) compare(str, target, isIgnore) / Math.max(str.length(), target.length());
        }
        return ret;
    }
    public static void main(String[] args) {
        CompareStrSimUtil lt = new CompareStrSimUtil();
        String str = "斗罗大陆";
        String target = "斗罗大陆";
        System.out.println("similarityRatio=" + lt.getSimilarityRatio(str, target, true));
    }
}
src/main/java/com/yeshi/buwan/util/SpringContext.java
@@ -11,10 +11,7 @@
import com.yeshi.buwan.service.imp.JobThreadExecutorServiceImpl;
import com.yeshi.buwan.service.imp.ResourceVideoService;
import com.yeshi.buwan.service.imp.VideoInfoService;
import com.yeshi.buwan.service.inter.juhe.FunTV2Service;
import com.yeshi.buwan.service.inter.juhe.Iqiyi2Service;
import com.yeshi.buwan.service.inter.juhe.PPTVService;
import com.yeshi.buwan.service.inter.juhe.YouKuService;
import com.yeshi.buwan.service.inter.juhe.*;
import com.yeshi.buwan.service.manager.SolrAlbumVideoDataManager;
import com.yeshi.buwan.service.manager.SolrInternetSearchVideoDataManager;
import com.yeshi.buwan.util.factory.InternetSearchVideoFactory;
@@ -85,6 +82,7 @@
            doDeleteVideoResource();
            doUpdateVideoExtraInfo();
        }
        doInternetSearchVideoUpdateJob();
    }
    private void doSolrJob() {
@@ -124,7 +122,7 @@
    @Resource
    private YouKuService youKuService;
    private InternetSearchVideoService internetSearchVideoService;
    @Resource
    private SolrInternetSearchVideoDataManager solrInternetSearchVideoDataManager;
@@ -138,30 +136,12 @@
                    if (solrMsgList != null)
                        for (InternetSearchVideoMQMsg solrVideo : solrMsgList) {
                            try {
                                switch (solrVideo.getResourceId()) {
                                    //优酷
                                    case 20:
                                        YouKuShowDetail detail = youKuService.getShowDetail(solrVideo.getId());
                                        if (detail == null) {//被删除
                                            solrInternetSearchVideoDataManager.deleteById(detail.getId());
                                        } else {//更新
                                            InternetSearchVideo video = InternetSearchVideoFactory.create(detail);
                                InternetSearchVideo video = internetSearchVideoService.selectByPrimaryKey(solrVideo.getId());
                                if (video != null)
                                            solrInternetSearchVideoDataManager.saveOrUpdate(video);
                                        }
                                        break;
                                    //腾讯
                                    case 17:
                                        break;
                                }
                                CMQManager.getInstance().deleteSolrMsg(solrVideo.getHandler());
                                else
                                    solrInternetSearchVideoDataManager.deleteById(video.getId());
                                CMQManager.getInstance().deleteInternetSearchVideoUpdateMsg(solrVideo.getHandler());
                            } catch (Exception e) {
                                logger.error("更新全网搜搜索引擎出错", e);
                            }
src/main/java/com/yeshi/buwan/util/factory/InternetSearchVideoFactory.java
@@ -118,7 +118,7 @@
        } else
            video.setTag(info.getEpisode_updated());
        video.setUpdateTime(new Date());
        video.setVideoCount(info.getVip_ids().size());
        video.setVideoCount(info.getVideoList().size());
        video.setYear(info.getYear());
        video.setId(InternetSearchVideo.createId(video.getName(), video.getRootType(), video.getYear()));
        return video;
src/main/java/com/yeshi/buwan/util/mq/CMQManager.java
@@ -242,7 +242,7 @@
     */
    public void addInternetSearchVideoUpdateMsg(InternetSearchVideoMQMsg msg) {
        cmqUtil.sendMsg(QUEUENAME_VIDEO_RESOURCE_DELETE, new Gson().toJson(msg));
        cmqUtil.sendMsg(QUEUENAME_UPDATE_INTERNET_SEARCH, new Gson().toJson(msg));
    }
    public List<InternetSearchVideoMQMsg> consumeInternetSearchVideoUpdateMsg(int count) {
src/main/java/com/yeshi/buwan/util/video/VideoDetailUtil.java
@@ -16,11 +16,9 @@
import com.yeshi.buwan.service.imp.juhe.FunTVService;
import com.yeshi.buwan.service.imp.juhe.IqiyiService;
import com.yeshi.buwan.service.imp.juhe.SoHuService;
import com.yeshi.buwan.service.inter.juhe.FunTV2Service;
import com.yeshi.buwan.service.inter.juhe.Iqiyi2Service;
import com.yeshi.buwan.service.inter.juhe.MogoTVService;
import com.yeshi.buwan.service.inter.juhe.YouKuService;
import com.yeshi.buwan.service.inter.juhe.*;
import com.yeshi.buwan.sohu.SoHuUtil;
import com.yeshi.buwan.tencent.TencentVideoUtil;
import com.yeshi.buwan.util.StringUtil;
import com.yeshi.buwan.util.log.VideoLogFactory;
import com.yeshi.buwan.vo.AcceptData;
@@ -79,6 +77,12 @@
    @Resource
    private MogoTVService mogoTVService;
    @Resource
    private TencentVideoService tencentVideoService;
    @Resource
    private TencentVideoUtil tencentVideoUtil;
    @SuppressWarnings("unchecked")
//    @Cacheable(value = "homeCache", key = "'getVideoInfo'+'-'+#videoid+'-'+#resourceId+'-'+#cacheMD5")
@@ -218,6 +222,8 @@
                return youKuService.getVideoDetailList(videoid, page, pageSize);
            case MogoTVUtil.RESOURCE_ID:
                return mogoTVService.getVideoDetailList(videoid, page, pageSize);
            case TencentVideoUtil.RESOURCE_ID:
                return tencentVideoService.getVideoDetailList(videoid, page, pageSize);
            default:
                return null;
        }
@@ -284,6 +290,10 @@
                return videoInfoService.getPlayUrl(detailSystemId, id, type, resourceid, videoid);
            case YouKuUtil.RESOURCE_ID:
                return youKuUtil.getPlayUrl(detailSystemId, id, type, resourceid, videoid);
            case MogoTVUtil.RESOURCE_ID:
                return mogoTVUtil.getPlayUrl(detailSystemId, id, type, resourceid, videoid);
            case TencentVideoUtil.RESOURCE_ID:
                return tencentVideoUtil.getPlayUrl(detailSystemId, id, type, resourceid, videoid);
            default:
                return null;
        }
src/test/java/com/hxh/spring/test/DES.java
@@ -5,6 +5,6 @@
public class DES {
    @org.junit.Test
    public void test1() {
        System.out.println(DESUtil.decode("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"));
        System.out.println(DESUtil.decode("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"));
    }
}
src/test/java/com/hxh/spring/test/GeneralTest.java
@@ -4,7 +4,7 @@
import com.yeshi.buwan.dao.video.VideoResourceVersionMapDao;
import com.yeshi.buwan.domain.video.VideoResourceVersionMap;
import com.yeshi.buwan.service.inter.video.VideoResourceVersionMapService;
import com.yeshi.buwan.youku.entity.YouKuSearchVideoMap;
import com.yeshi.buwan.tencent.entity.TencentSearchVideoMap;
import org.yeshi.utils.generater.SpringComponentGenerater;
import org.yeshi.utils.generater.entity.MongoDBDaoData;
import org.yeshi.utils.generater.entity.ServiceData;
@@ -14,7 +14,7 @@
    @org.junit.Test
    public void createDao() {
        try {
            SpringComponentGenerater.createMongoDao(new MongoDBDaoData.Builder().setBaseDaoClass(MongodbBaseDao.class).setDaoPackageName("com.yeshi.buwan.dao.juhe.youku").setEntityClass(YouKuSearchVideoMap.class).create(), "D:\\workspace\\BuWan\\src\\main\\java\\com\\yeshi\\buwan\\dao\\juhe\\youku\\");
            SpringComponentGenerater.createMongoDao(new MongoDBDaoData.Builder().setBaseDaoClass(MongodbBaseDao.class).setDaoPackageName("com.yeshi.buwan.dao.juhe.youku").setEntityClass(TencentSearchVideoMap.class).create(), "D:\\workspace\\BuWan\\src\\main\\java\\com\\yeshi\\buwan\\dao\\juhe\\tencent\\");
        } catch (Exception e) {
            e.printStackTrace();
        }
src/test/java/com/hxh/spring/test/SolrTest.java
@@ -161,7 +161,7 @@
    @Test
    public void addInternet() {
        InternetSearchVideo list = internetSearchVideoService.selectByPrimaryKey("59fafccefd20505b0aade6d9ba0e8ed1"); //listAll(1, 10);
        InternetSearchVideo list = internetSearchVideoService.selectByPrimaryKey("8a2332ccbabb5eb7076f690365db692a"); //listAll(1, 10);
        solrInternetSearchVideoDataManager.saveOrUpdate(list);
    }
src/test/java/com/hxh/spring/test/video/MogoTest.java
New file
@@ -0,0 +1,61 @@
package com.hxh.spring.test.video;
import com.yeshi.buwan.domain.video.InternetSearchVideo;
import com.yeshi.buwan.job.video.MogoTVVideoUpdate;
import com.yeshi.buwan.job.video.YouKuVideoUpdate;
import com.yeshi.buwan.mogotv.entity.MogoTVClipInfo;
import com.yeshi.buwan.service.inter.juhe.InternetSearchVideoService;
import com.yeshi.buwan.service.inter.juhe.MogoTVService;
import com.yeshi.buwan.service.inter.juhe.YouKuService;
import com.yeshi.buwan.util.factory.InternetSearchVideoFactory;
import com.yeshi.buwan.youku.YouKuApiUtil;
import com.yeshi.buwan.youku.entity.YouKuShowDetail;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import javax.annotation.Resource;
import java.util.List;
//
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
@ContextConfiguration(locations = {"classpath:spring.xml"})
@WebAppConfiguration
public class MogoTest {
    @Resource
    private MogoTVService mogoTVService;
    @Resource
    private MogoTVVideoUpdate mogoTVVideoUpdate;
    @Resource
    private InternetSearchVideoService internetSearchVideoService;
    @Test
    public void test2() {
        try {
            mogoTVVideoUpdate.updateLatestVideo("综艺");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Test
    public void addToSearch() {
        List<MogoTVClipInfo> list = mogoTVService.list("电视剧", 1, 1000);
        for (MogoTVClipInfo info : list) {
            try {
                mogoTVService.addToInternetSearch(info);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
src/test/java/com/hxh/spring/test/video/TencentTest.java
New file
@@ -0,0 +1,59 @@
package com.hxh.spring.test.video;
import com.yeshi.buwan.job.video.MogoTVVideoUpdate;
import com.yeshi.buwan.job.video.TencentVideoUpdate;
import com.yeshi.buwan.mogotv.entity.MogoTVClipInfo;
import com.yeshi.buwan.service.inter.juhe.InternetSearchVideoService;
import com.yeshi.buwan.service.inter.juhe.MogoTVService;
import com.yeshi.buwan.service.inter.juhe.TencentVideoService;
import com.yeshi.buwan.tencent.entity.TencentCoverInfo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import javax.annotation.Resource;
import java.util.List;
//
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
@ContextConfiguration(locations = {"classpath:spring.xml"})
@WebAppConfiguration
public class TencentTest {
    @Resource
    private TencentVideoService tencentVideoService;
    @Resource
    private TencentVideoUpdate tencentVideoUpdate;
    @Resource
    private InternetSearchVideoService internetSearchVideoService;
    @Test
    public void test2() {
        try {
            tencentVideoUpdate.updateLatestVideo("动漫");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Test
    public void addToSearch() {
        List<TencentCoverInfo> list = tencentVideoService.list("动漫", 1, 10);
        for (TencentCoverInfo info : list) {
            try {
                tencentVideoService.addToInternetSearch(info);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
src/test/java/com/hxh/spring/test/video/YouKuTest.java
@@ -44,7 +44,7 @@
    @Test
    public void test2() {
        List<YouKuShowDetail> details = youKuService.list("电视剧", 2, 700);
        List<YouKuShowDetail> details = youKuService.list("电影", 1, 2000);
        for (YouKuShowDetail detail : details) {
            try {
                InternetSearchVideo video = InternetSearchVideoFactory.create(detail);