作者 钟来

水产舆情采集

package com.ruoyi.system.domain.fish;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.PublicSQLConfig;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import com.ruoyi.common.tool.BaseEntity;
/**
* 水产舆情对象 fish_aquatic_public_opinion
*
* @author zhonglai
* @date 2025-07-03
*/
@ApiModel("水产舆情")
public class FishAquaticPublicOpinion extends BaseEntity
{
@PublicSQLConfig(isSelect=false)
private static final long serialVersionUID = 1L;
/** 主键 */
private Integer id;
/** 发布时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value="发布时间")
private Date releaseTime;
/** 标题 */
@ApiModelProperty(value="标题")
private String title;
/** 详情地址 */
@ApiModelProperty(value="详情地址")
private String infoUrl;
/** 文件地址 */
@ApiModelProperty(value="文件地址")
private String filePath;
public void setId(Integer id)
{
this.id = id;
}
public Integer getId()
{
return id;
}
public void setReleaseTime(Date releaseTime)
{
this.releaseTime = releaseTime;
}
public Date getReleaseTime()
{
return releaseTime;
}
public void setTitle(String title)
{
this.title = title;
}
public String getTitle()
{
return title;
}
public void setInfoUrl(String infoUrl)
{
this.infoUrl = infoUrl;
}
public String getInfoUrl()
{
return infoUrl;
}
public void setFilePath(String filePath)
{
this.filePath = filePath;
}
public String getFilePath()
{
return filePath;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("releaseTime", getReleaseTime())
.append("title", getTitle())
.append("infoUrl", getInfoUrl())
.append("createTime", getCreateTime())
.append("filePath", getFilePath())
.toString();
}
}
... ...
... ... @@ -46,6 +46,10 @@
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
... ...
package com.ruoyi.quartz.task;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.tool.SysLogininforType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.quartz.task.aquatic.AquaticPublicOpinionService;
import com.zhonglai.luhui.dao.service.PublicService;
import com.zhonglai.luhui.sys.manager.AsyncManager;
import com.zhonglai.luhui.sys.manager.factory.AsyncFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
/**
* 水产舆情
*/
@Component("aquaticPublicOpinionTask")
public class AquaticPublicOpinionTask {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private List<AquaticPublicOpinionService> aquaticPublicOpinionServices;
@Autowired
protected PublicService publicService;
public void run(String day)
{
for (AquaticPublicOpinionService service : aquaticPublicOpinionServices) {
AsyncManager.me().execute(new TimerTask() {
@Override
public void run() {
try {
logger.info("异步执行服务:{},参数:{}", service.getClass().getSimpleName(), day);
service.run(day);
logger.info("服务执行完成:{}", service.getClass().getSimpleName());
} catch (Exception e) {
logger.error("服务 {} 执行出错", service.getClass().getSimpleName(), e);
}
}
});
}
}
public void pushPublicOpinion()
{
List<Map<String,Object>> lsit = publicService.getObjectListBySQL("SELECT * FROM `fish_aquatic_public_opinion` WHERE release_time='"+DateUtils.getDate()+" 00:00:00'");
if (null != lsit && lsit.size()!=0)
{
for (Map<String,Object> map:lsit)
{
StringBuffer content = new StringBuffer();
content.append("【水产新闻】");
content.append("\n");
content.append(map.get("title"));
content.append("\n");
content.append("https://lh.admin.yu2le.com/api/profile/aquaticPublicOpinion/"+map.get("file_path"));
content.append("\n");
content.append("来源:"+map.get("info_url"));
content.append("\n");
JSONObject jsonObject = new JSONObject();
jsonObject.put("msgtype","text");
JSONObject text = new JSONObject();
text.put("content",content);
text.put("mentioned_mobile_list",new String[]{"@all"});
jsonObject.put("text",text);
HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=6d6b4790-d20f-4692-bc4a-e8ceb1e8cfda",jsonObject.toJSONString());
}
}
}
}
... ...
package com.ruoyi.quartz.task.aquatic;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.fish.FishAquaticPublicOpinion;
import com.zhonglai.luhui.dao.service.PublicService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
public abstract class AquaticPublicOpinionBase implements AquaticPublicOpinionService{
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
protected PublicService publicService;
public void updateSaveInfo(String text,Integer id)
{
if(StringUtils.isNotEmpty(text))
{
Path path = Paths.get("uploadPath/aquaticPublicOpinion/"+id+".txt");
String filepath = saveFile(text, path);
if(StringUtils.isNotEmpty(filepath))
{
FishAquaticPublicOpinion upaquaticPublicOpinion = new FishAquaticPublicOpinion();
upaquaticPublicOpinion.setId(id);
upaquaticPublicOpinion.setFilePath(filepath);
publicService.updateObject(upaquaticPublicOpinion,"id");
}
}
}
public String saveFile(String text,Path path) {
File file = path.getParent().toFile();
if(!file.exists())
{
file.mkdirs();
}
System.out.println(path.toAbsolutePath());
try {
return Files.write(path, text.toString().getBytes(StandardCharsets.UTF_8)).getFileName().toString();
} catch (IOException e) {
logger.error("文件"+path+"保存失败",e);
}
return null;
}
protected void insertFishAquaticPublicOpinions(List<FishAquaticPublicOpinion> fishAquaticPublicOpinions)
{
if(null != fishAquaticPublicOpinions && fishAquaticPublicOpinions.size() !=0)
{
publicService.insertAll( fishAquaticPublicOpinions);
}
}
abstract List<FishAquaticPublicOpinion> collect(String day);
abstract String getInfo(String info_url);
@Override
public void run(String day) {
if(StringUtils.isEmpty(day))
{
day = DateUtils.getDate();
}
List<FishAquaticPublicOpinion> list = collect(day);
if (null != list && list.size() != 0)
{
//持久
insertFishAquaticPublicOpinions(list);
//保存文件
for (FishAquaticPublicOpinion aquaticPublicOpinion:list)
{
Map<String,Object> map = publicService.getObjectList(aquaticPublicOpinion,"id,info_url",null,null,0,0).get(0);
String text = getInfo((String) map.get("info_url"));
updateSaveInfo(text, (Integer) map.get("id"));
}
}
}
protected Document createDocument(String url) throws IOException {
return Jsoup.connect(url).timeout(10000).get();
}
}
... ...
package com.ruoyi.quartz.task.aquatic;
public interface AquaticPublicOpinionService {
public void run(String day);
}
... ...
package com.ruoyi.quartz.task.aquatic;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.fish.FishAquaticPublicOpinion;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class WwwCafsAcCn extends AquaticPublicOpinionBase{
@Override
List<FishAquaticPublicOpinion> collect(String day) {
String[] urls = {"https://www.cafs.ac.cn/kxyj/kyjz.htm","https://www.cafs.ac.cn/gjhz/gjhz.htm","https://www.cafs.ac.cn/djwh/djdt.htm","https://www.cafs.ac.cn/xwxx/tpxw.htm"};
List<FishAquaticPublicOpinion> list = new ArrayList<>();
for (String domain :urls)
{
try {
// 解析页面
Document doc = createDocument(domain);
// 选中 div.m_list 下的 ul 中的所有 li
Elements liElements = doc.select("div.list_con ul li");
// 打印所有 li 的 HTML
for (Element li : liElements) {
Elements a = li.select("a");
String url = a.attr("abs:href");
String title = a.attr("title");
String time = li.select("span").text();
if(StringUtils.isNotEmpty(day) && DateUtils.parseDate(time, "yyyy年MM月dd日").equals(DateUtils.parseDate(day,DateUtils.YYYY_MM_DD)))
{
FishAquaticPublicOpinion aquaticPublicOpinion = new FishAquaticPublicOpinion();
aquaticPublicOpinion.setTitle(title);
aquaticPublicOpinion.setInfoUrl(url);
aquaticPublicOpinion.setReleaseTime(DateUtils.parseDate(time,"yyyy年MM月dd日"));
aquaticPublicOpinion.setCreateTime(new Date());
list.add(aquaticPublicOpinion);
}else{
return list;
}
}
} catch (Exception e) {
logger.error("数据解析错误:"+domain,e);
}
}
return list;
}
@Override
String getInfo(String info_url) {
try {
// 访问网页
Document doc = createDocument(info_url);
// 查找正文区域,常见class为 TRS_Editor 或 article
Element content = doc.selectFirst("div.v_news_content");
if (content != null) {
StringBuilder text = new StringBuilder();
// 遍历段落,保留换行
for (Element p : content.select("p")) {
String line = p.text().trim();
if (!line.isEmpty()) {
text.append(line).append("\n\n");
}
}
return text.toString();
} else {
logger.error("未找到正文内容区域:"+info_url);
}
} catch (Exception e) {
logger.error("解析详情错误:"+info_url,e);
}
return null;
}
public static void main(String[] args) {
String day = DateUtils.getDate();
String time = "2025年7月8日";
try {
System.out.println(StringUtils.isNotEmpty(day) && (
(DateUtils.parseDate(time, "yyyy年MM月dd日").equals(DateUtils.parseDate(day,DateUtils.YYYY_MM_DD)) ||
(DateUtils.parseDate(time, "yyyy年MM月dd日").after(DateUtils.parseDate(day,DateUtils.YYYY_MM_DD)))
)));
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
... ...
package com.ruoyi.quartz.task.aquatic;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.fish.FishAquaticPublicOpinion;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class WwwChinaCfaOrg extends AquaticPublicOpinionBase{
public static void main(String[] args) {
WwwChinaCfaOrg wwwCsfishOrgCn = new WwwChinaCfaOrg();
wwwCsfishOrgCn.collect("");
}
/**
* 中国渔业协会
* @param day
* @return
*/
@Override
public List<FishAquaticPublicOpinion> collect(String day)
{
String[] urls = {"http://www.china-cfa.org/xwzx/","http://www.china-cfa.org/tzgg/","http://www.china-cfa.org/tzgg/","http://www.china-cfa.org/hzjl/","http://www.china-cfa.org/hzzx/","http://www.china-cfa.org/jypx/","http://www.china-cfa.org/bzgz/"};
List<FishAquaticPublicOpinion> list = new ArrayList<>();
for (String domain :urls)
{
try {
// 解析页面
Document doc = createDocument(domain);
// 选中 div.m_list 下的 ul 中的所有 li
Elements liElements = doc.select("div.list ul li");
// 打印所有 li 的 HTML
for (Element li : liElements) {
Elements a = li.select("a");
String url = a.attr("abs:href");
String title = a.attr("title");
String time = li.select("span").text();
if(StringUtils.isNotEmpty(day) && DateUtils.parseDate(time,DateUtils.YYYY_MM_DD).equals(DateUtils.parseDate(day,DateUtils.YYYY_MM_DD)))
{
FishAquaticPublicOpinion aquaticPublicOpinion = new FishAquaticPublicOpinion();
aquaticPublicOpinion.setTitle(title);
aquaticPublicOpinion.setInfoUrl(url);
aquaticPublicOpinion.setReleaseTime(DateUtils.parseDate(time,DateUtils.YYYY_MM_DD));
aquaticPublicOpinion.setCreateTime(new Date());
list.add(aquaticPublicOpinion);
}else{
return list;
}
}
} catch (Exception e) {
logger.error("数据解析错误:"+domain,e);
}
}
return list;
}
@Override
public String getInfo(String info_url)
{
try {
// 访问网页
Document doc = createDocument(info_url);
// 查找正文区域,常见class为 TRS_Editor 或 article
Element content = doc.selectFirst("div.TRS_Editor");
if (content != null) {
StringBuilder text = new StringBuilder();
// 遍历段落,保留换行
for (Element p : content.select("p")) {
String line = p.text().trim();
if (!line.isEmpty()) {
text.append(line).append("\n\n");
}
}
return text.toString();
} else {
logger.error("未找到正文内容区域:"+info_url);
}
} catch (Exception e) {
logger.error("解析详情错误:"+info_url,e);
}
return null;
}
}
... ...
package com.ruoyi.quartz.task.aquatic;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.fish.FishAquaticPublicOpinion;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class WwwCsfishOrgCn extends AquaticPublicOpinionBase{
@Override
List<FishAquaticPublicOpinion> collect(String day) {
String domain = "http://www.csfish.org.cn/catalog/197";
List<FishAquaticPublicOpinion> list = new ArrayList<>();
try {
// 解析页面
Document doc = createDocument(domain);
// 选中 div.m_list 下的 ul 中的所有 li
Elements liElements = doc.select("div.zjjg-panel-bd ul li.zjjg-eli");
// 打印所有 li 的 HTML
for (Element li : liElements) {
Elements a = li.select("a");
String url = a.attr("abs:href");
String title = a.text();
String time = li.select("span").text();
if(StringUtils.isNotEmpty(day) && DateUtils.parseDate(time,DateUtils.YYYY_MM_DD).equals(DateUtils.parseDate(day,DateUtils.YYYY_MM_DD)))
{
System.out.println("url:"+url+" title:"+title+" time:"+time);
FishAquaticPublicOpinion aquaticPublicOpinion = new FishAquaticPublicOpinion();
aquaticPublicOpinion.setTitle(title);
aquaticPublicOpinion.setInfoUrl(url);
aquaticPublicOpinion.setReleaseTime(DateUtils.parseDate(time,DateUtils.YYYY_MM_DD));
aquaticPublicOpinion.setCreateTime(new Date());
list.add(aquaticPublicOpinion);
}else {
return list;
}
}
} catch (Exception e) {
logger.error("数据解析错误:"+domain,e);
}
return list;
}
@Override
String getInfo(String info_url) {
try {
// 访问网页
Document doc = createDocument(info_url);
// 查找正文区域,常见class为 TRS_Editor 或 article
Element content = doc.selectFirst("div.solution-inform");
if (content != null) {
StringBuilder text = new StringBuilder();
String title = doc.selectFirst("div.words-title span").text();
text.append( title);
text.append("\n\n");
// 遍历段落,保留换行
for (Element p : content.select("p")) {
String line = p.text().trim();
if (!line.isEmpty()) {
text.append(line).append("\n\n");
}
}
return text.toString();
} else {
logger.error("未找到正文内容区域:"+info_url);
}
} catch (Exception e) {
logger.error("解析详情错误:"+info_url,e);
}
return null;
}
}
... ...
package com.ruoyi.quartz.task.aquatic;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.fish.FishAquaticPublicOpinion;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
@Service
public class WwwMoaGovCn extends AquaticPublicOpinionBase{
/**
* 中华人民共和国农业农村部网站
* @param day
* @return
*/
@Override
public List<FishAquaticPublicOpinion> collect(String day)
{
//先下载规章
nyncbgzk();
List<FishAquaticPublicOpinion> list = govpublic(day);
return list;
}
@Override
String getInfo(String info_url) {
try {
// 访问网页
Document doc = createDocument(info_url);
// 查找正文区域,常见class为 TRS_Editor 或 article
Element content = doc.selectFirst("div.gsj_htmlcon");
if (content != null) {
StringBuilder text = new StringBuilder();
// 遍历段落,保留换行
for (Element p : content.select("p")) {
String line = p.text().trim();
if (!line.isEmpty()) {
text.append(line).append("\n\n");
}
}
return text.toString();
} else {
logger.error("未找到正文内容区域:"+info_url);
}
} catch (Exception e) {
logger.error("解析详情错误:"+info_url,e);
}
return null;
}
public static void main(String[] args) {
WwwMoaGovCn wwwMoaGovCn = new WwwMoaGovCn();
wwwMoaGovCn.nyncbgzk();
}
private List<FishAquaticPublicOpinion> govpublic(String day)
{
String domain = "https://www.moa.gov.cn/govpublic/";
List<FishAquaticPublicOpinion> list = new ArrayList<>();
try {
// 解析页面
Document doc = createDocument(domain);
// 选中 div.m_list 下的 ul 中的所有 li
Elements liElements = doc.select("ul.commonlist li");
// 打印所有 li 的 HTML
for (Element li : liElements) {
Elements a = li.select("a");
String url = a.attr("abs:href");
String title = a.attr("title");
String time = li.select("span").text();
if(StringUtils.isNotEmpty(day) && DateUtils.parseDate(time,DateUtils.YYYY_MM_DD).equals(DateUtils.parseDate(day,DateUtils.YYYY_MM_DD)))
{
FishAquaticPublicOpinion aquaticPublicOpinion = new FishAquaticPublicOpinion();
aquaticPublicOpinion.setTitle(title);
aquaticPublicOpinion.setInfoUrl(url);
aquaticPublicOpinion.setReleaseTime(DateUtils.parseDate(time,DateUtils.YYYY_MM_DD));
aquaticPublicOpinion.setCreateTime(new Date());
list.add(aquaticPublicOpinion);
}else {
return list;
}
}
} catch (Exception e) {
logger.error("数据解析错误:"+domain,e);
}
return list;
}
/**
* 农业农村部
* 规章
* @return
*/
private void nyncbgzk()
{
String firstUrl = "https://www.moa.gov.cn/gk/nyncbgzk/";
try {
// 解析页面
Document doc = createDocument(firstUrl);
// 选中 div.m_list 下的 ul 中的所有 li
Elements liElements = doc.select("div.gz_list ul li div.title");
File[] files = getDirFils(Paths.get("uploadPath/gz/").toAbsolutePath().toString());
for (Element li : liElements)
{
Elements a = li.select("a");
String url = a.attr("abs:href");
String title = a.text()+".txt";
if(isStringInTop20Files(files, title))
{
return;
}
Document info_doc = createDocument(url);
Elements content = info_doc.select("div.gz_content");
Path path = Paths.get("uploadPath/gz/"+title);
saveFile(content.text(),path);
}
} catch (IOException e) {
logger.error("数据解析错误:"+firstUrl,e);
}
}
/**
* 判断指定字符串str是否存在于指定目录中按修改时间排序的前20个文件名中
* @param files 指定目录路径
* @param str 要匹配的字符串
* @return 如果存在则返回true,否则返回false
*/
public static boolean isStringInTop20Files( File[] files , String str) {
// 取前20个文件名判断是否包含指定字符串
for (int i = 0; i < Math.min(20, files.length); i++) {
String fileName = files[i].getName();
if (fileName.contains(str)) {
return true;
}
}
return false;
}
private static File[] getDirFils(String dirPath)
{
File dir = new File(dirPath);
if (!dir.exists() || !dir.isDirectory()) {
System.err.println("目录不存在或不是一个目录: " + dirPath);
return null;
}
File[] files = dir.listFiles();
if (files == null || files.length == 0) {
return null;
}
// 按照文件最后修改时间降序排序
Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
return files;
}
}
... ...
package com.ruoyi.quartz.task.aquatic;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.fish.FishAquaticPublicOpinion;
import com.zhonglai.luhui.dao.service.PublicService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 全国水产技术推广总站、中国水产学会
*/
@Service
public class WwwNftecAgriCn extends AquaticPublicOpinionBase{
/**
* 全国水产技术推广总站、中国水产学会
* @param day
* @return
*/
@Override
public List<FishAquaticPublicOpinion> collect(String day)
{
String[] urls = {"http://www.nftec.agri.cn/tzgg/","http://www.nftec.agri.cn/bwzc/","http://www.nftec.agri.cn/zzxhdt/","http://www.nftec.agri.cn/dfgz/","http://www.nftec.agri.cn/zcfg/"};
List<FishAquaticPublicOpinion> list = new ArrayList<>();
for (String domain :urls)
{
try {
// 解析页面
Document doc = createDocument(domain);
// 选中 div.m_list 下的 ul 中的所有 li
Elements liElements = doc.select("div.m_list ul li");
// 打印所有 li 的 HTML
for (Element li : liElements) {
Elements a = li.select("a");
String url = a.attr("abs:href");
String title = a.attr("title");
String time = li.select("span").text().replace("(","").replace(")","");
if(StringUtils.isNotEmpty(day) && DateUtils.parseDate(time,DateUtils.YYYY_MM_DD).equals(DateUtils.parseDate(day,DateUtils.YYYY_MM_DD)))
{
FishAquaticPublicOpinion aquaticPublicOpinion = new FishAquaticPublicOpinion();
aquaticPublicOpinion.setTitle(title);
aquaticPublicOpinion.setInfoUrl(url);
aquaticPublicOpinion.setReleaseTime(DateUtils.parseDate(time,DateUtils.YYYY_MM_DD));
aquaticPublicOpinion.setCreateTime(new Date());
list.add(aquaticPublicOpinion);
}else {
return list;
}
}
} catch (Exception e) {
logger.error("数据解析错误:"+domain,e);
}
}
return list;
}
@Override
public String getInfo(String info_url)
{
try {
// 访问网页
Document doc = createDocument(info_url);
// 查找正文区域,常见class为 TRS_Editor 或 article
Element content = null;
if (info_url.startsWith("http://www.nftec.agri.cn/zcfg"))
{
content = doc.selectFirst("div#TRS_AUTOADD");
}else{
content = doc.selectFirst("div.TRS_Editor");
}
if (content != null) {
StringBuilder text = new StringBuilder();
// 遍历段落,保留换行
for (Element p : content.select("p")) {
String line = p.text().trim();
if (!line.isEmpty()) {
text.append(line).append("\n\n");
}
}
return text.toString();
} else {
logger.error("未找到正文内容区域:"+info_url);
}
} catch (Exception e) {
logger.error("解析详情错误:"+info_url,e);
}
return null;
}
}
... ...
package com.zhonglai.luhui.admin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class TxtFileEncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 如果是.txt文件,设置Content-Type为 text/plain; charset=UTF-8
if (request instanceof HttpServletRequest) {
HttpServletRequest req = (HttpServletRequest) request;
String uri = req.getRequestURI();
if (uri != null && uri.endsWith(".txt")) {
HttpServletResponse resp = (HttpServletResponse) response;
resp.setContentType("text/plain; charset=UTF-8");
}
}
chain.doFilter(request, response);
}
}
\ No newline at end of file
... ...
... ... @@ -173,6 +173,15 @@ public class ServerController extends BaseController
HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=6d6b4790-d20f-4692-bc4a-e8ceb1e8cfda",jsonObject.toJSONString());
return AjaxResult.success();
}
@ApiOperation("获取当天水产新闻")
@GetMapping("/getNowAquaticPublicOpinion")
public AjaxResult getNowAquaticPublicOpinion()
{
List<Map<String,Object>> lsit = publicService.getObjectListBySQL("SELECT * FROM `fish_aquatic_public_opinion` WHERE release_time='"+DateUtils.getDate()+" 00:00:00'");
return AjaxResult.success(lsit);
}
@ApiOperation("获取服务器应用列表")
@GetMapping("/getServiceAoolicationList")
public Map<String,Object> getServiceAoolicationList()
... ... @@ -307,7 +316,15 @@ public class ServerController extends BaseController
{
startPage();
startOrderBy();
List<Map<String,Object>> list = publicService.getObjectList(sysMonitorApplicationLog,"*",null,null,0,0);
Map<String, Object> map = new HashMap<>();
Map<String, Object> params = sysMonitorApplicationLog.getParams();
if(params.containsKey("s_timestamp") && params.containsKey("e_timestamp"))
{
map.put("end_timestamp",params.get("e_timestamp"));
sysMonitorApplicationLog.setTimestamp((String) params.get("s_timestamp"));
map.put("timestamp","time=");
}
List<Map<String,Object>> list = publicService.getObjectList(sysMonitorApplicationLog,"*",map,null,0,0);
return getDataTable(list);
}
... ...
# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 实例演示开关 demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) profile: D:/ruoyi/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 captchaType: math # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8080 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn com.zhonglai.luhui: debug # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 119.23.218.181 # 端口,默认为6379 port: 6379 # 数据库索引 database: 1 # 密码 password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-admin # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/tool/gen/generatorCodeFromDb,/data/**,/monitor/server/upload,/monitor/server/getSysMonitorServerList,/monitor/server/getSysMonitorServerLogList # NameServer地址 rocketmq: name-server: 8.129.224.117:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-mqtt-service-deviceCommand-test send-tags: 1
\ No newline at end of file
# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 实例演示开关 demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) profile: E:/work/idea/Luhui/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 captchaType: math # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8080 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn com.zhonglai.luhui: debug # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 119.23.218.181 # 端口,默认为6379 port: 6379 # 数据库索引 database: 1 # 密码 password: # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-admin # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/tool/gen/generatorCodeFromDb,/data/**,/monitor/server/upload,/monitor/server/getSysMonitorServerList,/monitor/server/getSysMonitorServerLogList # NameServer地址 rocketmq: name-server: 8.129.224.117:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-mqtt-service-deviceCommand-test send-tags: 1
\ No newline at end of file
... ...
... ... @@ -615,6 +615,11 @@
<version>1.18</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.2</version>
</dependency>
</dependencies>
... ...