利用Python, PyQt5,Selenium,百度图像识别API制作文献阅读辅助工具

开发背景

作为一名科研狗,经常需要读一些外文文献并且做笔记,有时还需要全文翻译以备后用。这时候会遇到一些问题:

PDF和CAJ文件直接复制出来的东西含有大量无用的换行符,手动删除十分麻烦;

有的文献是图片形式的,或者设置了权限导致无法复制,这个时候更麻烦,需要一个一个单词自己敲;

对于需要大量翻译的文献,经过本人测试发现一整段翻译效果不如一句一句单独翻译效果好,但是一句一句翻译起来实在太麻烦了。

基于以上的问题以及自己的英语水平,我开发了一个集去换行符,图片转文字,整段翻译于一体的文献阅读辅助工具,旨在提高自己的文献阅读效率,用最短的时间完成最多的工作。

工具介绍

  • Python

Python是一种计算机程序设计语言。是一种动态的、面向对象的脚本语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。……………………

这一段摘自百度百科

https://baike.baidu.com/item/Python/407313?fr=aladdin

  • 百度图片转文字API

百度图片转文字API地址:https://cloud.baidu.com/product/ocr/general

你需要注册账号,创建图片转文字才能使用,在此之前需要在python安装对应的库:baidu-api。

后续步骤其实我也是从别的博客里学的,这里放上博客传送门:https://blog.csdn.net/wc781708249/article/details/78559448

在此感谢ID为风吴痕的大哥/大姐

  • Selenium

关于selenium的基本信息可以参考百度。

本文使用selenium主要是用来做浏览器自动翻译。为什么不直接调用AIP翻译呢?我试过用有道和百度的API直接翻译,但是结果一点也不美好,翻译出来的东西完全不想人话~~~~这可能是免费版的原因吧,反正最后我是放弃这个思路了。

本文中使用Selenium的原因主要是本人的爬虫水平太低,只能选择selenium这样不需要太复杂操作和破解的爬虫工具来进行浏览器自动翻译。网上有很多大神可以不用selenium直接用爬虫翻译,这可能是我以后努力的目标吧,反正目前我还做不到~~~

  • PyQt5

PyQt5不多解释,具体见百度。

开发过程

  • 准备工作

在开发之前需要准备好开发环境和浏览器驱动,我用的是火狐浏览器,因此准备了火狐驱动。开发环境需要安装selenium,PyQt5,pyinstaller,baidu-api等,具体见下图:

利用Python, PyQt5,Selenium,百度图像识别API制作文献阅读辅助工具_第1张图片

因为这个虚拟环境还用来做别的事,因此看起来乱七八糟的~,准确的库安装目录参考后边的代码。

  • GUI设计

只有黑框框的工具当然也是可以用的,但是既然会用PyQt5,为什么还要用黑框框呢,是吧?

GUI设计我的总体思想是能用,但是不要太显眼,不能搞得太大了挡住其他更重要的部分,也不能太小了,太小不方便拖拽,此外最好还能置顶桌面,不用在切换程序的时候老是找他。基于这样的想法我的界面设计成了这样:

利用Python, PyQt5,Selenium,百度图像识别API制作文献阅读辅助工具_第2张图片

主要可以分成两个大区:按钮区和状态栏。按钮区又可以分为左右两个部分,左边小,右边大,这样方便将界面放在桌面最右边使用,如下图:

利用Python, PyQt5,Selenium,百度图像识别API制作文献阅读辅助工具_第3张图片

这样做的好处是既不挡着主界面又好找,是不是很机智。此外为了方便放在右边,状态栏的提示也是尽可能短小精悍。

GUI设计的具体代码如下:

class Settings():
    def __init__(self):
        self.button_height=40
        self.button_width_big=200
        self.button_width_small=40
        self.button_number=4
        self.button_wall=10  self.window_width=self.button_wall*3+self.button_width_big+self.button_width_small        self.window_height=(self.button_number+2)*self.button_wall+(self.button_number+0)*self.button_height
    def cal_loc_width(self,before_num):
        return self.button_width_small*before_num+self.button_wall*(before_num+1)
    def cal_loc_height(self,before_num):
        return self.button_wall*(before_num+1)+self.button_height*before_num





