zoukankan      html  css  js  c++  java
  • php抓取图片进行内容提取解析,文字性pdf进行内容文字提取解析

    2018年7月7日18:52:17

     php是用纯算法,自己是提取图片内容不是不行,可以但是优化起来很麻烦还得设计学习库,去矫正数据的正确率

    对于大多数项目来说,如果不是做ocr服务,就不必要做需求工具或者接口

    一,

    先说工具 tesseract-ocr/tesseract 目前没有时间测试,全套东西,学习难度不大,需要的训练数据,支持多国语言

    https://github.com/ShuiPingYang/tesseract-ocr-for-php

    官方网站 http://tesseract-ocr.repairfaq.org

    整一套到实际项目起码的一个月差不多,成熟的还得几个月的线上数据训练,差不多就OK了

    二,

    去购买其他成熟的平台的api,目前测试过的百度的图片识别api,通用文字高精度版,测试过几张稍复杂的图片还不错,返回的不是纯text

    返回的是数组,还行,对于不规则的表格,文本后面再说处理方法,

    我现在项目的使用的就是这个,官网http://ai.baidu.com/  500/天 是免费的,方便测试

    还有一个就是https://ai.qq.com/ 腾讯的 这个注册了但是还没有测试,

    当然还有阿里云的,但是也属于没测试过,

    都有各种语言的demo包

    提取的百度api的demo

    /*
         * 百度OCR
         * $data 传进来是图片的二进制数据
         * $type = 1 通用文字识别 50000次/天免费 
         * $type = 2 通用文字识别(高精度)500次/天免费
         * $type = 3 网络图片文字识别 500次/天免费
         * $type = 4 身份证识别 500次/天免费
         * $type = 5 银行卡识别 500次/天免费
         * 
         * 说明 通用文字识别(高精度)识别度可以建议使用这个
         */
    
        public static function baidu_ai($image = '', $type = 2) {
            if (empty($image)) {
                throw new Exception('图片二进制数据不能为空');
            }
    
            $AppID = '';
            $API_Key = '';
            $Secret_Key = '';
    
            if ($type == 1) {
    //            通用文字识别
                $url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic';
            } elseif ($type == 2) {
                //通用文字识别(高精度版
                $url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic';
            } elseif ($type == 3) {
                //网络图片文字识别
                $url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/webimage';
            } elseif ($type == 4) {
                //身份证识别
                $url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/idcard';
            } elseif ($type == 5) {
                //银行卡识别
                $url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/bankcard';
            } else {
                throw new Exception('$type 类型错误');
            }
            //获取token 有效时长30天,存redis
            $baidu_key = 'BAIDU_TOKET';
            if (Redis::ttl($baidu_key) < 360) {
                $data['grant_type'] = 'client_credentials';
                $data['client_id'] = $API_Key;
                $data['client_secret'] = $Secret_Key;
                $access_token_url = 'https://aip.baidubce.com/oauth/2.0/token';
                $result = self::post($access_token_url, $data);
                if ($result['code'] != 200) {
                    throw new Exception('授权出错');
                }
    
                Redis::set($baidu_key, $result['content']);
                Redis::expire($baidu_key, 29 * 24 * 3600);
            }
            $baidu_token = Redis::get($baidu_key);
            $baidu_token = json_decode($baidu_token, true);
    
            $access_token = $baidu_token['access_token'];
    
            $request_data['image'] = base64_encode($image);
            $request_url = $url . "?access_token={$access_token}&aipSdk=php&aipSdkVersion=2_2_2";
            $data_result = self::post($request_url, $request_data);
            if ($data_result['code'] != 200) {
                throw new Exception('接口请求出错');
            }
            return $data_result['content'];
        }
    
        public static function post($url = '', $data = [], $headers = []) {
            if (empty($url) || empty($data)) {
                throw new Exception('请求URL和数据都不能为空');
            }
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($data) ? http_build_query($data) : $data);
            curl_setopt($ch, CURLOPT_TIMEOUT_MS, 60000);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 60000);
            $content = curl_exec($ch);
            $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
            if ($code === 0) {
                throw new Exception(curl_error($ch));
            }
    
            curl_close($ch);
            return array(
                'code' => $code,
                'content' => $content,
            );
        }

    三,

    纯算法提取,算了

    pdf解析内容

    目前解析文字性pdf的php,效果还不错,但是解析出来是纯文本,是不规则数据,

    https://github.com/smalot/pdfparser  php的库

    文字识别率和效率都还不错

    项目demo代码

    composer require smalot/pdfparser
    use SmalotPdfParserParser;
    
    
    public static function parsing_pdf() {
     $parser = new Parser();
            $pdf = $parser->parseFile('http://www.yafco.com.hk/asp_bin/newimg/1523872385.pdf');
    //        pp($pdf);
            $text = $pdf->getText();
            $result = json_encode($text, JSON_UNESCAPED_UNICODE);
    }

    图片性的pdf更麻烦,还得切成一页的图片然后再去ocr

    说点数据提取的一点点心得

     比如我获取某些网站发布的pdf文件进行部分数据的提取

    首先我建议提取的pdf原始文本,进行json吧制表符转换成实体,记住不要把中文不要转码

    json_encode( '中文', JSON_UNESCAPED_UNICODE );

    利用制表符,        等作为分隔符,然后就是肉眼看到貌似很规则的pdf格式

    其实解析完,你会发现一点都不规则,如果你没处理过,你会使用分割完的数组进行key的偏移进行定位你需要的位置的文本

    但是,你不能使用不可穷尽的匹配位置的去获取数据

    所以利用一点小方法就可以轻松获取数据,而且也不用写得极其的多的代码去匹配数据位置

    方法1:

    比如你的pdf文件数据大致的位置都是固定,但是解析出来的文本不规则的,可以进行数据块进行分割成一块一块的,如果你需要某块 的一部分数据,你就直接写稍微多3-4个

    方法,去匹配位置就ok了,就不用去全文的匹配位置,麻烦少了很多,原则就是大块文本分小块,分块分次处理,进行全局匹配位置太麻烦,而且全局匹配可能你都没办法对复杂一点的pdf无法处理

    方法2:

    使用nlp接口去分析文本,百度ai的文本分析说使用只是把各种算法实现了,提供了接口,但是不是提供完整的功能,比如文本块分析

    腾讯ai 也提供了。但是最大字符只有1024个字符,所以就直接放弃了,一页文本经常好几千个字,基本无实用性,如果你有小块文本需要提取的可以试试这个接口

    方法3:

    hadoop,但是貌似也没有直接数据清洗和数据提取的工具,如果你需要进行很多的数据的分析,还是得上这个生态

    本文还会时不时继续更新

  • 相关阅读:
    bzoj3757 苹果树
    bzoj2743 [HEOI2012]采花
    bzoj4241 历史研究
    bzoj4448 [Scoi2015]情报传递
    bzoj3295 [Cqoi2011]动态逆序对
    bzoj4034 [HAOI2015]T2
    bzoj3339 Rmq Problem
    BZOJ 1017 魔兽地图
    BZOJ 1021 循环的债务
    SUOI #37 清点更多船只
  • 原文地址:https://www.cnblogs.com/zx-admin/p/9263212.html
Copyright © 2011-2022 走看看