文档智能的社会效益
在大规模社会性突发事件背景下,由于传播渠道有限和实时性要求,处于困境中的个人往往会在公开社交媒体上发布求助信息;
这种信息的格式通常是:何时何地何人需要何种帮助,
尤其是时间、地点这两个关键信息非常重要,时间可以用来记录存档和判断信息是否过期,假如没有地点信息,就好比消防队员不知道去哪救火、红十字会不知道去哪发放物资...
每逢这种背景,通常有这样的监控系统出现,实时采集各大平台中的相关话题的求助信息,智能解析信息后给予当事人及时的救助。
例如从一段微博文本中,提取时间、地点、人物、联系电话等关键信息,
但是信息不都是纯文本,特别是在这样一个信息过载的时代,越来越多的人选择发图片文字,这样一种更加直观易读的方式。
所以在从文本中提取结构性信息前,还需要增加一步 OCR 处理,一种将输入、手写或印刷体文本从图片转换为机器编码文本的基础技术。
这两个标准步骤,不仅在社会救助实践上大有可为,而且在不少应急管理的科研课题上提供技术支撑。
几年前我如何做内容文档抽取
我几年前的时候,就给老师做过这样一个科研项目,有关 2021 河南暴雨事件,采集一个河南暴雨互助超话下的所有微博,并下载所有图片,然后利用 OCR 提取图片中的数据,交给下游任务处理。
当时好像用的是 Tesseract OCR 框架处理图片转文本,再使用从改编的算法从文本中提取信息,不仅流程长,依赖多,精确率有待提高。
当今腾讯云的智能文档抽取
但是现在是2025年了,刚好看到腾讯云出了文档智能产品,官网是这样宣传的:
具备全面的行业覆盖能力,能精确识别包括卡证、物流单据、工业标签、服务合同及医疗报告在内的多种文件。
听这名字,不仅 OCR,而且文档抽取,敢情是把上面两个步骤一步到位了?
说干就干,于是我参考在腾讯云 OCR 文档,折腾了下,果真如此,特此记录分享出来。
现在的我们可以怎么做智能文档抽取
获取 SecretId 和 SecretKey
为了保护隐私,我将使用下面这个文本图片(demo.jpg)作为演示,提取图片中的时间、地点等结构信息,
文本本身不具有真实性,仅供测试。

