|
|
@@ -1,25 +1,34 @@
|
|
|
package com.YuyeTech.HeartRate.game.food.service;
|
|
|
|
|
|
-import com.YuyeTech.HeartRate.common.service.*;
|
|
|
-import com.YuyeTech.HeartRate.enums.FoodEnum;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import com.YuyeTech.HeartRate.common.service.CommonServiceImpl;
|
|
|
import com.YuyeTech.HeartRate.game.food.pojo.Food;
|
|
|
+import com.YuyeTech.HeartRate.game.food.repository.FoodRepository;
|
|
|
import com.YuyeTech.HeartRate.game.food.vo.FoodSimpleVo;
|
|
|
import com.YuyeTech.HeartRate.game.food.vo.FoodVo;
|
|
|
-import com.YuyeTech.HeartRate.game.food.repository.FoodRepository;
|
|
|
+import com.YuyeTech.HeartRate.utils.CopyUtil;
|
|
|
+import com.YuyeTech.HeartRate.utils.RedisSettingMap;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.jsoup.Jsoup;
|
|
|
import org.jsoup.nodes.Document;
|
|
|
import org.jsoup.nodes.Element;
|
|
|
import org.jsoup.select.Elements;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
+import org.springframework.data.redis.core.ZSetOperations;
|
|
|
+import org.springframework.http.*;
|
|
|
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.MultiValueMap;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
+import org.springframework.web.util.UriComponentsBuilder;
|
|
|
|
|
|
import javax.persistence.EntityManager;
|
|
|
import javax.persistence.PersistenceContext;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.URLEncoder;
|
|
|
+import java.util.*;
|
|
|
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@@ -33,88 +42,129 @@ public class FoodServiceImpl extends CommonServiceImpl<FoodVo, Food, Integer> im
|
|
|
@Autowired
|
|
|
private FoodRepository foodRepository;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private RedisSettingMap redisSettingMap;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private StringRedisTemplate stringRedisTemplate;
|
|
|
+
|
|
|
@Override
|
|
|
public Food addFood(Food food) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public List<FoodSimpleVo> getListFromUrl(String url) {
|
|
|
+ public FoodSimpleVo getByFoodTitle(String title) {
|
|
|
+ Food food = foodRepository.findByTitle(title).orElse(null);
|
|
|
+ return food == null?null: CopyUtil.copy(food,FoodSimpleVo.class);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<FoodSimpleVo> getListFromUrl(String url,String refer) {
|
|
|
|
|
|
RestTemplate restTemplate = new RestTemplate();
|
|
|
String response = restTemplate.getForObject(domain+url, String.class);
|
|
|
Document doc = Jsoup.parse(response);
|
|
|
+// log.info(String.valueOf(doc));
|
|
|
Element postList = doc.getElementById("main");
|
|
|
Elements postItems = postList.getElementsByClass("item clearfix");
|
|
|
- log.info("postList size={}", postItems.size());
|
|
|
+// log.info("postList size={}", postItems.size());
|
|
|
List<FoodSimpleVo> foodVoList = new ArrayList<>();
|
|
|
for (Element postItem : postItems) {
|
|
|
//像jquery选择器一样,获取文章标题元素
|
|
|
Elements titleEle = postItem.select(".text-box a");
|
|
|
String detailUrl = domain+titleEle.attr("href");
|
|
|
- log.info("标题:" + titleEle.attr("title"));;
|
|
|
- log.info("详情地址:" + detailUrl);
|
|
|
+// log.info("标题:" + titleEle.attr("title"));;
|
|
|
+// log.info("详情地址:" + detailUrl);
|
|
|
String src = postItem.select("img").attr("src");
|
|
|
- log.info("缩略图:" + src);
|
|
|
+// log.info("缩略图:" + src);
|
|
|
Elements describe = postItem.select(".text-box p");
|
|
|
- log.info("描述:" + describe.text());
|
|
|
- log.info("*********************************");
|
|
|
+// log.info("描述:" + describe.text());
|
|
|
+// log.info("*********************************");
|
|
|
String[] hrefs = titleEle.attr("href").split("/");
|
|
|
FoodSimpleVo foodVo = new FoodSimpleVo();
|
|
|
foodVo.setTitle(titleEle.attr("title"));
|
|
|
foodVo.setType(hrefs[1]);
|
|
|
foodVo.setName(hrefs[2]);
|
|
|
- foodVo.setDescribe(describe.text());
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- String detailUrlResponse = restTemplate.getForObject(detailUrl, String.class);
|
|
|
- Document detailDoc = Jsoup.parse(detailUrlResponse);
|
|
|
-
|
|
|
- Element detailMain = detailDoc.getElementById("main");
|
|
|
- Elements detailItems = detailMain.select(".basic-infor li");
|
|
|
+ foodVo.setIconUrl(src);
|
|
|
+ foodVo.setFDescribe(describe.text());
|
|
|
+ foodVo.setCreateTime(DateUtil.date());
|
|
|
+ foodVo.setUpdateTime(DateUtil.date());
|
|
|
+
|
|
|
+ String _describe = describe.text();
|
|
|
+ Integer _dIndex = _describe.indexOf("大卡");
|
|
|
+ String _calorieText = _describe.substring(0,_dIndex);
|
|
|
+ String _calorieStr = _calorieText.replaceAll("\\s*","").replaceAll("[^(0-9)]","");
|
|
|
+ Double _calorie = Double.parseDouble(_calorieStr);
|
|
|
+// log.info("_calorie:"+_calorie);
|
|
|
+ foodVo.setKcal(_calorie);
|
|
|
+ foodVo.setCarbohydrate(0d);
|
|
|
+ foodVo.setFat(0d);
|
|
|
+ foodVo.setProtein(0d);
|
|
|
+ foodVo.setCellulose(0d);
|
|
|
+ foodVo.setFGroup(0);
|
|
|
+
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.add("referer", domain + refer);
|
|
|
+ HttpEntity request = new HttpEntity(null, headers);
|
|
|
+// MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
|
|
|
+// new MappingJackson2HttpMessageConverter();
|
|
|
+// mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_HTML));
|
|
|
+// restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
|
|
|
+ ResponseEntity<String> detailUrlResponse = restTemplate.exchange(detailUrl, HttpMethod.GET, request, String.class);
|
|
|
+ Document detailDoc = Jsoup.parse(detailUrlResponse.getBody());
|
|
|
+// log.info(String.valueOf(detailDoc));
|
|
|
+ Element detailMain = detailDoc.getElementById("food_cover");
|
|
|
String iconUrl = detailMain.select("img").attr("src");
|
|
|
foodVo.setIconUrl(iconUrl);
|
|
|
- for (Element _item : detailItems) {
|
|
|
- //像jquery选择器一样,获取文章标题元素
|
|
|
- //Elements titleEle = _item.select(".basic-infor li");
|
|
|
- log.info("b1:" + _item.text().split(":")[0]);
|
|
|
- log.info("b2:" + _item.text().split(":")[1]);
|
|
|
- Elements count = _item.select(".stress");
|
|
|
- log.info("count:" + count.text() + "K");
|
|
|
- log.info("*********************************");
|
|
|
- }
|
|
|
- Elements infoItems = detailMain.select(".nutr-tag dl").not(".header");
|
|
|
- Elements ddItems = infoItems.select("dd");
|
|
|
- for (Element _ddItem : ddItems) {
|
|
|
- Elements _name= _ddItem.select(".dt");
|
|
|
- Elements _num= _ddItem.select(".dd");
|
|
|
- log.info(_name.text() +" = "+_num.text());
|
|
|
- double _value = 0;
|
|
|
- try {
|
|
|
- _value = Double.parseDouble(_num.text());
|
|
|
- } catch (Exception e) {
|
|
|
- _value = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if(_name.text().indexOf("热量")>-1){
|
|
|
- foodVo.setKcal(_value);
|
|
|
-
|
|
|
- }else if(_name.text().indexOf("碳水化合物")>-1){
|
|
|
- foodVo.setCarbohydrate(_value);
|
|
|
- }else if(_name.text().indexOf("脂肪")>-1){
|
|
|
- foodVo.setFat(_value);
|
|
|
- }else if(_name.text().indexOf("蛋白质")>-1){
|
|
|
- foodVo.setProtein(_value);
|
|
|
- }else if(_name.text().indexOf("纤维素")>-1){
|
|
|
- foodVo.setCellulose(_value);
|
|
|
- }
|
|
|
- }
|
|
|
- log.info("*********************************");
|
|
|
+// Element detailMain = detailDoc.getElementById("main");
|
|
|
+// Elements detailItems = detailMain.select(".basic-infor li");
|
|
|
+// String iconUrl = detailMain.select("img").attr("src");
|
|
|
+// foodVo.setIconUrl(iconUrl);
|
|
|
+// for (Element _item : detailItems) {
|
|
|
+// //像jquery选择器一样,获取文章标题元素
|
|
|
+// //Elements titleEle = _item.select(".basic-infor li");
|
|
|
+// log.info("b1:" + _item.text().split(":")[0]);
|
|
|
+// log.info("b2:" + _item.text().split(":")[1]);
|
|
|
+// Elements count = _item.select(".stress");
|
|
|
+// log.info("count:" + count.text() + "K");
|
|
|
+// log.info("*********************************");
|
|
|
+// }
|
|
|
+// Elements infoItems = detailMain.select(".nutr-tag dl").not(".header");
|
|
|
+// Elements ddItems = infoItems.select("dd");
|
|
|
+// for (Element _ddItem : ddItems) {
|
|
|
+// Elements _name= _ddItem.select(".dt");
|
|
|
+// Elements _num= _ddItem.select(".dd");
|
|
|
+// log.info(_name.text() +" = "+_num.text());
|
|
|
+// double _value = 0;
|
|
|
+// try {
|
|
|
+// _value = Double.parseDouble(_num.text());
|
|
|
+// } catch (Exception e) {
|
|
|
+// _value = 0;
|
|
|
+// }
|
|
|
+//
|
|
|
+// if(_name.text().indexOf("热量")>-1){
|
|
|
+// foodVo.setKcal(_value);
|
|
|
+//
|
|
|
+// }else if(_name.text().indexOf("碳水化合物")>-1){
|
|
|
+// foodVo.setCarbohydrate(_value);
|
|
|
+// }else if(_name.text().indexOf("脂肪")>-1){
|
|
|
+// foodVo.setFat(_value);
|
|
|
+// }else if(_name.text().indexOf("蛋白质")>-1){
|
|
|
+// foodVo.setProtein(_value);
|
|
|
+// }else if(_name.text().indexOf("纤维素")>-1){
|
|
|
+// foodVo.setCellulose(_value);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// log.info("*********************************");
|
|
|
|
|
|
foodVoList.add(foodVo);
|
|
|
}
|
|
|
-
|
|
|
+ Collections.sort(foodVoList,(a,b)->{
|
|
|
+ return (int) (a.getKcal() - b.getKcal());
|
|
|
+ });
|
|
|
return foodVoList;
|
|
|
}
|
|
|
|
|
|
@@ -123,4 +173,35 @@ public class FoodServiceImpl extends CommonServiceImpl<FoodVo, Food, Integer> im
|
|
|
public List<Food> getListByIds(List<Integer> ids) {
|
|
|
return foodRepository.findAllByIdIn(ids);
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void addKeywordToRedis(String keyword) {
|
|
|
+ //直接记录一个keyword 到缓存,用于定时任务爬数据
|
|
|
+ String keywordPrefix = redisSettingMap.getKeywordPrefix();
|
|
|
+ ZSetOperations zSetOperations = stringRedisTemplate.opsForZSet();
|
|
|
+ //如果不存在,直接添加,如果存在,+1
|
|
|
+ zSetOperations.incrementScore(keywordPrefix, keyword, 1.0);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getKeywordsFromRedis() {
|
|
|
+ //直接记录一个keyword 到缓存,用于定时任务爬数据
|
|
|
+ String keywordPrefix = redisSettingMap.getKeywordPrefix();
|
|
|
+ ZSetOperations zSetOperations = stringRedisTemplate.opsForZSet();
|
|
|
+ //获取搜索最多的前十个数据
|
|
|
+ Set<ZSetOperations.TypedTuple<Object>> rankTen = zSetOperations.reverseRangeWithScores(keywordPrefix, 0, 10);
|
|
|
+ Iterator<ZSetOperations.TypedTuple<Object>> iterator = rankTen.iterator();
|
|
|
+ List<String> keywordList = new ArrayList<>();
|
|
|
+ List<Double> scoreList = new ArrayList<>();
|
|
|
+ while (iterator.hasNext()) {
|
|
|
+ ZSetOperations.TypedTuple<Object> typedTuple = iterator.next();
|
|
|
+ keywordList.add(typedTuple.getValue().toString());
|
|
|
+ scoreList.add(typedTuple.getScore());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|