图片验证码识别接口

一、效果演示:http://www.bhshare.cn/imgcode/demo.html

  1. 本地图片识别


    本地上传识别.png
  2. 网络图片识别


    网络图片识别.png

二、免费api接口

接口地址:http://www.bhshare.cn/imgcode/

请求类型:post

数据格式:application/x-www-form-urlencoded

接口参数:

参数名 类型 是否必需 备注
token String 用户标识(token 免费获取:http://www.bhshare.cn/imgcode/gettoken
type String 识别类型。”online“:网络图片识别,”local“:本地图片上传
uri String 在线图片网址或图片base64编码(含头部信息),当type取online时生效
file file 本地图片文件,当type取local时生效

返回数据:

数据格式:json

参数名 类型 备注
code int 状态码。200:识别成功,其他:识别失败
msg String 错误提示信息。当code不等于200时才有意义
data String 识别结果
  1. python实现
# -*- coding: utf-8 -*-
# @Date    : 2021/10/03
# @Author  : 薄荷你玩
# @Website :http://www.bhshare.cn

import json
import requests

TOKEN = 'free'  # token 获取:http://www.bhshare.cn/imgcode/gettoken
URL = 'http://www.bhshare.cn/imgcode/'  # 接口地址


def imgcode_online(imgurl):
    """
    在线图片识别
    :param imgurl: 在线图片网址 / 图片base64编码(包含头部信息)
    :return: 识别结果
    """
    data = {
        'token': TOKEN,
        'type': 'online',
        'uri': imgurl
    }
    response = requests.post(URL, data=data)
    print(response.text)
    result = json.loads(response.text)
    if result['code'] == 200:
        print(result['data'])
        return result['data']
    else:
        print(result['msg'])
        return 'error'


def imgcode_local(imgpath):
    """
    本地图片识别
    :param imgpath: 本地图片路径
    :return: 识别结果
    """
    data = {
        'token': TOKEN,
        'type': 'local'
    }

    # binary上传文件
    files = {'file': open(imgpath, 'rb')}

    response = requests.post(URL, files=files, data=data)
    print(response.text)
    result = json.loads(response.text)
    if result['code'] == 200:
        print(result['data'])
        return result['data']
    else:
        print(result['msg'])
        return 'error'


if __name__ == '__main__':
    imgcode_online('http://www.bhshare.cn/test.png')

    imgcode_local('img/test.png')

    # 输出样例:
    # {'code': 200, 'msg': 'ok', 'data': '74689'}
    # 74689
    
  1. Java实现
 /**
  * @author 薄荷你玩
  * @date 2021/10/04
  * @Website http://www.bhshare.cn
  */
 
 import java.io.BufferedReader;
 import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.Map.Entry;
 import javax.imageio.ImageIO;
 import javax.imageio.stream.ImageInputStream;
 
 
 public class ImgcodeUtil {
 
     private static final String URL = "http://www.bhshare.cn/imgcode/"; //接口地址
     private static final String TOKEN = "free"; // token 获取:http://www.bhshare.cn/imgcode/gettoken
 
     private final static String BOUNDARY = UUID.randomUUID().toString().toLowerCase().replaceAll("-", "");// 边界标识
     private final static String PREFIX = "--";// 必须存在
     private final static String LINE_END = "\r\n";
 
 
     /**
      * 网络图片识别
      *
      * @param imgUrl 图片网址/图片base64编码
      * @return 服务器返回结果(json格式)
      */
     private static String imgcode_online(String imgUrl) {
         String BOUNDARY = UUID.randomUUID().toString(); // 文件边界随机生成
         HttpURLConnection con = null;
         BufferedReader buffer = null;
         StringBuffer resultBuffer = null;
         try {
             URL url = new URL(URL);
             //得到连接对象
             con = (HttpURLConnection) url.openConnection();
             //设置请求类型
             con.setRequestMethod("POST");
             //设置请求需要返回的数据类型和字符集类型
             con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
 
             //允许写出
             con.setDoOutput(true);
             //允许读入
             con.setDoInput(true);
             //不使用缓存
             con.setUseCaches(false);
             DataOutputStream out = new DataOutputStream(con.getOutputStream());
             String content = "token=" + TOKEN;
             content += "&type=online";
             content += "&uri=" + URLEncoder.encode(imgUrl);
             // DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写到流里面
             out.writeBytes(content);
             out.flush();
             out.close();
             //得到响应码
             int responseCode = con.getResponseCode();
             if (responseCode == HttpURLConnection.HTTP_OK) {
                 //得到响应流
                 InputStream inputStream = con.getInputStream();
                 //将响应流转换成字符串
                 resultBuffer = new StringBuffer();
                 String line;
                 buffer = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                 while ((line = buffer.readLine()) != null) {
                     resultBuffer.append(line);
                 }
                 return resultBuffer.toString();
             }
 
         } catch (Exception e) {
             e.printStackTrace();
         }
         return "";
     }
 
     /**
      * 本地图片上传
      *
      * @param path 图片路径
      * @return 返回数据(json)
      */
     public static String imgcode_local(String path) throws Exception {
         HttpURLConnection conn = null;
         InputStream input = null;
         OutputStream os = null;
         BufferedReader br = null;
         StringBuffer buffer = null;
         try {
             URL url = new URL(URL);
             conn = (HttpURLConnection) url.openConnection();
 
             conn.setDoOutput(true);
             conn.setDoInput(true);
             conn.setUseCaches(false);
             conn.setConnectTimeout(1000 * 10);
             conn.setReadTimeout(1000 * 10);
             conn.setRequestMethod("POST");
             conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
 
             conn.connect();
 
             // 往服务器端写内容 也就是发起http请求需要带的参数
             os = new DataOutputStream(conn.getOutputStream());
             // 请求参数部分
             Map requestText = new HashMap();
             requestText.put("token", TOKEN);
             requestText.put("type", "local");
             writeParams(requestText, os);
             // 请求上传文件部分
             writeFile(path, os);
             // 请求结束标志
             String endTarget = PREFIX + BOUNDARY + PREFIX + LINE_END;
             os.write(endTarget.getBytes());
             os.flush();
 
             // 读取服务器端返回的内容
             if (conn.getResponseCode() == 200) {
                 input = conn.getInputStream();
             } else {
                 input = conn.getErrorStream();
             }
             br = new BufferedReader(new InputStreamReader(input, "UTF-8"));
             buffer = new StringBuffer();
             String line = null;
             while ((line = br.readLine()) != null) {
                 buffer.append(line);
             }
         } catch (Exception e) {
             throw new Exception(e);
         } finally {
             try {
                 if (conn != null) {
                     conn.disconnect();
                     conn = null;
                 }
                 if (os != null) {
                     os.close();
                     os = null;
                 }
                 if (br != null) {
                     br.close();
                     br = null;
                 }
             } catch (IOException ex) {
                 throw new Exception(ex);
             }
         }
         return buffer.toString();
     }
 
     /**
      * 对post参数进行编码处理并写入数据流中
      *
      * @throws Exception
      * @throws IOException
      */
     private static void writeParams(Map requestText, OutputStream os) throws Exception {
         try {
 
             StringBuilder requestParams = new StringBuilder();
             Set set = requestText.entrySet();
             Iterator it = set.iterator();
             while (it.hasNext()) {
                 Entry entry = (Entry) it.next();
                 requestParams.append(PREFIX).append(BOUNDARY).append(LINE_END);
                 requestParams.append("Content-Disposition: form-data; name=\"")
                         .append(entry.getKey()).append("\"").append(LINE_END);
                 requestParams.append("Content-Type: text/plain; charset=utf-8")
                         .append(LINE_END);
                 requestParams.append("Content-Transfer-Encoding: 8bit").append(
                         LINE_END);
                 requestParams.append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容
                 requestParams.append(entry.getValue());
                 requestParams.append(LINE_END);
             }
             os.write(requestParams.toString().getBytes());
             os.flush();
         } catch (Exception e) {
             throw new Exception(e);
         }
     }
 
     /**
      * 对post上传的文件进行编码处理并写入数据流中
      *
      * @throws IOException
      * @path 文件路径
      */
     private static void writeFile(String path, OutputStream os) throws Exception {
         try {
             InputStream is = null;
             File file = new File(path);
             StringBuilder requestParams = new StringBuilder();
             requestParams.append(PREFIX).append(BOUNDARY).append(LINE_END);
             requestParams.append("Content-Disposition: form-data; name=\"")
                     .append("file").append("\"; filename=\"")
                     .append(file.getName()).append("\"")
                     .append(LINE_END);
             requestParams.append("Content-Type:")
                     .append(getContentType(file))
                     .append(LINE_END);
             requestParams.append("Content-Transfer-Encoding: 8bit").append(
                     LINE_END);
             requestParams.append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容
 
             os.write(requestParams.toString().getBytes());
 
             is = new FileInputStream(file);
 
             byte[] buffer = new byte[1024 * 1024];
             int len = 0;
             while ((len = is.read(buffer)) != -1) {
                 os.write(buffer, 0, len);
             }
             os.write(LINE_END.getBytes());
             os.flush();
 
         } catch (Exception e) {
             throw new Exception(e);
         }
     }
 
     /**
      * 获取ContentType
      */
     public static String getContentType(File file) throws Exception {
         String streamContentType = "application/octet-stream";
         String imageContentType = "";
         ImageInputStream image = null;
         try {
             image = ImageIO.createImageInputStream(file);
             if (image == null) {
                 return streamContentType;
             }
             Iterator it = ImageIO.getImageReaders(image);
             if (it.hasNext()) {
                 imageContentType = "image/png";
                 return imageContentType;
             }
         } catch (IOException e) {
             throw new Exception(e);
         } finally {
             try {
                 if (image != null) {
                     image.close();
                 }
             } catch (IOException e) {
                 throw new Exception(e);
             }
 
         }
         return streamContentType;
     }
 
     public static void main(String[] args) throws Exception {
 
         String path = "E:\\NLP_study\\imgcode\\img\\test.png";
         System.out.println(imgcode_local(path));
         System.out.println(imgcode_online("http://www.bhshare.cn/test.png"));
         
         // 输出:
         // {"code":200,"msg":"ok","times":93,"data":"yemm"}
         // {"code":200,"msg":"ok","times":92,"data":"74689"}
     }
 }
  1. HTML/JavaScript实现

    网络图片识别:

 <!--网络图片识别/html-->
 <input type="text" name="uri" id="uri" placeholder="请输入验证码图片网址" />
 <input type="button" onclick="imgcode()" value="识别" />
 <input name="token" id="token" value="free" type="hidden">
 <input name="type" value="online" type="hidden">
 <p>识别结果:<span id="resultCode" style="color:red;">请稍后...</span></p>
// 网络图片识别/js
function imgcode() {
        if ($("#uri").val() == "") {
            alert("网址不能为空");
            return;
        }
        $.ajax({
            type: "post",
            url: "http://www.bhshare.cn/imgcode/",
            data: {
                token: $("#token").val(),
                uri: $("#uri").val(),
                type: "online"
            },
            dataType: "json",
            success: function (data) {
                console.log(data);
                if (data.code > 0) {
                    $("#resultCode").text(data.data);
                } else {
                    $("#resultCode").text(data.msg);
                }
            },
            error: function (result) {
                console.log(result);
                $("#resultCode").text(JSON.stringify(result));
                alert("系统繁忙,请稍后再试!");
            }

        });
    }

本地图片上传:

<!--本地图片上传/html-->
<form encType="multipart/form-data" method="post" id="selPicture">
 <input type="file" accept="image/*" name="selPicture" id="file" />
    <input type="button" name="upload" onclick="sendimg()" id="upload" value="识别" />
    <input name="token" value="free" type="hidden">
    <input name="type" value="local" type="hidden">
</form>
<p>识别结果:<span id="resultCode" style="color:red;">请稍后...</span></p>
// 本地图片上传/js
function sendimg() {
        var $file1 = $("input[name='selPicture']").val();//用户文件内容(文件)
        // 判断文件是否为空
        if ($file1 == "") {
            alert("请选择上传的目标文件! ")
            return false;
        }
        //判断文件大小
        var size1 = $("input[name='selPicture']")[0].files[0].size;
        if (size1 > 5242880) {
            alert("上传文件不能大于5M!");
            return false;
        }

        boo1 = true;
        var type = "file";
        var formData = new FormData($("#selPicture")[0]);//这里需要实例化一个FormData来进行文件上传
        $.ajax({
            type: "post",
            url: "http://www.bhshare.cn/imgcode/",
            data: formData,
            processData: false,
            contentType: false,
            dataType: "json",
            success: function (data) {
                console.log(data);
                if (data.code == 200) {
                    $("#resultCode").text(data.data);
                } else {
                    $("#resultCode").text(data.msg);
                }
            },
            error: function (result) {
                console.log(result);
                $("#resultCode").text(JSON.stringify(result));
                alert("系统繁忙,请稍后再试!");
            }

        });
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容