版权
本文首发于soarli博客,转载请注明来源。传送门
配置Typecho
文本识别能力项目实战笔记,内容原创,转载请注明来源!
前言
早在去年参与苹果iOS 15
内测中体验其在全局融入的文字识别能力以及相册场景文本搜索功能时,我就想给自己的博客也实现搜索图片中所含文本的功能。受限于当时的时间和技术条件,这个想法一直处于“挂起”状态。
恰好上个月微信在其新版本也发布了聊天内容中的图片文本搜索功能。刚好寒假期间对PaddlePaddle
深度学习框架做了些许研究并在本地部署了OCR
项目。择日不如撞日,昨天晚上一口气把这套“前端”逻辑以Python
脚本的形式实现了出来。
程序代码已公开,可能存在不足之处与优化空间,希望各位大佬能在看过本文后不吝赐教。
配置
新增Typecho
数据表字段:
ALTER TABLE `typecho_contents` ADD `ocr` TEXT NULL AFTER `views`;
修改Typecho
搜索逻辑(1189行):
安装用到的Python
包
pip3 install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
代码
其中xxxxx
应换为自己的对应信息:
# -*- coding: utf-8 -*-
# @Author : soarli
# @Date : 2021/4/6
from datetime import datetime
import os
import time
import requests
import re
import pymysql
# <功能选项>
# 是否更新所有信息的OCR结果(False则仅对未OCR的文章执行OCR操作)
updateAll = False
# 处理每张图片请求后的冷却时间(秒,防止因频次限制导致漏掉部分图片)
cool = 5
# <数据库及网站配置相关信息>
# 数据库地址
host = 'xxxxx'
# 数据库用户名
user = 'xxxxx'
# 数据库密码
password = 'xxxxx'
# 数据库名
database = 'xxxxx'
# 博客域名
target = 'https://xxxxx.xxxxx.xxx/'
# <全局变量>
# OCR接口地址
url = "https://xxxxx.xxx/xxxxx"
# 全局请求头
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36','referer':target}
upload_data = {"name": "1.jpg", "type": "image/jpeg"}
# 维护数据库连接状态
def keepAlive():
cur = conn.cursor()
sql = "SELECT ocr FROM `typecho_contents` WHERE cid=1"
cur.execute(sql)
# 输入markdown文本,输出其中引用图片中的文字结果
def getPageOCRText(text):
pic_list = re.findall(r"\!\[.*\]\((.+)\)",text)
this_text = ''
for i in pic_list:
try:
img = {'file':requests.get(i,headers=headers).content}
img_text = requests.post(url, upload_data, files=img)
this_text += img_text.text
time.sleep(cool)
# 维护数据库连接状态
keepAlive()
# print(this_text)
except Exception as e:
print('Error msg: ' + str(e))
ocrtext = this_text.replace("\n","").replace('\'','\\\'').replace('\"','\\\"').replace('-','\-')
if(ocrtext == ''):
ocrtext = 'none!'
return ocrtext
# 返回需要进行ocr操作的cid(直接传入下一个函数)
def getUnOCRedCid():
cur = conn.cursor()
if(updateAll):
sql = "SELECT cid FROM `typecho_contents` WHERE 1"
else:
sql = "SELECT cid FROM `typecho_contents` WHERE ocr is NULL"
try:
cid_list = []
cur.execute(sql)
alldata = cur.fetchall()
for rec in alldata:
cid_list.append(rec[0])
except Exception as e:
print('Error msg: ' + str(e))
return getText(cid_list)
# 获取cid列表中逐条cid对应的markdown内容并逐条调用ocr获取结果
def getText(cid_list):
for i in cid_list:
cur = conn.cursor()
sql = "SELECT text FROM `typecho_contents` WHERE cid=%s" % (i)
try:
cur.execute(sql)
text = cur.fetchall()[0]
except Exception as e:
conn.rollback()
print('Error msg: ' + str(e))
# print(type(text))
print('='*50)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
print(i) # cid
ocr_text = getPageOCRText(text[0]) # 去换行后的整篇图片OCR文本
print(ocr_text)
writeOCRText(ocr_text, i) # 入库
# 将识别到的结果写入数据表的ocr字段
def writeOCRText(text, cid):
cur = conn.cursor()
sql = "UPDATE `typecho_contents` SET `ocr` = '%s' WHERE `typecho_contents`.`cid` = %s" % (text,cid)
try:
cur.execute(sql)
conn.commit()
except Exception as e:
conn.rollback()
print('Error msg: ' + str(e))
if __name__ == '__main__':
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+'开始运行')
# 连接数据库
conn = pymysql.connect(host=host, user=user, password=password, database=database)
# 获取需要进行ocr操作的文章cid,其会调用getText,getText又会逐条调用getPageOCRText对markdown text引用的逐张图片进行OCR操作,返回的合成文本又会调用writeOCRText写回数据库的ocr字段
getUnOCRedCid()
# 断开数据库
conn.close()
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+'运行完毕')
执行
经过本地的反复测试与修正,本程序于4月6日凌晨3点左右在我的blog
服务器正式运行,并于当天晚上9点左右运行完毕。期间OCR
服务器(我的另一台腾讯云)的CPU
一直处于满载状态:
数据
看了看博客数据库中ocr
字段总字符数:
SELECT sum(length(ocr)) FROM `typecho_contents`
我这三百多篇文章中的所有图片竟然识别出近两百万文字,真的有被吓到:
效果
选了6个关键词,分别截图对比了OCR程序首次执行前后的搜索结果。
识别完成之前:
识别完成之后:
定时
如果数据库中没有文章更新,程序几乎在开始运行瞬间即可运行完毕。
考虑到OCR
服务器的业务压力,程序的自动执行周期设置到了每天夜里。
先执行一次,看看效果:
完美搞定!
其他
不算不知道,一算吓一跳!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iFBzmkWy-1649275764690)(https://cdn.soarli.top/img/20220407020109.png?x-oss-process=style/soarli)]
webp
格式下的我的全站图片平均每张仅占40KB
的大小!
Google yyds!
参考资料:
https://blog.bossdong.cn/411.html
https://blog.csdn.net/qq_44754132/article/details/104418657
https://www.begtut.com/python/ref-requests-post.html
https://blog.csdn.net/weixin_40006779/article/details/109940125
https://blog.csdn.net/weixin_40394560/article/details/116269688
https://blog.csdn.net/itguangzhi/article/details/107501813
https://www.runoob.com/python/att-string-split.html
https://blog.csdn.net/qq_38276669/article/details/81329752
https://www.jianshu.com/p/801750d5a735
https://blog.csdn.net/m0_37696990/article/details/105925940
https://blog.csdn.net/menglinjie/article/details/78539022
https://blog.csdn.net/hhyygg2009/article/details/102844607
https://blog.csdn.net/weixin_50990952/article/details/111796512
https://www.php.cn/python-tutorials-462304.html