1.文本垃圾内容检测
试用阿里云的内容安全检测来做我们的文本,图片的检测
1.1使用方法如下:
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix="aliyun")
@PropertySource("classpath:aliyun.properties")
public class AliyunTextScanRequest {
private String accessKey;
private String secret;
public String textScanRequest(String content) throws Exception {
IClientProfile profile = DefaultProfile.getProfile("cn-shanghai", accessKey, secret);
IAcsClient client = new DefaultAcsClient(profile);
TextScanRequest textScanRequest = new TextScanRequest();
textScanRequest.setAcceptFormat(FormatType.JSON); // 指定api返回格式
textScanRequest.setHttpContentType(FormatType.JSON);
textScanRequest.setMethod(com.aliyuncs.http.MethodType.POST); // 指定请求方法
textScanRequest.setEncoding("UTF-8");
textScanRequest.setRegionId("cn-shanghai");
List<Map<String, Object>> tasks = new ArrayList<Map<String, Object>>();
Map<String, Object> task1 = new LinkedHashMap<String, Object>();
task1.put("dataId", UUID.randomUUID().toString());
/**
* 待检测的文本,长度不超过10000个字符
*/
task1.put("content", content);
tasks.add(task1);
JSONObject data = new JSONObject();
/**
* 检测场景,文本垃圾检测传递:antispam
**/
data.put("scenes", Arrays.asList("antispam"));
data.put("tasks", tasks);
System.out.println(JSON.toJSONString(data, true));
textScanRequest.setHttpContent(data.toJSONString().getBytes("UTF-8"), "UTF-8", FormatType.JSON);
// 请务必设置超时时间
textScanRequest.setConnectTimeout(3000);
textScanRequest.setReadTimeout(6000);
try {
HttpResponse httpResponse = client.doAction(textScanRequest);
if(httpResponse.isSuccess()){
JSONObject scrResponse = JSON.parseObject(new String(httpResponse.getHttpContent(), "UTF-8"));
System.out.println(JSON.toJSONString(scrResponse, true));
if (200 == scrResponse.getInteger("code")) {
JSONArray taskResults = scrResponse.getJSONArray("data");
for (Object taskResult : taskResults) {
if(200 == ((JSONObject)taskResult).getInteger("code")){
JSONArray sceneResults = ((JSONObject)taskResult).getJSONArray("results");
for (Object sceneResult : sceneResults) {
String scene = ((JSONObject)sceneResult).getString("scene");
String suggestion = ((JSONObject)sceneResult).getString("suggestion");
//根据scene和suggetion做相关处理
//suggestion == pass 未命中垃圾 suggestion == block 命中了垃圾,可以通过label字段查看命中的垃圾分类
System.out.println("args = [" + scene + "]");
System.out.println("args = [" + suggestion + "]");
return suggestion;
}
}else{
System.out.println("task process fail:" + ((JSONObject)taskResult).getInteger("code"));
}
}
} else {
System.out.println("detect not success. code:" + scrResponse.getInteger("code"));
}
}else{
System.out.println("response not success. status:" + httpResponse.getStatus());
}
} catch (ClientException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
编写配置类扫描阿里云Config,同时编写测试类AliTest{
@Autowired
private AliyunTextScanRequest aliyunTextScanRequest;
@Test
public void testText(){
String content ="阿里云,阿里巴巴集团旗下云计算品牌,全球卓越的云计算技术和服务提供商。创立于2009年,在杭州、北京、硅谷等地设有研发中心和运营机构。";
String response=aliyunTextScanRequest.textScanRequest(content);
System.out.println(response+"------------------");
}
}
2.图片审核
图片审核,有两种方式,第一种放一个url,第二种方式传一个本地的图片到程序中进行检测
创建工具类:com.common.aliyun.AliyunImageScanRequest
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix="aliyun")
@PropertySource("classpath:aliyun.properties")
public class AliyunImageScanRequest {
private String accessKey;
private String secret;
public String imageScanRequest(List<String> images) throws Exception {
IClientProfile profile = DefaultProfile.getProfile("cn-shanghai",accessKey,secret);
DefaultProfile.addEndpoint("cn-shanghai", "cn-shanghai", "Green", "green.cn-shanghai.aliyuncs.com");
IAcsClient client = new DefaultAcsClient(profile);
ImageSyncScanRequest imageSyncScanRequest = new ImageSyncScanRequest();
// 指定api返回格式
imageSyncScanRequest.setAcceptFormat(FormatType.JSON);
// 指定请求方法
imageSyncScanRequest.setMethod(MethodType.POST);
imageSyncScanRequest.setEncoding("utf-8");
//支持http和https
imageSyncScanRequest.setProtocol(ProtocolType.HTTP);
JSONObject httpBody = new JSONObject();
/**
* 设置要检测的场景, 计费是按照该处传递的场景进行
* 一次请求中可以同时检测多张图片,每张图片可以同时检测多个风险场景,计费按照场景计算
* 例如:检测2张图片,场景传递porn,terrorism,计费会按照2张图片鉴黄,2张图片暴恐检测计算
* porn: porn表示色情场景检测
*/
httpBody.put("scenes", Arrays.asList("logo","porn","ad","terrorism"));
/**
* 设置待检测图片, 一张图片一个task,
* 多张图片同时检测时,处理的时间由最后一个处理完的图片决定。
* 通常情况下批量检测的平均rt比单张检测的要长, 一次批量提交的图片数越多,rt被拉长的概率越高
* 这里以单张图片检测作为示例, 如果是批量图片检测,请自行构建多个task
*/
List<JSONObject> list = new ArrayList<JSONObject>();
for (String image : images) {
JSONObject task = new JSONObject();
task.put("dataId", UUID.randomUUID().toString());
//设置图片链接为上传后的url
task.put("url", image);
task.put("time", new Date());
list.add(task);
}
httpBody.put("tasks", list);
imageSyncScanRequest.setHttpContent(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(httpBody.toJSONString()),
"UTF-8", FormatType.JSON);
/**
* 请设置超时时间, 服务端全链路处理超时时间为10秒,请做相应设置
* 如果您设置的ReadTimeout 小于服务端处理的时间,程序中会获得一个read timeout 异常
*/
imageSyncScanRequest.setConnectTimeout(3000);
imageSyncScanRequest.setReadTimeout(10000);
HttpResponse httpResponse = null;
try {
httpResponse = client.doAction(imageSyncScanRequest);
} catch (Exception e) {
e.printStackTrace();
}
//服务端接收到请求,并完成处理返回的结果
if (httpResponse != null && httpResponse.isSuccess()) {
JSONObject scrResponse = JSON.parseObject(org.apache.commons.codec.binary.StringUtils.newStringUtf8(httpResponse.getHttpContent()));
System.out.println(JSON.toJSONString(scrResponse, true));
int requestCode = scrResponse.getIntValue("code");
//每一张图片的检测结果
JSONArray taskResults = scrResponse.getJSONArray("data");
if (200 == requestCode) {
for (Object taskResult : taskResults) {
//单张图片的处理结果
int taskCode = ((JSONObject) taskResult).getIntValue("code");
//图片要检测的场景的处理结果, 如果是多个场景,则会有每个场景的结果
JSONArray sceneResults = ((JSONObject) taskResult).getJSONArray("results");
if (200 == taskCode) {
for (Object sceneResult : sceneResults) {
String scene = ((JSONObject) sceneResult).getString("scene");
String suggestion = ((JSONObject) sceneResult).getString("suggestion");
//根据scene和suggetion做相关处理
//do something
System.out.println("scene = [" + scene + "]");
System.out.println("suggestion = [" + suggestion + "]");
return suggestion;
}
} else {
//单张图片处理失败, 原因是具体的情况详细分析
System.out.println("task process fail. task response:" + JSON.toJSONString(taskResult));
}
}
} else {
/**
* 表明请求整体处理失败,原因视具体的情况详细分析
*/
System.out.println("the whole image scan request failed. response:" + JSON.toJSONString(scrResponse));
}
}
return null;
}
}
当自媒体用户在自媒体端发表了一篇文章是需要通过审核通过之后才能在用户app端展示
news:文章状态
1.提交(待审核)
2.审核失败
3.人工审核
4.人工审核通过
8.审核通过(待发布)
9.已发布
审核的思路和流程是这样:
1.文章状态如果为4就不用再次去审核了,可以直接保存数据。
2.状态为8,发布时间是大于当前时间的,就可以保存数据了
3.判断为1,待审核
4.标题和内容是否匹配,不匹配,operation:人工复审或拒绝给用户推送消息。
5.审核文本 operation:人工复审或者拒绝。
6.审核图片,
7.判断发布时间是否大于当前时间 是的话就保存数据,不是的话就将vmNews的状态改成9审核已通过。
8.如果不是就保存数据,向ap_article中保存一条数据。
ap_article_config
ap_article
ap_ariticle_content
ap_author
4张表中都需要存贮
8.创建索引
9.修改wmNew文章的状态为9,文章审核通过保存消息。
文章审核代码实现
1.adChannelMapper的接口,添加根据id查询频道的方法.
AdChannel selectByPrimaryKey(Integer id);
AdChannelMapper.xml
<select id="selectByPrimaryKey" resultMap="BaseResultMap" paramType="java.lang.Integer">
select
<include refid="Base_Column_List"/>
from ad_channel
where id=#{id}
</select>
2.修改com.heima.model.mapper.app.ApAuthorMapper,添加根据名称查询作者的添加方法
ApAuthor selectByAuthorName(String authorName);
void insert(ApAuthor apAuthor);
先根据作者名称来查询作者,没有查询到就添加作者信息。
3.添加对应的ApArticleContentMapper
void insert(ApArticleContent articleContent)
ApArticleConfigMapper
int insert(ApArticleConfig apArticleConfig);
ApArrticleMapper
int insert(ApArticle apArticle);
这里的mapper中需要返回我们的文章id,这样我们才能添加对应config,content.
在WmNewsMapper
新建ApUserMessageMapper类 。
@Service
@SuppressWarnnings("all")
public class ReviewMediaAtricleImpl implements ReviewMediaAtricleService{
@Autowired
private WmNewsMapper wmNewsMapper;
@Autowired
private AliyunTextScanRequest aliyunTestScanRequest;
@Autowired
private AliyunImageScanRequest aliyunImageScanRequest;
@Override
public void autoReviewAticleByMedia(Integer newsId){
//根据文章id查询文章信
WmNews wmNews= wmNewsMapper.selectNewsDetailByPrirmaryKey(newsId);
if(wmNes!=null){
//判断状态为4的时,直接保存数据,人工审核通过了
if(wmNews.getStatus()==4){
reviewSuccessSaveAll(wmNews);
return;
}
//审核通过后的待发布文章,判断发布时间
if(wmNews.getStatus()==0&&wmNews.getPublishTime()!=null&&wm.getPublishTime>new Date().getTime){
reviewSuccessSaveAll(wmNews);
return;
}
}
//审核文章
if(wmNews.getStatus()==1){
//审核文章标题和内容的匹配度使用工具类Compute,比对第一个字符串,在第二个字符串的一个占有率
String content=wmNew.getContent();
String title=wmNew.getNews();
double degree=Compute.SimilarDegree(content,title);
if(degree<=0){
//文章标题不匹配,审核不通过
updateWmNews(wmNews,(short)2,"文章内容和标题不匹配");
return;
}
//文章标题匹配,审核文本和图片其实都是content
//解析content
List<String> images=new ArrayList<>();
StringBuilder sb=new StringBuilder();
JSONArray jsonarray=JSON.parseArray(content);
handlerTextAndImages(images,sb,jsonArray);
//审核文本内容,
String response =aliyunTextScanRequest.textScanRequest(sb.toString());
if("review".equals(response)){
//人工审核
updateWmNews(wmNews,(short)3,"需要人工审核");
return;
}
if("block".equals(response)){
updateWmNews(wmNews,(short)2,"文本内容审核失败");
return;
}
//审核文章中的图片信息,阿里接口
String imageResponse=aliyunImageScanRequset.imageScanRequset(images);
if(imageResponse==null){
updateWmNews(wmNews,(short)3,"需要人工审核");
retrun;
}
if("review".equals(response)){
//人工审核
updateWmNews(wmNews,(short)3,"需要人工审核");
return;
}
if("block".equals(response)){
updateWmNews(wmNews,(short)2,"图片内容审核出现问题");
return;
}
//审核图片信息,阿里接口
//判断发布时间,如果否的话,保存数据,是的话,将wmApticle得status改成8.
if(wmNews.getPublishTime()!=null){
if(wmNews.getPublishTime.getTime()>new Date().getTime()){
//修改wmNews的状态为8
updateWmNews(wmNews,(short)8,"待发布");
}
else{
//立即发布
updateWmNews(wmNews );
}
}else{
reviewSuccessSaveAll(wmNews);
}
}
}
private void updateWmNews(WmNew swmNews,short status,String type){
wmNews.setStatus(status);
wmNews.setReason(String);
WmNews.updateByPrimaryKeySelective(wmNews);
}
@Autowired
private ApAuthorMapper apAurthorMapper;
//保存数据,有4张表 ap_article_config,ap_article,ap_article_content,ap_author
//ap_author,保存文章的时候依赖于作者,有就用,没有就添加
private void reviewSuccessSaveAll(WmNews wmNews){
if(wmNews.getUserId!=null){
wmUser wmuser=wmUserMapper.selectById(wmNews.getUserId()) ;
ApAuthor apauthor=null;
if(wmuser!=null&&wmUser.getName!=null){
ApAuthor apauthor=ApAtuhorMapper.selectByAuthorName(wmUser.getName());
if(apauthor==null||author.getId()==null){
//查询保存
apAuthor=new ApAuthor():
apAuthor.setUseId(wmNews.getUserId());
apAuthor.setCreatedTime(new Dat());
apAuthor.setType(2);
apAuthor.setName(wmUser.getName());
apAUthor.setWmUserId(wmUser.getId());
apAuthorMapper.insert(apAuthor);
}
}
}
//ap_article:channel需要查询ad_channel,布局需要设置vm中的type.文章的图片,文章的标签,创建时间设置,来源设置一下
ApArticle apArticle=new ApArticle();
Integer channelId=wmNews.getId();
if(apAuthor!=null){
apArticle.setAuthorId(apAuthor.getId().longValue());
apArticle.setAuthorName(apAuthor.getName());}
apArticle.setCreatTime(new Date())
if(channelId!=null){
adChannelMapper.selectByPrimaryKey(channelId);
apArticle.setChannelId(channelId);
apArticle.setChannelName(adChannel.getName());
}
//ap_article_congfig,ap_article_content
apArticle.setLayout(wmNews.getType());
apArticle.setTitle(wmNews.getTitle());
String images=wmNews.getImages();//访问路径 servrUri+文件id
if(images!=null){
String[] split=images.split(",");
StringBuilder sb=new StirngBuilder();
for(int i<0;i<split.length;i++){
if(i>0){
sb.append(,);
}
sb.append(fileServerUrl);
sb.append(split[i]);
}
apArticle.setImages(sb.toString());
}
apArticleMapper.insert(apArticle);
//创建ES索引,便于搜索。
}
//找出文本内容和图片列表
private void handlerTextAndImages(List<String> images,StrinBuilder sb,JSONArray jsonArray){
for(Object obj:jsonArray){
JSONObject jsonObj=(JSONObject)obj;
String type=(String)jsonObj.get("type");
if("image".equals(type)){
String value=(String)jsonObj.get("value");
images.add(value);
}
if("text".equals(type)){
sb.append(jsonObj.get("value"));
}
}
}
}
Content的格式如下:
我们需要将text和层image都取出来,答题思路,转换成list
文章审核自动测试:
public void TestReview(){
reviewMediaArticleService.autoReviewByMedia(6110);
//当路径访问不到的时候,我们的response可能会为null,我们需要修改代码。
//如果时间为null,我们就立即发布
}