专栏首页wangweijun无法复制PDF的文字内容?只能说你没有看过这篇文章

无法复制PDF的文字内容?只能说你没有看过这篇文章

突发奇想

先说说我为什么要写这篇文章,在这之前,我遇到了一个问题,就是复制不了PDF的文字内容,而我偏偏又想获取到。 我尝试了很多办法,先是将PDF转成Word文档,这样就可以从文档中把内容复制出来了,但是这些格式转换的工具基本都收费,自然就不用再考虑了。 我还想过将要复制的文字部分截图下来,然后发到手机上,通过手机QQ的提取文字内容功能将文字提取出来然后复制:

效果很好,也实现了我的需求,但是未免太麻烦了,要截图,还要发到手机上,于是我陷入了深深的思考,我能不能自己实现这样的功能呢?

学编程为了什么,就是解决问题嘛,所以,我考虑了一下,QQ是如何实现这个功能的。毫无疑问,是文字识别,通过一张图片,然后识别图片里的文字,最后显示出来。

准备工作

搞清楚原理之后,就要解决该如何实现文字识别呢?自己实现显然不现实,自己也不会啊,在百度上搜索了一下,我决定使用百度提供的文字识别API。为了使整个过程变得简便,最终决定使用Python语言实现整个过程。

申请百度识别API

我们先来申请一下百度的文字识别API。 百度搜索百度AI开放平台:

点第一个官方链接,进去后点击控制台:

然后会让你注册,有账号的话登录就可以了,登录之后就可以看到控制台,点击左侧导航栏中的文字识别:

然后点击创建应用,信息随便填一填就好了,我这里已经创建好了:

创建好了就先放着,这三个数据到后面是有用的。

模块介绍

在写代码之前,我得先介绍一下要使用的模块,先来说说我想实现的功能: 首先通过截图(QQ截图、微信截图、电脑自带的截图工具都可以)截取需要的文字内容,然后将图片保存到电脑中,接着通过文字识别把图片中的文字进行提取,最后输出。 先给大家看看效果:

大致功能就是这样,大家也可以根据自己的想法进行拓展。

keyboard

先来介绍一下keyboard模块,因为我们要直接获取到截图的图片,肯定不能自己去保存,那样太麻烦,我们要截图完成后自动将图片进行保存,所以我们先监听到键盘的输入。 先安装keyboard模块,在cmd窗口执行指令:

pip install keyboard

来体验一下这个模块。

import keyboard

keyboard.wait(hotkey = 's')
print("键盘按下了's'")

通过该模块的wait函数可以等待键盘输入,函数参数表示等待的热键,意思是说当执行该程序后,程序会一直等待,直到你键盘按下了’s’程序才会继续执行。 我们运行该程序,然后按下’s’,运行结果如下:

键盘按下了's'

学会了这个,接下来的事情就很简单了,我这里用的是QQ的截图,快捷键为:Ctrl + Alt + A,所以我们要监听该快捷键,代码如下:

import keyboard

print("开始截图")
keyboard.wait(hotkey = 'ctrl+alt+a')
print("键盘按下了'ctrl+alt+a'")
keyboard.wait(hotkey = 'enter')
print("键盘按下了'enter'")
print("结束截图")

运行之后,我们正常执行一次截图操作,看下运行结果:

开始截图
键盘按下了'ctrl+alt+a'
键盘按下了'enter'
结束截图

这样监听截图操作就完成了。

ImageGrab

这是一个非常优秀的图像处理库,我们通过它来保存截取的图片,先安装一下该模块:

pip install Pillow

这是PIL(全程:Pillow)包下的一个模块,所以我们把Pillow包下载好,要用到该模块的一个函数,代码如下:

import keyboard
from PIL import ImageGrab 

print("开始截图")
keyboard.wait(hotkey = 'ctrl+alt+a')
print("键盘按下了'ctrl+alt+a'")
keyboard.wait(hotkey = 'enter')
print("键盘按下了'enter'")

# 保存剪切板快照
image = ImageGrab.grabclipboard()
image.save('screen.png')

print("结束截图")

使用也很简单,先通过keyboard模块的wait函数等待我们截图,当按下enter后截图结束,使用ImageGrab模块的grabclipboard函数将截图获取出来,该函数的功能是抓取当前剪切板的快照,然后封装成image返回,接着用image的save函数进行保存,若只写文件名,则图片将保存在当前目录。