第一步,需要先在腾讯云开通文档智能服务,开通控制台和文档都在下面这个链接,现在开通还有免费额度赠送,
https://cloud.tencent.com/product/doc-ai
按照文档中的最佳实践操作,需要注意的是,为了资源安全,最好开通一个子账号,
因为腾讯云所有的产品默认都可以由主账号的一个
SecretId
和 SecretKey
控制,这很危险,不小心被别人拿到开通各种付费服务就麻烦了。所以推荐创建一个子账号,然后只授权这个子账号
QcloudOCRReadOnlyaccess
这一个文字识别只读访问权限,只允许访问文字识别所有读接口,包含调用所有 OCR 接口、允许查看所有账号用量等;在下面这个页面可以开通子账号:
https://console.cloud.tencent.com/cam
授权后在这个子账号下新建一个 API 密钥,注意在新建时保存
SecretId
和 SecretKey,SecretKey
只在创建时可见可复制。拿到
SecretId
和 SecretKey
后,第一步就算完成了。使用 Python 请求服务
首先安装腾讯云最新版本的 Python SDK:
pip install --upgrade tencentcloud-sdk-python
然后使用下面这份代码,坑我踩了,0 报错 0 警告,拿去用即可。
// step 1 初始化 SDK Auth Clientdef initClient():# 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密# 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。cred = credential.Credential("替换成您自己的 SecretId", "替换成您自己的 SecretKey")# 实例化一个http选项,可选的,没有特殊需求可以跳过http_profile = HttpProfile()http_profile.endpoint = "ocr.tencentcloudapi.com"# 实例化一个client选项,可选的,没有特殊需求可以跳过client_profile = ClientProfile()client_profile.httpProfile = http_profile# 实例化要请求产品的client对象,clientProfile是可选的client = ocr_client.OcrClient(cred, "", client_profile)return client
由于调用服务需要把二进制图片转成 Base64 字符串,下面是两个工具函数。
def getFileContent(file_path):with open(file_path, 'rb') as fp:return fp.read()def imageToBase64(image_path):# 读取图片文件的二进制数据binary_data = getFileContent(image_path)# 使用 base64 编码二进制数据base64_encoded_data = base64.b64encode(binary_data)# 将 base64 编码的二进制数据转换为字符串base64_message = base64_encoded_data.decode('utf-8')return base64_message
构建文档抽取(多模态版)请求,并且获得响应:
def buildTencentSmartStructuralOCRV2(image_file_path):try:client = initClient()# 实例化一个请求对象,每个接口都会对应一个request对象req = models.SmartStructuralOCRV2Request()params = {"ImageBase64": imageToBase64(image_file_path),"ItemNames": ["日期", "地点"],"ReturnFullText": False}req.from_json_string(json.dumps(params))# 返回的resp是一个SmartStructuralOCRV2Response的实例,与请求对象对应resp = client.SmartStructuralOCRV2(req)# 输出json格式的字符串回包print(resp.to_json_string())return json.loads(resp.to_json_string())except TencentCloudSDKException as err:print(err)return None
参数
ItemNames
指明了我们需要解析的文本字段列表,您也可以尝试更多的一些字段,SDK 给我们的响应输出是一个字符串,在此我把它转成了 JSON 格式,方便后续的响应解析,获得我们目标数据。
传入上文的测试文本图片 demo.jpg,输出内容如下:
{"Angle": -0.02881504036486149,"StructuralList": [{"Groups": [{"Lines": [{"Key": {"AutoName": "日期","ConfigName": null},"Value": {"AutoContent": "2025年1月5日","Coord": {"LeftTop": {"X": 457,"Y": 86},"RightTop": {"X": 774,"Y": 85},"RightBottom": {"X": 774,"Y": 157},"LeftBottom": {"X": 457,"Y": 158}}}}]}]},{"Groups": [{"Lines": [{"Key": {"AutoName": "地点","ConfigName": null},"Value": {"AutoContent": "圣丹市丹塔县星域镇未名村","Coord": {"LeftTop": {"X": 249,"Y": 956},"RightTop": {"X": 1181,"Y": 955},"RightBottom": {"X": 1181,"Y": 1035},"LeftBottom": {"X": 249,"Y": 1036}}}}]}]}],"WordList": [],"RequestId": "月小水长 buyixiao 的 RID"}
Angle 是图片相对于水平的旋转角度,文本的水平方向为 0,顺时针为正,逆时针为负;
AutoName 是我们传入的待解析字段,对应的 AutoContent 就是解析的字段值;
X 和 Y 就是文本在图片中的位置边框,其四个点的坐标。
所以下面的我们的目标就是解析所有的 AutoContent了。
解析响应获取目标结果
看起来这个 JSON 一点也不规则,不能直接清晰地通过下标或者键名获取想要的结果,
当然可以选择诸如
json["StructuralList"][0]["Groups"][0]["Lines"]
之类的 ugly 写法,但是这样看起来不易读不好维护,而且不一定通用,就能清楚地知道,本文解析任务也类似,都可以通过设计递归算法简化之,
递归解析引擎我写好了,测试通过,拿去用即可。
def parseEntity(resp_json):entity_collected = {}def recurse_seek(obj):if isinstance(obj, dict):if "Key" in obj.keys() and "AutoName" in obj["Key"] and \\"Value" in obj.keys() and "AutoContent" in obj["Value"]:entity_collected[obj["Key"]["AutoName"]] = obj["Value"]["AutoContent"]else:for key, value in obj.items():if isinstance(value, list):for vv in value:recurse_seek(vv)elif isinstance(obj, list):for item in obj:recurse_seek(item)if resp_json:recurse_seek(resp_json)return entity_collected
最终输出的结果如下:
{'日期': '2025年1月5日', '地点': '圣丹市丹塔县星域镇未名村'}
运行代码的注意事项
新建一个 py 文件,
1. 需要导入的包如下,复制到文件最前面。
import base64import jsonfrom tencentcloud.common import credentialfrom tencentcloud.common.profile.client_profile import ClientProfilefrom tencentcloud.common.profile.http_profile import HttpProfilefrom tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKExceptionfrom tencentcloud.ocr.v20181119 import ocr_client, models
2. 接着复制上面所有的工具函数、请求函数、解析函数(JSON 输出不要复制了)。
3. 最后复制调用入口,demo.jpg 放到和 py 文件一个目录下,就能完整运行起来了。
if __name__ == '__main__':response_json = buildTencentSmartStructuralOCRV2(image_file_path='./demo.jpg')entity_dict = parseEntity(response_json)print(entity_dict)
总结
腾讯云文档智能给 OCR 提取和结构信息提取提供了新的选择,而且产品和文档都做得比较好,有需要的朋友们可以动手试试,我仅小小抛砖引玉了下,其实这个产品还有其他更多强大功能可以探索,在大模型能力的加持下,想象空间很大,我在官方文档找到了如下表述:
即便在版式多变或中英文混排的情形下,仍可维持高识别精度。
借助多模态大模型技术构建键值对应关系,支持客户个性化模板定制,提升数据提取录入效率,
适用于政务处理、票据核销、行业表单填写、国际物流管理、人寿保险理赔、AI 在线问诊、律师事务所合同审查及供应链合同审核等多种应用场景。
所以,海阔天空,不妨一试~