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]; } VideoInfo info = null; if (Integer.parseInt(resourceId) == YouKuUtil.RESOURCE_ID) { VideoInfo info = null; try { info = youKuUtil.getVideoInfo(internetSearchVideo); } catch (Exception e) { @@ -377,11 +384,28 @@ return; } JSONArray array = new JSONArray(); JSONObject obj = new JSONObject(); out.print(JsonUtil.loadTrueJson(StringUtil.outPutResultJson(Utils.convertVideo(info)), array.toString(), obj.toString())); } 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); localList.add(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 void save(TencentCoverInfo detail) throws Exception; public TencentCoverInfo getConverDetail(String id); public TencentCoverInfo getCoverDetail(String coverId); public long count(String type); public TencentCoverInfo getSimpleCoverDetail(String coverId); public List<TencentCoverInfo> list(String type, int page, int pageSize); 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 { query = new SimpleQuery(new Criteria("nameStr").startsWith(filter.getKey()).or("mainactor").expression("\"" + filter.getKey() + "\"")); 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; } public VideoInfo getVideoInfo(InternetSearchVideo internetSearchVideo) throws Exception { TencentSearchVideoMap map = tencentVideoService.selectMapByVideoId(internetSearchVideo.getId()); if (map == null) { throw new Exception("视频源不存在"); } 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(); 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); } info.setResourceList(resourceList); info.setShowType(YouKuUtil.getShowType(internetSearchVideo)); info.setScore(new BigDecimal(showDetail.getScore().getScore()).setScale(1).toString()); 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<>(); //获取分类详情 info.setVideoType(videoTypeService.getVideoType(info.getVideoType().getId())); info.setCommentCount(0); info.setVideocount((int) (Math.random() * 1000)); 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; 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(); } } } catch (IOException 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; } 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(); public static int getShowType(InternetSearchVideo video) { if (video == null) return 2; // } 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)); 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; } } 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); solrInternetSearchVideoDataManager.saveOrUpdate(video); } break; //腾讯 case 17: break; } CMQManager.getInstance().deleteSolrMsg(solrVideo.getHandler()); InternetSearchVideo video = internetSearchVideoService.selectByPrimaryKey(solrVideo.getId()); if (video != null) solrInternetSearchVideoDataManager.saveOrUpdate(video); 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);