利用阿里云接口“印刷文字识别”识别图表。地址:https://market.aliyun.com/products/57124001/cmapi024968.html
![](https://i-blog.csdnimg.cn/blog_migrate/26620dc1ad0d7a699b4a6682b829ed44.png)
相关接口
![](https://i-blog.csdnimg.cn/blog_migrate/fb2d128659acec723e7ecc70b6649c8c.png)
java代码调用。APPcode的值是需要去开通这个功能的服务,然后才获取到的。
package com.alibaba.ocr.demo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.api.gateway.demo.util.HttpUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.apache.commons.codec.binary.Base64.encodeBase64;
/**
* 使用APPCODE进行云市场ocr服务接口调用
*/
public class APPCodeDemo {
/*
* 获取参数的json对象
*/
public static JSONObject getParam(int type, String dataValue) {
JSONObject obj = new JSONObject();
try {
obj.put("dataType", type);
obj.put("dataValue", dataValue);
} catch (JSONException e) {
e.printStackTrace();
}
return obj;
}
public static void main(String[] args){
String host = "https://form.market.alicloudapi.com";
String path = "/api/predict/ocr_table_parse";
String appcode = "你的APPCODE";
String imgFile = "图片路径";
Boolean is_old_format = false;//如果文档的输入中含有inputs字段,设置为True, 否则设置为False
//请根据线上文档修改configure字段
JSONObject configObj = new JSONObject();
configObj.put("format", "html");
configObj.put("finance", false);
configObj.put("dir_assure", false);
String config_str = configObj.toString();
// configObj.put("min_size", 5);
//String config_str = "";
String method = "POST";
Map<String, String> headers = new HashMap<String, String>();
//最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
headers.put("Authorization", "APPCODE " + appcode);
Map<String, String> querys = new HashMap<String, String>();
// 对图像进行base64编码
String imgBase64 = "";
try {
File file = new File(imgFile);
byte[] content = new byte[(int) file.length()];
FileInputStream finputstream = new FileInputStream(file);
finputstream.read(content);
finputstream.close();
imgBase64 = new String(encodeBase64(content));
} catch (IOException e) {
e.printStackTrace();
return;
}
// 拼装请求body的json字符串
JSONObject requestObj = new JSONObject();
try {
if(is_old_format) {
JSONObject obj = new JSONObject();
obj.put("image", getParam(50, imgBase64));
if(config_str.length() > 0) {
obj.put("configure", getParam(50, config_str));
}
JSONArray inputArray = new JSONArray();
inputArray.add(obj);
requestObj.put("inputs", inputArray);
}else{
requestObj.put("image", imgBase64);
if(config_str.length() > 0) {
requestObj.put("configure", config_str);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
String bodys = requestObj.toString();
try {
/**
* 重要提示如下:
* HttpUtils请从
* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
* 下载
*
* 相应的依赖请参照
* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
*/
HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
int stat = response.getStatusLine().getStatusCode();
if(stat != 200){
System.out.println("Http code: " + stat);
System.out.println("http header error msg: "+ response.getFirstHeader("X-Ca-Error-Message"));
System.out.println("Http body error msg:" + EntityUtils.toString(response.getEntity()));
return;
}
String res = EntityUtils.toString(response.getEntity());
JSONObject res_obj = JSON.parseObject(res);
if(is_old_format) {
JSONArray outputArray = res_obj.getJSONArray("outputs");
String output = outputArray.getJSONObject(0).getJSONObject("outputValue").getString("dataValue");
JSONObject out = JSON.parseObject(output);
System.out.println(out.toJSONString());
}else{
System.out.println(res_obj.toJSONString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
返回结果
支持三种格式输出:html/xlsx(excel)/json
#html 格式输出
{
"success":true,
"tables":"<html>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">\n<style type=\"text/css\">\n table tr td { border: 1px solid blue }\n table { border: 1px solid blue }\n span.note { font-size: 9px; color: red }\n</style>\n<table \"id\"=0>\n<tr><td colspan=1 rowspan=1>项 目 </td><td colspan=1 rowspan=1>期末余额 </td><td colspan=1 rowspan=1>年初余额 </td></tr><tr><td colspan=1 rowspan=1>合计 </td><td colspan=1 rowspan=1>5,423,591,988.10 </td><td colspan=1 rowspan=1>4,281,407,583.62 </td></tr>...</table></html>\n"
}
#xlsx 格式:
{"success":true,
"tables":"UEsDBBQAAAAIAAAAIQAR0e9YNAoAAIpUAAAYAAAA..." #base64 encoded excel file( base64编码的excel文件)
}
直接拷贝tables后面的字符串到文件保存,需要将里面的\n替换掉,在linux环境下,可以执行如下操作:
sed -i -e 's/\\n/\n/g' tmp_base64
base64 -d tmp_base64 > 9_100.xlsx
如果用python的话,可以执行如下代码:
import base64
import json
...
# result = "{\"success\":true, \"tables\":\"UEsD...\"}"
res_obj = json.loads(result)
with open('output.xlsx', 'wb') as fout:
fout.write(base64.b64decode(res_obj['tables']))
#json 格式输出
{
"success":true,
"tables":[
[ #table 0
[ # table0 row 0
{ # table 0 row 0 col 0
"sx":0, #start from column(单元格的起始列id)
"sy":0, #start row(单元格的起始行id)
"ex":1, #one past end column index(单元格所占的列数(colspan)为ex - sx)
"ey":1, #one past end row index(单元格所占的行数(rowspan)为ey - sy)
"height":96, #cell height,图片上单元格的高度
"width":573 #cell width,图片上单元格的宽度
"text":[
"项", #text block 0 (第一个文字块)
"目" #text block 1 (第二个文字块)
],
},
...
],
[ #table 0 row 1
{
"ex":1,
"ey":2,
"height":94,
"sx":0,
"sy":1,
"text":[
"合计"
],
"width":572
},
...
],
... #more rows
]
]
}
失败返回示
上面获取的xlsx的base64转为文件
public String decryptByBase64(String base64, String filePath) {
if (base64 == null && filePath == null) {
return "生成文件失败,请给出相应的数据。";
}
try {
Files.write(Paths.get(filePath), Base64.getDecoder().decode(base64),StandardOpenOption.CREATE);
} catch (IOException e) {
e.printStackTrace();
}
return "指定路径下生成文件成功!";
}
xlsx文档数据打印
/**
* 根据文件路径解析出行数据map
* @param filePath
* @return
* @throws IOException
*/
public static List<Map<Integer, Object>> parseXlsxFile(String filePath) throws IOException {
List<Map<Integer, Object>> list = new ArrayList<>();
//加载数据源文件
//把目标文件转化为文件流
File excelFile=new File(filePath);
//判断是否是文件并且是否存在
if(excelFile.isFile()&&excelFile.exists()){
//创建输出流对象
FileInputStream fls=new FileInputStream(excelFile);
//将输出的流对象引入到解析excel文件的对象中
Workbook wb=null;
/*判断文件是xlsx结尾还是xls结尾 声明XSSF或HSSF对象*/
String[] split = excelFile.getName().split("\\.");
if(split[1].equals("xlsx")){
wb= new XSSFWorkbook(fls);
}else if(split[1].equals("xls")){
wb= new HSSFWorkbook(fls);
}
//获取工作表页数据
//读取第1页的数据
Sheet sheet=wb.getSheetAt(0);
//获取工作表页中行数据
//读取的行,如果sheet中一行数据没有返回-1,只有第一行有数据则返回0,最后有数据的行是第n行则返回n-1
int firstRowIndex=sheet.getFirstRowNum();
//读取的总的行数
int lastRowIndex=sheet.getLastRowNum();
//可以通过for循环遍历每一行的数据再在循环内对列的数据进行处理
for(int i=firstRowIndex;i<=lastRowIndex;i++){
Map<Integer,Object> map=new HashMap<>();
//获取指定行的数据
Row row=sheet.getRow(i);
//获取工作表页中指定行的指定列数据
//当前行的第一个列的数据的下标
int firstCellIndex=row.getFirstCellNum();
//row中一列数据都没有则返回-1,只有第一列有数据则返回-1,最后有数据的列是第n列则返回n
int lastCeeIndex=row.getLastCellNum();
//获取当前下标(列)的单元格数据
for(int j=firstCellIndex;j<lastCeeIndex;j++){
Cell cell=row.getCell(j);
map.put(j,cell);
}
list.add(map);
}
}else{
System.out.println("文件类型错误");
}
return list;
}