pythonの鉴黄之路(五)——强行解析json串

23 篇文章 0 订阅

*以下内容并非正规解决方案,效仿请谨慎。


之前有介绍过阿里云的鉴黄API接口http://blog.csdn.net/sm9sun/article/details/53321888

其支持:porn: 黄图检测,ocr:文字识别,illegal: 暴恐敏感识别三个业务

其API也很人性的把其返回的json串做出了解析,我们可以直接拿到相应的返回值。

而如果想对其做进一步的开发,比如说拿到ocr后再做敏感词识别

字典树实现敏感词检索http://blog.csdn.net/sm9sun/article/details/53308643

那么想了想最好还是回到C++去处理这部分工作。

之前也有写过C++嵌入python开发的博客http://blog.csdn.net/sm9sun/article/details/53392760

网上找了一下,也确实有实现python的字典与C++ map容器转换的方法(用PyDict_Next遍历python的字典对象)

不过想来想去总是感觉有一些麻烦。反正字符串是万能的,我们还不如干脆拿到python的返回json串(实际是转换后的string字符串)

然后自己去做解析处理,简单粗暴~


首先我们需要strstr函数来进行字典关键词的匹配,但是有一个问题,我们知道strstr匹配不到的时候会返回NULL指针的,而我们把json串当作string去匹配处理的话肯定会出现某个字典匹配不到的情况,那么这就非常的不安全。所以我们在其外部套了一层,也顺便把字典名给去掉

string my_strstrEX(char * _Str,const char * _SubStr)
{

	char *posStr=strstr(_Str,_SubStr);
	if(posStr==NULL)
	{
		return "";
	}
	else
	{
		return string(posStr+strlen(_SubStr));
	}
}

还有就是需要去除[] “”等区间符号


/*
功能:去掉区间符号


dictword:字典字符串
c       :区间符,例如:[] '' "" (){}

return  :关键词

*/
string getKeyBydictword(string dictword,char c)
{
	if(strlen(dictword.c_str())<2)   //如果长度小于2,直接返回错误
	{
		return "ErrorString";
	}
	char ec=c;               //结束符
	if('\"'==c) ec='\"';
	if('\''==c) ec='\'';
	if('['==c) ec=']';
	if('('==c) ec=')';
	if('{'==c) ec='}';
	int si=0,ei=-1;
	int nsi=0,nei=0;//记录符号出现的次数,当nsi和nei相等时,说明其是匹配的一对
    for(int i=0;i<=strlen(dictword.c_str())-1;i++)
	{
		
		if(dictword[i]==ec&&(nsi>nei))      //因为某些区间符两边相等,如"",所以判断标准为nsi>nei
		{
			nei++;
			if(nsi==nei)
			{
				ei=i;
				break;
			}		
		}		
		else if(dictword[i]==c)
		{
			nsi++;
			if(nsi==1)
			{
				si=i+1;
			}			
		}
	}
	if(nei>0)
	return dictword.substr(si,ei-si);
	else
    return "ErrorString";
}



接下来就是主函数的调用了

完整代码:


// call_py_test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Python.h" 
#include <string>
#include <iostream>

using namespace std;

/* 
图像识别py
返回字典结构体
*/

struct retdict
{
string strCode;   //执行信息
string strMsg;    //异常信息
string strOcr;    //文字识别
int nPorn;        //色情返回值
int nIllegal;     //暴恐返回值
};





/*
由于strstr匹配不到检索字串Substr时会返回NULL
考虑到安全性问题,故在此加了一层NULL的处理
额外过滤掉检索字串的长度
*/
string my_strstrEX(char * _Str,const char * _SubStr)
{

	char *posStr=strstr(_Str,_SubStr);
	if(posStr==NULL)
	{
		return "";
	}
	else
	{
		return string(posStr+strlen(_SubStr));
	}
}


/*
const char*的重载
*/
string my_strstrEX(const char * _Str,const char * _SubStr)
{

	const char *posStr=strstr(_Str,_SubStr);
	if(posStr==NULL)
	{
		return "";
	}
	else
	{
		return string(posStr+strlen(_SubStr));
	}
}








/*
功能:去掉区间符号


dictword:字典字符串
c       :区间符,例如:[] '' "" (){}

return  :关键词

*/
string getKeyBydictword(string dictword,char c)
{
	if(strlen(dictword.c_str())<2)   //如果长度小于2,直接返回错误
	{
		return "ErrorString";
	}
	char ec=c;               //结束符
	if('\"'==c) ec='\"';
	if('\''==c) ec='\'';
	if('['==c) ec=']';
	if('('==c) ec=')';
	if('{'==c) ec='}';
	int si=0,ei=-1;
	int nsi=0,nei=0;//记录符号出现的次数,当nsi和nei相等时,说明其是匹配的一对
    for(int i=0;i<=strlen(dictword.c_str())-1;i++)
	{
		
		if(dictword[i]==ec&&(nsi>nei))      //因为某些区间符两边相等,如"",所以判断标准为nsi>nei
		{
			nei++;
			if(nsi==nei)
			{
				ei=i;
				break;
			}		
		}		
		else if(dictword[i]==c)
		{
			nsi++;
			if(nsi==1)
			{
				si=i+1;
			}			
		}
	}
	if(nei>0)
	return dictword.substr(si,ei-si);
	else
    return "ErrorString";
}



