1. 前言
目前Google翻译是我们平时用得比较多的一款软件,为我们提供了众多便利。早前谷歌就发布了为用户提供可调用的谷歌翻译API,对此博主比较欣喜,有了自行DIY一个简洁版的谷歌翻译软件的想法,也为以后用到打点基础。后来看到网页版的免费谷歌翻译,联想到可以通过类似网络爬虫的方式自行写一个谷歌翻译接口得到网络翻译的结果。在此将两种实现方式都写在这篇博文中,作为总结也希望能给其他想做关于谷歌翻译研究的朋友有所启发。
2. 调用Google翻译API方式
在python中有个googletrans的库,首先需要通过pip安装。googletrans可通过在控制台输入如下代码安装:
python pip install googletrans
通过调用googletrans的库我们可以通过以下的python代码实现对一段文本的翻译。首先导入googletrans库,第3行实例化一个翻译对象,其中参数service_urls设置为谷歌翻译的网址。第5行调用translate方法获得翻译结果,其中参数source为需要翻译的文本,src为待翻译的文本的语言类型(这里设置为中文),dest为翻译成的文本语言类型(这里设置为英文),获取翻译结果中的文本类型作为最终翻译结果输出。
python # -*- coding: utf-8 -*- from googletrans import Translator translator = Translator(service_urls=['translate.google.cn']) source = '我是博主小思绪,这是我写的简易翻译软件,真心地希望能够帮助到您。' text = translator.translate(source,src='zh-cn',dest='en').text print(text) # >I am a blogger with a small thought, this is my simple translation software, I really hope to help you.
运行效果如下:
python >I am a blogger with a small thought, this is my simple translation software, I really hope to help you.
以上代码中可以看出,googletrans的封装使得使用起来格外方便。由于是调用的谷歌翻译的API,我们实际的翻译过程是在线上完成的,因此需要保持网络通畅,同时以上代码中的方法对于大规模的文本翻译就比较费时了。
3. 自行定义谷歌翻译接口方式
既然上面的库可以通过访问网页的方式获取翻译结果,我们当然可以自行编写一个类似的接口。思路是通过urllib中的request向谷歌翻译的网页发送请求,解析并获取我们输入文本的翻译结果,转换为我们需要的格式输出。这其实相当于一个网络爬虫,其实现的python代码如下:
python # -*- coding: utf-8 -*- from re import findall from urllib.parse import quote_plus from urllib.request import Request,urlopen from HTMLParser import HTMLParser # 伪造成通过浏览器访问,防止被屏蔽 agent = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 LBBROWSER'} def unescape(text): parser = HTMLParser() return (parser.unescape(text)) # 转换成标准的html标签 def TranslateByGoogle(text, fromLang="auto", toLang="zh-CN"): # 默认输入语言为自动检测,翻译语言为中文 base_link = "http://translate.google.cn/m?hl=%s&sl=%s&q=%s"# 谷歌翻译网址 text = quote_plus(str(text)) link = base_link % (toLang,fromLang,text) # 实际需要网址 request = Request(link, headers=agent) # 访问网页 try: raw_data = urlopen(request).read() # 读取网页数据 data = raw_data.decode("utf-8") # 对数据解码,变成Unicode编码 expr = r'class="t0">(.*?)<' re_result = findall(expr, data) # 找到匹配的内容 if (len(re_result) == 0): result = "" else: result = unescape(re_result[0]) # 转换翻译结果为可用形式 return (result) # 返回翻译结果 except Exception as e: print (e) if __name__=='__main__': # 测试文本 text='I am a blogger and I sincerely hope that my blog can help you.' # 翻译文本 translated_text = TranslateByGoogle(text) print(translated_text) # >我是博主,我真诚地希望我的博客能为您提供帮助。
在以上代码中,主要函数是TranslateByGoogle,从下面运行的变量结果截图可以看出第15-17行是为了得到我们实际需求下实际访问的网址并访问,link中包含了访问的基本网址(谷歌翻译)、待翻译语言类型、翻译语言类型及待翻译文本,它们以一定规则组成我们需要的最终访问地址。
在第20行程序读取以上网址的网页数据,获得的数据还不能直接使用,在21-23行首先将获得的数据解码,变成Unicode编码,以expr为分割点找到包含在expr中的字符作为翻译结果。当结果不为空时,第27行将结果转换为我们需要的字符串形式。
如此,自行定义的谷歌翻译(函数)完成。第33-38行对该函数进行简单测试,采用默认参数(fromLang="auto", toLang="zh-CN")将text翻译能够得到翻译的结果(第39行)。值得注意的是,在调用request访问网站时通过设置headers参数伪造成浏览器浏览器访问,以躲避服务器认为User-Agent为“非人类”而引起的屏蔽。
在上面的示例中,我们设置输入文本的语言类型为auto,将识别语言类型的任务交给了谷歌翻译网页,而如果我们想自行检测一段文本的语言类型又该如何实现呢?python的包langid可实现这一功能。首先安装langid,如下
python
pip install langid
通过如下代码可实现语言类型识别,如输入s1输出zh(表示为中文):
python from langid import classify s1 = "我是博主小思绪" array = classify(s1) print (array[0]) # > zh
4. 谷歌翻译简版pyqt5界面设计
这里利用pyqt5设计一个UI界面,首先利用Qt Designer将用到的空间拖到主窗口中,其中用到的控件有QLabel、QPlainTextEdit、QtoolButton及QTextBrowser,其摆放如下图所示
利用PyUIC将保存的UI文件转化为py文件,对生成的界面类稍作修改。标签5,6分别代表了输入、输出语言类型;对两个QtoolButton控件添加响应点击事件的槽函数,控件1用于弹出选择翻译方式的对话框,在点击时跳出输入框供我们选择执行翻译任务的方法,即上面介绍的两种方法。控件2用于交换翻译的语言类型,被点击时控件5,6上的文本内容交换同时程序实际翻译时的输入、输出语言类型会受到影响(以标签5,6上的语言类型翻译)。控件3、4分别用于显示输入文本(待翻译文本)和输出文本(翻译好的文本)。实现代码如下:
python # -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'GoogleTransUI.ui' # Created by: PyQt5 UI code generator 5.11.3 # author: 思绪无限 # version: 0.1 (2019.5) from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtWidgets import QInputDialog from PyQt5.QtGui import QIcon from googleTranslator import TranslateByGoogle from langid import classify from googletrans import Translator import image1_rc # 导入要用到的图片文件 class Ui_MainWindow(object): def __init__(self, MainWindow): self.type_trans = 'googletrans' self.setupUi(MainWindow) self.retranslateUi(MainWindow) # 设置按钮点击监听事件 self.toolButton_trans.clicked.connect(self.clickButton_trans) self.toolButton_select.clicked.connect(self.clickButton_select) # 设置文本被改变监听事件 self.textEdit_input.textChanged.connect(self.textChanging_textEdit_input) def setupUi(self, MainWindow): # 设置主窗口 MainWindow.setObjectName("MainWindow") # 窗口对象名 MainWindow.setWindowModality(QtCore.Qt.NonModal) MainWindow.resize(600, 500) # 窗口一般大小 MainWindow.setMinimumSize(QtCore.QSize(600, 500)) # 窗口最小尺寸 MainWindow.setMaximumSize(QtCore.QSize(16777215, 16777215)) # 窗口最大尺寸 MainWindow.setToolTip("") # 功能提示 MainWindow.setAutoFillBackground(False) MainWindow.setWindowIcon(QIcon(':/newPrefix/images_test/Google.png')) # 设置窗口图标 MainWindow.setIconSize(QtCore.QSize(60, 60)) # 图标尺寸 MainWindow.setStyleSheet("...") # 主窗口qss格式,限于篇幅,实际内容贴在博文最后 MainWindow.setTabShape(QtWidgets.QTabWidget.Rounded) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.centralwidget) self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.verticalLayout_4 = QtWidgets.QVBoxLayout() self.verticalLayout_4.setObjectName("verticalLayout_4") self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setContentsMargins(-1, -1, -1, 20) self.horizontalLayout_3.setObjectName("horizontalLayout_3") # 工具按钮设置 self.toolButton_trans = QtWidgets.QToolButton(self.centralwidget) self.toolButton_trans.setMinimumSize(QtCore.QSize(30, 25)) self.toolButton_trans.setMaximumSize(QtCore.QSize(20, 20)) self.toolButton_trans.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.toolButton_trans.setAutoFillBackground(False) self.toolButton_trans.setStyleSheet("background-color: transparent;") self.toolButton_trans.setText("") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/newPrefix/images_test/exchange.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.toolButton_trans.setIcon(icon) self.toolButton_trans.setIconSize(QtCore.QSize(20, 20)) self.toolButton_trans.setPopupMode(QtWidgets.QToolButton.DelayedPopup) self.toolButton_trans.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) self.toolButton_trans.setAutoRaise(False) self.toolButton_trans.setArrowType(QtCore.Qt.NoArrow) self.toolButton_trans.setObjectName("toolButton_trans") self.horizontalLayout_3.addWidget(self.toolButton_trans) self.label_title = QtWidgets.QLabel(self.centralwidget) self.label_title.setMinimumSize(QtCore.QSize(0, 30)) font = QtGui.QFont() font.setFamily("隶书") font.setPointSize(18) self.label_title.setFont(font) self.label_title.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop) self.label_title.setObjectName("label_title") self.horizontalLayout_3.addWidget(self.label_title) self.verticalLayout_4.addLayout(self.horizontalLayout_3) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setContentsMargins(-1, 0, -1, 10) self.horizontalLayout.setObjectName("horizontalLayout") self.label_language1 = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setFamily("Sitka Small") font.setPointSize(13) self.label_language1.setFont(font) self.label_language1.setLayoutDirection(QtCore.Qt.LeftToRight) self.label_language1.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_language1.setObjectName("label_language1") self.horizontalLayout.addWidget(self.label_language1) self.toolButton_select = QtWidgets.QToolButton(self.centralwidget) self.toolButton_select.setMinimumSize(QtCore.QSize(50, 39)) self.toolButton_select.setMaximumSize(QtCore.QSize(50, 45)) self.toolButton_select.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) self.toolButton_select.setAutoFillBackground(False) self.toolButton_select.setStyleSheet("background-color: transparent;") self.toolButton_select.setText("") icon1 = QtGui.QIcon() icon1.addPixmap(QtGui.QPixmap(":/newPrefix/images_test/change.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.toolButton_select.setIcon(icon1) self.toolButton_select.setIconSize(QtCore.QSize(50, 39)) self.toolButton_select.setPopupMode(QtWidgets.QToolButton.DelayedPopup) self.toolButton_select.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) self.toolButton_select.setAutoRaise(False) self.toolButton_select.setArrowType(QtCore.Qt.NoArrow) self.toolButton_select.setObjectName("toolButton_select") self.horizontalLayout.addWidget(self.toolButton_select) self.label_language2 = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setFamily("楷体") font.setPointSize(14) self.label_language2.setFont(font) self.label_language2.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.label_language2.setObjectName("label_language2") self.horizontalLayout.addWidget(self.label_language2) self.verticalLayout_4.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.label_in = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setFamily("微软雅黑") font.setPointSize(10) self.label_in.setFont(font) self.label_in.setLineWidth(1) self.label_in.setObjectName("label_in") self.verticalLayout.addWidget(self.label_in) self.textEdit_input = QtWidgets.QPlainTextEdit(self.centralwidget) self.textEdit_input.setMinimumSize(QtCore.QSize(0, 0)) self.textEdit_input.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.textEdit_input.setSizeIncrement(QtCore.QSize(0, 0)) font = QtGui.QFont() font.setFamily("Consolas") self.textEdit_input.setFont(font) self.textEdit_input.setMouseTracking(True) self.textEdit_input.setStyleSheet("background-color: transparent;") self.textEdit_input.setLineWidth(3) self.textEdit_input.setLineWrapMode(QtWidgets.QPlainTextEdit.WidgetWidth) self.textEdit_input.setObjectName("textEdit_input") self.verticalLayout.addWidget(self.textEdit_input) self.horizontalLayout_2.addLayout(self.verticalLayout) self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.label_out = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setFamily("微软雅黑") font.setPointSize(10) self.label_out.setFont(font) self.label_out.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_out.setObjectName("label_out") self.verticalLayout_2.addWidget(self.label_out) self.textBrowser_output = QtWidgets.QTextBrowser(self.centralwidget) self.textBrowser_output.setMinimumSize(QtCore.QSize(0, 0)) self.textBrowser_output.setMaximumSize(QtCore.QSize(16777215, 16777215)) font = QtGui.QFont() font.setFamily("Consolas") font.setPointSize(9) font.setItalic(False) self.textBrowser_output.setFont(font) self.textBrowser_output.setStyleSheet("background-color: transparent;") self.textBrowser_output.setLineWidth(3) self.textBrowser_output.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) self.textBrowser_output.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) self.textBrowser_output.setLineWrapMode(QtWidgets.QTextEdit.WidgetWidth) self.textBrowser_output.setObjectName("textBrowser_output") self.verticalLayout_2.addWidget(self.textBrowser_output) self.horizontalLayout_2.addLayout(self.verticalLayout_2) self.verticalLayout_4.addLayout(self.horizontalLayout_2) self.horizontalLayout_4.addLayout(self.verticalLayout_4) MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Google Translation —— author:小思绪")) self.label_title.setToolTip(_translate("MainWindow", "Test Result Helper 3.3.10 author:WuXian (2019.3.13)")) self.label_title.setText(_translate("MainWindow", "谷歌翻译简版 ")) self.label_language1.setText(_translate("MainWindow", "English")) self.label_language2.setText(_translate("MainWindow", "中文(简体)")) self.label_in.setText(_translate("MainWindow", " 检测语言")) self.textEdit_input.setToolTip(_translate("MainWindow", "请输入要翻译的文本")) self.label_out.setText(_translate("MainWindow", " 翻译结果 ")) def textChanging_textEdit_input(self): # 输入文本改变执行槽函数 QtWidgets.QApplication.processEvents() inputTxt = self.textEdit_input.toPlainText() # 检测当前语言类型 self.textBrowser_output.setText('正在自动检测语言...') QtWidgets.QApplication.processEvents() # 处理事件 array = classify(inputTxt)# array中即检测结果 languageType='未知' # 根据语言类型调整对应显示标签 if array[0] == 'zh': languageType='中文' font = QtGui.QFont() font.setFamily("楷体") font.setPointSize(14) self.label_language1.setText("中文(简体)") self.label_language1.setFont(font) font.setPointSize(13) font.setFamily("Sitka Small") self.label_language2.setFont(font) self.label_language2.setText("English") elif array[0] == 'en': languageType = '英文' font = QtGui.QFont() font.setFamily("楷体") font.setPointSize(14) self.label_language2.setFont(font) self.label_language2.setText("中文(简体)") font.setPointSize(13) font.setFamily("Sitka Small") self.label_language1.setFont(font) self.label_language1.setText("English") QtWidgets.QApplication.processEvents() if self.label_language1.text() == "中文(简体)": formLang="zh-CN"# 输入为中文 toLang = "en"# 翻译为英文 font = QtGui.QFont() font.setFamily("微软雅黑") font.setPointSize(10) font.setItalic(False) self.textEdit_input.setFont(font) font = QtGui.QFont() font.setFamily("Times New Roman") font.setPointSize(10) font.setItalic(True) self.textBrowser_output.setFont(font) else: formLang = "en" # 输入为英文 toLang = "zh-CN" # 翻译为中文 font = QtGui.QFont() font.setFamily("微软雅黑") font.setPointSize(10) font.setItalic(False) self.textBrowser_output.setFont(font) font = QtGui.QFont() font.setFamily("Times New Roman") font.setPointSize(10) font.setItalic(True) self.textEdit_input.setFont(font) QtWidgets.QApplication.processEvents() self.textBrowser_output.setText('检测语言:'+languageType) # 调用翻译API进行翻译 self.textBrowser_output.append('正在翻译...') QtWidgets.QApplication.processEvents() # 根据选取的翻译方式选择接口调用 if self.type_trans=='googletrans': try: translator = Translator(service_urls=['translate.google.cn']) QtWidgets.QApplication.processEvents() # 调用谷歌翻译API的方法翻译 translated_text = translator.translate(inputTxt, src=formLang, dest=toLang).text QtWidgets.QApplication.processEvents() self.textBrowser_output.setText(translated_text) # 在输出框显示结果 except Exception as e: self.textBrowser_output.setText('调用谷歌翻译API出错') else: QtWidgets.QApplication.processEvents() # 调用自行编写的谷歌翻译方法翻译 translated_text = TranslateByGoogle(inputTxt,formLang,toLang) QtWidgets.QApplication.processEvents() self.textBrowser_output.setText(translated_text) # 在输出框显示结果 def clickButton_select(self): # 点击交换语言按钮槽函数,按钮被点击将两边显示的语言类型交换 if self.label_language1.text()=="English": font = QtGui.QFont() font.setFamily("楷体") font.setPointSize(14) self.label_language1.setText("中文(简体)") self.label_language1.setFont(font) font.setPointSize(13) font.setFamily("Sitka Small") self.label_language2.setFont(font) self.label_language2.setText("English") else: font = QtGui.QFont() font.setFamily("楷体") font.setPointSize(14) self.label_language2.setText("中文(简体)") self.label_language2.setFont(font) font.setPointSize(13) font.setFamily("Sitka Small") self.label_language1.setFont(font) self.label_language1.setText("English") def clickButton_trans(self): # 点击按钮弹出对话框,选择翻译要调用的接口类型 items = ("googletrans","google website") item, ok = QInputDialog.getItem(self.centralwidget,"选择翻译方式","翻译方式:",items,0,False) if ok: self.type_trans=item
每次在控件3的文本输入框中输入文本,程序会自动调用对应槽函数检测语言类型然后调用翻译接口进行翻译,显示翻译结果在控件4的文本浏览框中。其界面如下
上面的一段代码中定义了Ui_MainWindow的类,里面包含的是关于UI界面的生成以及内部逻辑,我们只需在外部调用该类显示窗口就行了,调用并运行该类的代码如下:
python from GoogleTransUI import Ui_MainWindow from sys import argv,exit from PyQt5.QtWidgets import QApplication,QMainWindow if __name__ == '__main__': app = QApplication(argv) window = QMainWindow() ui = Ui_MainWindow(window) window.show() exit(app.exec_())
为了使界面简洁美观在代码中使用了qss,在主窗口中利用setStyleSheet对其中的各控件设置了背景、图标以及其他的美化设置,在本节上面的第一段代码中为了代码看起来美观将其第40行代码中的内容省略了,特此贴在最后有需要的朋友可以复制下面的代码并将第40行代码内容覆盖即可。至于里面的具体含义,这里限于篇幅真的不适合在这里详细讲了,在后面我会专门出个专栏讲述的,这里就直接用好了。
python MainWindow.setStyleSheet("#MainWindow,QInputDialog{border-image: url(:/newPrefix/images_test/light.png);}\n" "QMenuBar{border-color:transparent;}\n" "QToolButton[objectName=\"pushButton_doIt\"]{\n" "\n" "border:5px;\n" "}\n" "\n" "QToolButton[objectName=\"pushButton_doIt\"]:hover {\n" "image:url(:/newPrefix/images_test/run_hover.png);}\n" "\n" "QToolButton[objectName=\"pushButton_doIt\"]:pressed {\n" "image:url(:/newPrefix/images_test/run_pressed.png);}\n" "\n" "\n" "QScrollBar:vertical{\n" "\n" "background:transparent;\n" "padding:2px;\n" "\n" "border-radius:8px;\n" "max-width:14px;\n" "}\n" "\n" "QScrollBar::handle:vertical{\n" "background:#9acd32;\n" "min-height:50px;\n" "border-radius:8px;\n" "}\n" "\n" "QScrollBar::handle:vertical:hover{\n" "background:#9eb764;\n" "}\n" "\n"