现在我们运行一下项目,然后随意截取一张图片:

虽然这样实现了截图的保存,但细心的同学肯定能发现,第一次截图的时候报错了,然而第二次截图的时候,保存的却是第一次截图的内容,这是为什么呢? 这是因为grabclipboard函数有一个缓存的问题,操作太快,有时候它就会读取上一次的内容,因为第一个没有读取到图像,所以报错了。 问题找到了,该如何解决呢?既然是操作太快导致读取了缓存,那就让它慢一点呗,我们加上一个时间的延迟就可以了,代码修改如下:

import keyboard
from PIL import ImageGrab 
import time

print("开始截图")
keyboard.wait(hotkey = 'ctrl+alt+a')
print("键盘按下了'ctrl+alt+a'")
keyboard.wait(hotkey = 'enter')
print("键盘按下了'enter'")

time.sleep(0.1) # 因为读取截取内容会有一个延迟,导致读取到的是上一次的截图,这里我们主动延迟

# 保存剪切板快照
image = ImageGrab.grabclipboard()
image.save('screen.png')

print("结束截图")

这里在保存剪切板快照之前进行了0.1秒的延迟,就能很好地解决这个问题,使用sleep函数需要导入time模块,下载模块指令:

pip install time

到这里,截取的图片就保存完毕了。

baidu-aip

下面介绍百度的文字识别API。 关于文字识别API的介绍,大家可以查看百度官方的技术文档,我这里只介绍需要使用到的。

AipOcr

AipOcr是OCR的Python SDK客户端,为使用OCR的开发人员提供了一系列的交互方法。

from aip import AipOcr

""" 你的 APPID AK SK """
APP_ID = '你的 App ID'
API_KEY = '你的 Api Key'
SECRET_KEY = '你的 Secret Key'

client = AipOcr(APP_ID, API_KEY, SECRET_KEY)

这三个数据都在之前的应用管理里面呢,粘贴进来就可以了。 这样便创建了客户端,还可以对客户端进行一些配置,比如连接的超时时间等等,这里就不做配置了。

通用文字识别

""" 读取图片 """
def get_file_content(filePath):
    with open(filePath, 'rb') as fp:
        return fp.read()

image = get_file_content('example.jpg')

这段代码是从官方文档中复制过来的,意思很简单,get_file_content函数通过一个图片的路径将图片转换成二进制数据进行返回,这里的image即为指定图片的二进制数据,有了二进制数据后,就能进行文字识别了。

  • basicGeneral
  • basicAccurate

这两个方法都可以进行文字识别,不过basicAccurate方法是高精度版本的,具体用哪个方法看大家喜好。

下面来测试一下我们能否成功提取到图片文字,比如下面的一张图片:

from aip import AipOcr

# 调用百度API识别图片内容
APP_ID = '18076523'
API_KEY = 'vlLcZ6VGb88qoAr5IN0OTShw'
SECRET_KEY = '8KzHr2AvEREYGGwdwIMFZSwTUoPB6LC4'

client = AipOcr(APP_ID,API_KEY,SECRET_KEY) # 生成一个对策

# 获取图片的二进制数据
def get_file_content(filePath):
	with open(filePath,'rb') as fp:
		return fp.read()

image = get_file_content('screen.png')

# 调用文字识别(高精度版)
text = client.basicAccurate(image)

print(text)

运行结果:

成功获取到文字内容,我们先来处理一下这些数据。 log_id我们不管,words_result_num应该是识别的文字数量,它把图片中的文字拆分成了几个小块,这里一共四块,文字内容存放在列表words_result中,每个列表由一个字典组成,文本内容的键为words,所以接下来取出文本内容就很简单了:

from aip import AipOcr

# 3、调用百度API识别图片内容
APP_ID = '18076523'
API_KEY = 'vlLcZ6VGb88qoAr5IN0OTShw'
SECRET_KEY = '8KzHr2AvEREYGGwdwIMFZSwTUoPB6LC4'

client = AipOcr(APP_ID,API_KEY,SECRET_KEY) # 生成一个对策

# 获取图片的二进制数据
def get_file_content(filePath):
	with open(filePath,'rb') as fp:
		return fp.read()

