图表识别并保存数据

  1. 利用阿里云接口“印刷文字识别”识别图表。地址:https://market.aliyun.com/products/57124001/cmapi024968.html

  1. 相关接口

  1. 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();
        }
    }
}
  1. 返回结果

支持三种格式输出: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
      ]
   ]
}
失败返回示
  1. 上面获取的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 "指定路径下生成文件成功!";
}
  1. 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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞流银河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值