综合应用-《美食趋势》
前言
最近事情比较多,一直没找出时间继续写东西,抱歉。
后面准备综合前面的东西写一个小应用。通过图片抓取获取美食资源,然后美食信息进行展示和数据分析。
需求功能整理
小吕最近胃口不好,吃啥啥不香,日益消瘦。小貂看在眼里,疼在心里,甚至怀疑是不是自己的饭已经被吃够了,甚是伤心。一天她把自己的担忧跟小诸葛说了,小诸葛轻轻摇扇说,这个好办,我们蜀氏集团出个菜谱,只要按照这个菜谱高的做,保准你家小吕吃的开心。
小诸葛回到公司后,把情况给大家说,理出一个大概的思路:小吕不爱吃饭-->小貂做的不好吃-->小貂不知道做啥好吃-->蜀氏集团能否提供美食参考?美食参考需要怎么做才能达到目的?大家讨论后,一致同意先出一个雏形,讨论雏形结果如下
数据设计
数据结构
功能实现
1. 定时抓取数据
小赵接手定时任务计划,他决定采用spring-task,就像把大象放到冰箱一样简单。引用依赖-->配置spring task--> 定时注解。
a. 引用依赖spring-webmvc已经把task的依赖包含了。只引用下一下个即可
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
...
b. 配置spring,注意xml一定要声明task
<beans xmlns="http://www.springframework.org/schema/beans"
...
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
...
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-4.0.xsd">
...
<context:component-scan base-package="org.sl.food">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
...
<task:annotation-driven executor="executor" scheduler="scheduler" proxy-target-class="true" />
<task:executor id="executor" pool-size="5" />
<task:scheduler id="scheduler" pool-size="10" />
...
</beans>
c. 定时注解,定时表达式采用cron表达式
package org.sl.food.task;
...
@Component
public class FoodCrawlTask {
@Scheduled(cron = "0/5 * * * * ?")
public void foodCrawl() {
...
}
...
}
现在乍听特别高大上的定时任务功能就这么完成了,只要定时去获取数据就行啦,剩下的交给别人吧。
2. 解析数据入库
小张表面看着满脸横肉,胡子比头发还长。怎么看都感觉是个大大咧咧,易燃易爆品。正是这人,非想做需要细心,耐心的活;想改变人们对他的看法。怎么做呢,怎么把浏览器看到的数据转换成固定结构的数据呢?首先需要有数据,这个小赵已经完成;其次需要解析数据,jsoup,专门解析html数据,这个算是解决;剩下的对应数据了,id,name,菜谱地址,图片……这么多,关键小赵给的数据,还不能完全满足,需要额外的数据,这可咋整,但是小张不能急!!!怎么能快速的取到我想要的值呢?浏览器可以用jQuery,什么?jsoup支持jQuery语法?!。
...
Elements el = doc.select("#listtyle1_list .listtyle1 a.big");
logger.debug("{}", el);
List<FoodEntity> foodList = new LinkedList<>();
for (Element e : el) {
FoodEntity food = new FoodEntity();
food.setUpdateTime(new Date());
food.setName(e.attr("title"));
food.setDetailsSite(e.attr("href"));
food.setPicture(e.select("img").attr("src"));
String tmp = e.select(".c2 .li2").text();
String[] strArr = tmp.split("/");
food.setTasteType(strArr[1].trim());
Matcher m = idPattern.matcher(food.getDetailsSite());
if (m.find()) {
tmp = m.group();
food.setId(tmp.substring(1, tmp.length() - 5));
} else {
food.setId(new Date().toString());
}
getMore(food);
foodList.add(food);
}
...
so easy,想要啥,就拿啥。嗯,还有个点赞数没法拿,不怕,还是同样的套路,照着小赵拿数据的方法来一遍。嘿!看我要变形了!呔!嗯?没有值!!明明浏览器里有,凭啥我就没有?这可咋整,但是小张不能急!!!咦,浏览器页面访问后,又走了一个ajax拿数据,好家伙,被我逮着了,我请求下数据不就行了呗。啊?请求回复403!!又没有数据!!这可咋整,但是小张不能急!!!浏览器能整的,我也能!照着浏览器的请求写呗,少header,我加header。
HttpGet get = new HttpGet(s);
get.setHeader("Accept-Encoding", "gzip, deflate, br");
get.setHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
get.setHeader("Cache-Control", "no-cache");
get.setHeader("Connection", "keep-alive");
get.setHeader("Host", "xxxxxxx");
get.setHeader("Pragma", "no-cache");
get.setHeader("Referer", "xxxxxxxxxx");
get.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36");
嘿,来了。小样,还有我小张搞不了的?这么费神的事我也能搞!以后这样的事,就不要找我了!!
3. 比对分析功能
to be continue!!!
github地址
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。