image = get_file_content('screen.png')

# 调用文字识别(高精度版)
text = client.basicAccurate(image)

# 处理返回的数据
textList = text['words_result']
for i in textList:
	print(i['words'])

运行结果:

到这里,图片的文字识别我们也掌握了。

程序源代码

下面是程序的所有代码:

import time
import keyboard
from PIL import ImageGrab
from aip import AipOcr

# 1、截取图片
keyboard.wait(hotkey='ctrl+alt+a') # 键盘输入的触发事件

keyboard.wait(hotkey='enter')

time.sleep(0.1) # 因为读取截取内容会有一个延迟,导致读取到的是上一次的截图,这里我们主动延迟

# 2、将图片保存到电脑上
image = ImageGrab.grabclipboard()
image.save('screen.png') # 将截取的图片进行保存

# 3、调用百度API识别图片内容
APP_ID = '18076523'
API_KEY = 'vlLcZ6VGb88qoAr5IN0OTShw'
SECRET_KEY = '8KzHr2AvEREYGGwdwIMFZSwTUoPB6LC4'

client = AipOcr(APP_ID,API_KEY,SECRET_KEY) # 生成一个对策

# 获取图片的二进制数据
def get_file_content(filePath):
	with open(filePath,'rb') as fp:
		return fp.read()

image = get_file_content('screen.png')

# 调用文字识别(高精度版)
text = client.basicAccurate(image)
textList = text['words_result']
for i in textList:
	print(i['words'])

效果在刚开始就演示过了,它可不光能复制PDF文字的内容,因为在哪里都可以进行截图操作,所以诸如一些百度文库的地方,无法复制文字内容,就可以通过这种方式曲线复制。

最后

最后我想说的是,要把学习当做自己的乐趣,编程是灵活的,自己遇到一些问题的时候,可以想着自己制作一些小工具,既解决了自己的问题,又能够从中学到很多知识,何乐而不为呢?

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring框架完全掌握(上)

    前面我写了一篇关于Spring的快速入门,旨在帮助大家能够快速地了解和使用Spring。既然是快速入门,讲解的肯定只是一些比较泛的知识,那么对于Spring的一...

    wangweijun
  • 带你掌握框架的灵魂——反射技术

    Java反射机制指的是在Java程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法;对于给定的一个对象,都能够调用它的任意一个属性和方法。这种动态...

    wangweijun
  • 深入Java源码剖析之字符串常量

    字符串在Java生产开发中的使用频率是非常高的,可见,字符串对于我们而言非常关键。那么从C语言过来的同学会发现,在C中是没有String类型的,那么C语言要想实...

    wangweijun
  • Java Web 中使用ffmpeg实现视频转码、视频截图,javaffmpeg

    http://www.cnblogs.com/dennisit/archive/2013/02/16/2913287.html#!comments

    bear_fish
  • 常青:小程序音视频功能的原理及应用

    12月15日,由腾讯云主办的首届“腾讯云+社区开发者大会”在北京举行。本届大会以“新趋势•新技术•新应用”为主题,汇聚了超40位技术专家,共同探索人工智能、大数...

    云加社区技术沙龙
  • Windows轻量抓包工具SmartSniff

    http://www.nirsoft.net/utils/smsniff.html

    shawyang
  • thinkphp中出现无法加载控制器index?

    今天学习thinkphp时看着视频学,然后我却出现了无法加载控制器index的问题。。。

    meihuasheng
  • 漫画:什么是树状数组?

    我们学习数据结构的目的在于将我们的算法变得更快。由 Peter M. Fenwick 提出的树状数组 BIT 结构就是一个优秀的数据结构,BIT 全称 Bina...

    程序员小浩
  • go语言 tcp通信例子

    go 的tcp的应用层代码看起来极为简单 1,多个协程同时Accept , 不知道这种实现有没有什么问题 2,多个协程同时处理网络IO事件, 貌似意味着, 有多...

    李海彬
  • lodash源码分析之baseFindIndex中的运算符优先级

    我悟出权力本来就是不讲理的——蟑螂就是海米;也悟出要造反,内心必须强大到足以承受任何后果才行。 ——北岛《城门开》 本文为读 lodash 源码的第十篇,后...

    对角另一面

扫码关注云+社区

领取腾讯云代金券