打字的小强 发表于 2020-6-11 13:45

爬虫遇到了字符图片混淆。pytesseract识别图片字符

本帖最后由 打字的小强 于 2020-6-11 14:05 编辑

最近爬虫遇到了字符图片混淆的反爬。如图所示,文字和图片混在一起,需要对图片进行识别,图片很小,这时候我就想到了pytesseract,一直知道但是从未去实际操作,今天讲讲基本步骤




一.搭建环境
tesseract是很多语言都可以调用的,简而言之是一个ocr本地识别引擎,所以要装本地环境,并不是pip install 就可以的。并不是python的专利,可以用这个训练自己的库,搭建环境还需要下载简体中文包
下载tesseract-ocr-setup-4.0.0-alpha.20180109.exe进行安装,可以选择安装位置,记住安装位置,我的位置是D:\minitool\Tesseract-OCR

下载简体中文识别库chi_sim.traineddata,放到安装位置的tesseract安装目录下tessdata的文件下


接下来做环境变量的配置,打开我的电脑,右键点击属性,计算机名,域工作组设置点击更改设置,点击高级,点击环境变量。在用户变量里面把tesseract安装目录添加进入path里面,在系统变量添加一个变量名为TESSDATA_PREFIX,变量值为字库存放目录的环境变量

接下来验证是否安装成功了里面输入 tesseract -v,如下图就是安装成功了


二.测试
找到所有的图片使用正则,我要把所有的标签和对应的字符做成一个python字典,后面就好替换
我这里只提供一个测试的例子
def ocrs(names):
    im = cv2.imread(names)
    config = ("-l chi_sim --oem 0 --psm 10")#这些参数要做出说明的
    datas = pytesseract.image_to_string(im, config=config)#调用pytesseract识别,
    if datas:   #判断有没有识别结果
      c_datas = easygui.ccbox(msg='识别结果是' + datas, title=' ', choices=('True', 'false'),
                                 image=names)   #easygui一个询问框,人工确认是否识别正确
      if not c_datas:
            #如果识别不正确,enterbox人工输入,收集最终结果
            datas = easygui.enterbox(msg="请输入正确的字:", title=' ', default=' ', strip=True,
                                     image=names, root=None)
    else:
      # 如果pytesseract识别结果为空,enterbox人工输入,收集最终结果
      datas = easygui.enterbox(msg="请输入正确的字:", title=' ', default=' ', strip=True,
                                    image=names, root=None)
    #返回最终结果。最坏的结果就是人工也没有输入
    return datas
def img_to_string():
    paths = "**********" #填写一个文本的路径,读取本文的信息,这里面有很多的标签
    datas = open(paths, encoding='utf-8')

    pattern = re.compile("<img.*?>")      #找到所有img的正则
    str2 = pattern.findall(datas)   #找到所有的img标签
    for i in str2:
      #现在有很多的img的标签被匹配出来了
      pattern = re.compile("/.*?\\.png")   #正则找到其中的链接,图片文件格式都是png格式
      str3 = pattern.findall(i)      #正则找到其中的链接
      urls = "*********"+str3#*号是这个目标站点的域名,拼装起来,下面requests保存图片
      if urls not in font_list :   #为了防止同一个图片下载很多遍,过滤一下
            font_list.append(urls)   #没有就保存在数组里面,给上面判断
            names = str3   #提取图片的名称,保存文件的地方用
            datass = requests.get(urls,verify=False)#下载图片
            print(urls)
            with open('./verify/' + str(names) + '.png', 'wb') as file:
                file.write(datass.content)   #保存图片的二进制的数据

            result = ocrs('./verify/' + str(names) + '.png')#把文件脚本专门的识别函数识别,返回实际的识别的文字
            if result:
                print(result)
                font_dict=result#有结果就加入字典保存
            else:
                #人工也没有输入的结果
                print("null")
                font_dict = "null"

效果图字库标记少,几十个文件公用20多个字,可以这样弄,先一一把对应关系找出来,在进行替换,下面的替换我就不讲了,写的比较垃圾,哈哈,不献丑了。下图就是效果,所有识别过都会记录到字典:



补充:
pytesseract调用的时候参数说明,这些参数我调了很久都没有准确的,完美的,后面只好做弹窗确认,我们的图片很小,只有一个字符。
--psm 10 这就是把整个图当一个字符来识别
--oem 0 旧的引擎,一共有四种,都试了,这种比较准
把参数列给大家看下
OCR选项:

--tessdata dir PATH指定tessdata PATH的位置。

--用户字路径指定用户字文件的位置。

--用户模式路径指定用户模式文件的位置。

--dpi值指定输入图像的dpi。

-l LANG[+LANG]指定用于OCR的语言。

-c VAR=配置变量的值设置值。

允许多个-c参数。

--psm NUM指定页面分段模式。

--oem NUM指定OCR引擎模式。

注意:这些选项必须在任何配置文件之前出现。



页面分割模式:

仅限0方向和脚本检测(OSD)。

1个带有OSD的自动页面分割。

2自动页面分割,但没有OSD或OCR。(未实施)

3全自动页面分割,但没有OSD。(默认)

4假设一列大小可变的文本。

5假设一个垂直对齐的文本块。

6假设一个统一的文本块。

7将图像视为单个文本行。

8将图像视为一个单词。

9将图像视为一个圆圈中的单个单词。

10将图像视为单个字符。

11稀疏文本。找尽可能多的文本没有特别的顺序。

12带OSD的稀疏文本。

13原始生产线。将图像视为单个文本行,

绕过特定于Tesseract的攻击。



OCR引擎模式:

仅限0旧版引擎。

仅限1台神经网络LSTM发动机。

2个传统+LSTM引擎。

3默认,基于可用的内容。


相关附件
链接:https://pan.baidu.com/s/13Ry_cDnbteIUHMr_33oi4w
提取码:fxfl
三.总结
Tesseract还是很方便的,还可以做一些其他的简单的验证码识别,网上也有很多的例子。一开始弄了半天,因为参数的问题,一直没有返回值,本来是想接入腾讯或者百度的第三方接口来识别的,结果发现并没有多少字。最后来在使用过程中加了一个群,里面还是有很多的其他用法,还可以用Tesseract训练出自己的字库,又涨见识了。

hong_sun 发表于 2020-6-11 14:00

没用过这个,支持!

Light紫星 发表于 2020-6-11 14:06

这个也可以用来识别验证码吗

打字的小强 发表于 2020-6-11 14:34

Light紫星 发表于 2020-6-11 14:06
这个也可以用来识别验证码吗

可以的,百度有很多例子

Capitalwell 发表于 2020-6-11 14:57

感谢楼主技术贴分享,很详细

zdnyp 发表于 2020-6-11 15:52

可以把采集源地址发一下嘛,学习一下

打字的小强 发表于 2020-6-11 16:05

zdnyp 发表于 2020-6-11 15:52
可以把采集源地址发一下嘛,学习一下

哈哈,保密
页: [1]
查看完整版本: 爬虫遇到了字符图片混淆。pytesseract识别图片字符