#kill_change_lineV4.0
#更新:有道翻译,selenium页面管理
#唐明弘 2019-01-09
import sys,threading
from PyQt5.QtWidgets import QApplication, QPushButton,QMainWindow
from PyQt5.QtCore import Qt
from Tools import *
from setting import Settings
from selenium import webdriver
class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.title = 'KCL4.0'
        self.left = 100
        self.top = 100
        self.width = 230
        self.height = 200
        self.initUI()
        self.words=""
        self.time=1
        self.time2=1
        self.time3=1
        self.bro=webdriver.Firefox()
        self.bro.minimize_window()
    def initUI(self):
        s=Settings()
        self.setWindowTitle(self.title)
        self.setFixedSize(s.window_width, s.window_height)
        #self.setGeometry(self.left, self.top)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        # Create a button in the window

        self.button1 = QPushButton('K', self)
        self.button1.move(s.cal_loc_width(0), s.cal_loc_height(0))
        self.button1.resize(s.button_width_small, s.button_height)
        self.button = QPushButton('去掉换行符', self)
        self.button.move(s.cal_loc_width(1), s.cal_loc_height(0))
        self.button.resize(s.button_width_big,s.button_height)

        self.pic2words1=QPushButton("C",self)
        self.pic2words1.move(s.cal_loc_width(0), s.cal_loc_height(1))
        self.pic2words1.resize(s.button_width_small,s.button_height)
        self.pic2words=QPushButton("图片转文字",self)
        self.pic2words.move(s.cal_loc_width(1), s.cal_loc_height(1))
        self.pic2words.resize(s.button_width_big,s.button_height)

        self.translate_google_button_small = QPushButton("GT", self)
        self.translate_google_button_small.move(s.cal_loc_width(0), s.cal_loc_height(2))
        self.translate_google_button_small.resize(s.button_width_small,s.button_height)
        self.translate_google_button_big= QPushButton("谷歌翻译", self)
        self.translate_google_button_big.move(s.cal_loc_width(1), s.cal_loc_height(2))
        self.translate_google_button_big.resize(s.button_width_big,s.button_height)

        self.translate_youdao_small=QPushButton("YT",self)
        self.translate_youdao_small.move(s.cal_loc_width(0),s.cal_loc_height(3))
        self.translate_youdao_small.resize(s.button_width_small,s.button_height)
        self.translate_youdao_big=QPushButton("有道翻译",self)
        self.translate_youdao_big.move(s.cal_loc_width(1),s.cal_loc_height(3))
        self.translate_youdao_big.resize(s.button_width_big,s.button_height)

        self.button1.clicked.connect(self.on_click)
        self.pic2words1.clicked.connect(self.pic2word)
        self.button.clicked.connect(self.on_click)
        self.pic2words.clicked.connect(self.pic2word)
        self.translate_google_button_small.clicked.connect(self.translate_google_button)
        self.translate_google_button_big.clicked.connect(self.translte_google_before)
        self.translate_youdao_small.clicked.connect(self.translate_youdao_button)
        self.translate_youdao_big.clicked.connect(self.translate_youdao_brfore)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    app.exit(app.exec_())
  • 去掉换行符

辅助工具的第一个功能是去掉换行符,这是最简单也是唯一一个不需要联网就能用的功能:只是从剪切板读取文字,把原始文字中的换行符(“\r\n”)换成空(“”)即可。代码如下:

def on_click(self):
    try:
        write_text_to_clipboard(read_text_from_clipboard().replace("\r\n"," "))
        self.statusBar().showMessage(str(self.time)+"K成功!!")
        self.time=self.time+1
    except:
        self.statusBar().showMessage(str(self.time)+"K失败!!")
  • 图片转文字

图片转文字用到了百度图片转文字API,具体代码我是参考前边提到的ID为风吴痕的大哥/大姐的博客的。具体代码如下:

主线程:

def pic2word(self):
t=threading.Thread(target=pic2wordsss,args=(self.My_statusBar,self.time2),name="function")
    t.start()
    self.time2+=1

 

t线程:

def pic2wordss(pic):
    #  定义常量
    APP_ID = '14966447'
    API_KEY = 'Gaz1QIGG0XFUzHA1cfwGlvRA'
    SECRET_KEY = 'bZXqpXb82E2AGvKBzHlfgZrIYYGuIXF2 '
    # 初始化文字识别分类器
    aipOcr = AipOcr(APP_ID, API_KEY, SECRET_KEY)
    options = {'detect_direction': 'true', 'language_type': 'CHN_ENG', }
    result = aipOcr.webImage(pic, options)#得到结果
    words = result.get("words_result")
    pp = ""
    for word in words:
        pp = pp + " " + word.get("words")
    print(str(pp))
    return str(pp)
def pic2wordsss(status_bar,time2):
    try:
        pic = read_pic_from_clipboard()
        words = pic2wordss(pic)
        print(type(words))
        write_text_to_clipboard(words)
        status_bar(str(time2) + "C成功!!")
        time2 = time2 + 1
    except:
        status_bar(str(time2) + "C成功!!")
  • 翻译工具