int main(int argc, char** argv) 
{ 
	//初始化Python 
	//在使用Python系统前,必须使用Py_Initialize对其 
	//进行初始化。它会载入Python的内建模块并添加系统路 
	//径到模块搜索路径中。这个函数没有返回值,检查系统 
	//是否初始化成功需要使用Py_IsInitialized。 

	Py_Initialize(); 


	// 检查初始化是否成功 
	if ( !Py_IsInitialized() ) 
	{ 
		return -1; 
	} 

	// 添加当前路径 
	//把输入的字符串作为Python代码直接运行,返回0 
	//表示成功,-1表示有错。大多时候错误都是因为字符串 
	//中有语法错误。 
	PyRun_SimpleString("import sys"); 
	PyRun_SimpleString("sys.path.append('./')"); 
	PyObject *pName,*pModule,*pDict,*pFunc,*pArgs; 

	// 载入脚本 
	pName = PyString_FromString("imgfocpp"); 
	pModule = PyImport_Import(pName); 
	if ( !pModule ) 
	{ 
		printf("can't find imgfocpp.py"); 
		getchar(); 
		return -1; 
	} 
	pDict = PyModule_GetDict(pModule); 
	if ( !pDict ) 
	{ 
		return -1; 
	} 

	// 找出函数名为retStr_test的函数 
	pFunc = PyDict_GetItemString(pDict, "imgmain"); 
	if ( !pFunc || !PyCallable_Check(pFunc) ) 
	{ 
		printf("can't find function [imgmain]"); 
		getchar(); 
		return -1; 
	} 

	// 参数进栈 
	*pArgs; 
	pArgs = PyTuple_New(1); 

	//  PyObject* Py_BuildValue(char *format, ...) 
	//  把C++的变量转换成一个Python对象。当需要从 
	//  C++传递变量到Python时,就会使用这个函数。此函数 
	//  有点类似C的printf,但格式不同。常用的格式有 
	//  s 表示字符串, 
	//  i 表示整型变量, 
	//  f 表示浮点数, 
	//  O 表示一个Python对象。 

	string arg1="图片的URL";
	PyTuple_SetItem(pArgs, 0, Py_BuildValue("s",arg1.c_str())); 
	// 调用Python函数 
	
	char* strRet;
	PyObject* result=PyObject_CallObject(pFunc, pArgs); 

	//返回值类型转换
	PyArg_Parse(result, "s", &strRet);

	//cout<<"strRet="<<strRet<<endl;
	

	retdict a;
	string Codedict=my_strstrEX(strRet,"\"Code\":");
	a.strCode=getKeyBydictword(Codedict,'\"');

	string Msgdict=my_strstrEX(strRet,"\"Msg\":");
	a.strMsg=getKeyBydictword(Msgdict,'\"');

	// the list string format:   "Label":[int],"Rate":[int]
	string Porndict=my_strstrEX(strRet,"\"PornResult\":");
	string listPorn=getKeyBydictword(Porndict,'{');
	a.nPorn=atoi(my_strstrEX(listPorn.c_str(),"\"Rate\":").c_str());

	string Illegaldict=my_strstrEX(strRet,"\"IllegalResult\":");
	string listIllegal=getKeyBydictword(Illegaldict,'{');
	a.nIllegal=atoi(my_strstrEX(listIllegal.c_str(),"\"Rate\":").c_str());

	string Ocrdict=my_strstrEX(strRet,"\"String\":");
	a.strOcr=getKeyBydictword(Ocrdict,'[');


	cout<<"******************retdict******************"<<endl;
	cout<<a.strCode<<endl;
	cout<<a.strMsg<<endl;
	cout<<a.strOcr<<endl;
	cout<<a.nPorn<<endl;
	cout<<a.nIllegal<<endl;

	Py_DECREF(pName); 
	Py_DECREF(pArgs); 
	Py_DECREF(pModule); 

	// 关闭Python 
	Py_Finalize(); 
	system("pause");
	return 0; 



	
} 



C++做字符串解析工作,python代码就很简单了,直接返回string类型的json串就好。

#coding=utf-8
def imgmain(imgurl):
    import sys
    reload(sys)
    sys.setdefaultencoding('gbk')
    imgurl2=imgurl.encode('utf8')
    sys.setdefaultencoding('utf8')
    # 同步图片检测服务接口, 会实时返回检测的结果
    from aliyunsdkcore import client
    from aliyunsdkgreen.request.v20161018 import ImageDetectionRequest
    import json
    # 请替换成你自己的accessKeyId、accessKeySecret, 您可以类似的配置在配置文件里面,也可以直接明文替换
    #clt = client.AcsClient("1", "2",'3')
    clt = client.AcsClient("你自己的accessKeyId", "你自己的accessKeySecret",'cn-hangzhou')
    request = ImageDetectionRequest.ImageDetectionRequest()
    request.set_accept_format('json')
    # 设置成同步调用
    request.set_Async('false')
    # 设置要检测的图片链接
    # json字符串格式, 同步只支持单张图片
    request.set_ImageUrl(json.dumps([imgurl2]))
    # 设置要检测的服务场景
    # 异步支持多个场景同时识别
    # porn: 黄图检测
    # ocr: ocr文字识别
    # illegal: 暴恐敏感识别
    request.set_Scene(json.dumps(["porn","ocr","illegal"]))
    response = clt.do_action(request)
    #"The request has failed due to a temporary failure of the server"
    print response.encode('gbk')
    return response.encode('gbk')


调用成功截图:


注:ocr返回的其实是个列表,所以用引号括起来,每个独立的词汇后面会有一个“,”这里就先不作处理,

等与敏感词检索联立时再进行切分。


调用失败截图:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值