翻译工具是本文中最复杂的部分。

翻译工具包括谷歌翻译和有道翻译,主要的处理流程为:

  1. 标签切换
  2. 文字前处理
  3. 翻译
  4. 结果后处理
  • 标签管理

标签管理的主要作用是将浏览器界面切换到对应的网页,是正常翻译的保证。例如,若选择了谷歌翻译而浏览器界面是有道翻译,就会因为找不到对应的目标而报错。标签管理的代码如下:

def tag_manage(browser,target):#标签管理函数
    Google='window.open("https://translate.google.cn/");'
    Youdao='window.open("http://fanyi.youdao.com/");'
    statu=0
    try:
        handles = browser.window_handles
    except:
        browser=webdriver.Firefox()
        handles=browser.window_handles
    if browser.title==target:
        pass
    else:
        for handle in handles:
            browser.switch_to.window(handle)
            if browser.title == target:
                statu = 1
                break
        if statu == 0 and target=="在线翻译_有道":
            browser.execute_script(Youdao)
        if statu==0 and target == "Google 翻译":
            browser.execute_script(Google)
    return browser
  • 前处理

前处理要解决的问题是在翻译之前去掉文字中不需要的东西,把一整段话以句为单位进行分解,最后输出分解结果

代码如下:

def before_translate():
    words=read_text_from_clipboard()
    p=words.replace("\r\n"," ")
    pp=p.replace("et al. ","et al ")
    ppp=pp.replace("e.g.","***********")
    pppp=ppp.replace("i.e.","&&&&&&&&&&&")
    ppppp=pppp.replace("\x00",'')
    wordss=ppppp.split(". ")
    for i in range(len(wordss)):
        wordss[i]=wordss[i].replace("***********","e.g.")
        wordss[i]=wordss[i].replace("&&&&&&&&&&&", "i.e.")
    for word in wordss:
        if word=='':
            wordss.pop(wordss.index(word))
    return wordss
  • 谷歌翻译

谷歌翻译的主要流程是:

1.清楚翻译栏原有文字

2.放进新文字

3.点击翻译

4.点急复制按钮

5.将结果存储了,进行下一句翻译

代码如下:

def translate_google(browser,words):
    WebDriverWait(browser,20,0.01).until(lambda browser:browser.find_element_by_class_name("clear")).click()
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_id("source")).send_keys(words.replace("al.[","al ["))
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_class_name("go-button")).click()
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_class_name("translation"))
    time.sleep(0.5)
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_class_name("copybutton")).click()
  • 有道翻译

有道翻译的基本过程同谷歌翻译,代码如下:

def translate_youdao(browser,words):
    try:
        WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_id("inputDelete")).click()
        #点击清除
    except:
        pass
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_id("inputOriginal")).send_keys(
        words.replace("al.[", "al ["))
    #输入内容
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_id("transMachine")).click()
    #点击翻译
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_id("transTarget"))
    time.sleep(0.5)
    #等待结果
    WebDriverWait(browser, 20, 0.01).until(lambda browser: browser.find_element_by_id("targetCopy")).click()
    #复制
  • 共有翻译函数

两种翻译方式的共有部分为共有翻译函数,代码如下:

def translate_with_google_and_youdao(browser,status_bar,time3,tranlate):
    i = 1
    sucess_num = 0
    fail_num = 0
    out = ""
    status_bar(str(time3) + "T开始!!")
    time.sleep(0.2)
    words = before_translate()  # 预处理
    word_num=len(words)
    for word in words:
        try:
            tranlate(browser,word)
            out=out+read_text_from_clipboard()+"。"
            sucess_num+=1
            status_bar(str(i) + "/" + str(word_num) + "/" + str(time3) + "T成功")
        except:
            status_bar(str(i) + "/" + str(word_num) + "/" + str(time3) + "T失败")
            time.sleep(1)
            fail_num+=1
        i+=1
    if fail_num:
        status_bar(str(time3)+"-"+str(fail_num)+"T失败")
    else:
        status_bar(str(time3) +  "T成功")
    write_text_to_clipboard(out)
  • 打包发布

所有程序都正常运行之后需要将工具打包成exe,方便以后直接调用。用到的工具是pyinstaller,打包命令为:

Pyinsaller -F -w xxxxx.py

打包好了就可以正常使用了!

 

本文涉及的源代码和最后的exe程序连接如下:

链接:https://pan.baidu.com/s/1FAP18elUegRsAM4WysU6GQ

提取码:pf1a

有需要的朋友可以自己下载

 

你可能感兴趣的:(编程语言,Python,selenium,pyqt5)