Python實(shí)現(xiàn)翻譯小工具(python打包成exe文件)

1.環(huán)境

  • windows10
  • python3.5(電腦上安裝的是python的集成環(huán)境anaconda2,而且python3.5不是默認(rèn)的環(huán)境)

2.原理

利用Requests模塊獲取有道詞典web頁(yè)面的post信息,BeautifulSoup來(lái)獲取需要的內(nèi)容,通過(guò)tkinter模塊生成gui界面。

3.目錄結(jié)構(gòu)

圖片.png

4.代碼

fangyi.py代碼如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# _author:kaliarch
import requests
import urllib.parse
import time
import random
import hashlib
import json

class search(object):
    def __init__(self):
        self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

    def getData(self,search_name):
        # salt =i = "" + ((new Date).getTime() + parseInt(10 * Math.random(), 10)
        salt = ((time.time() * 1000) + random.randint(1,10))
        # sign = n.md5("fanyideskweb" + t + i + "ebSeFb%=XZ%T[KZ)c(sy!")
        sign_text = "fanyideskweb" + search_name + str(salt) + "ebSeFb%=XZ%T[KZ)c(sy!"
        sign = hashlib.md5((sign_text.encode('utf-8'))).hexdigest()
        paydata = {
            'i': search_name,
            'from': 'AUTO',
            'to': 'AUTO',
            'smartresult': 'dict',
            'client': 'fanyideskweb',
            'salt': salt,
            'sign': sign,
            'doctype': 'json',
            'version': '2.1',
            'keyfrom': 'fanyi.web',
            'action': 'FY_BY_CLICKBUTTION',
            'typoResult': 'false'
        }
        return paydata

    def getHeader(self):
        header = {
            'Host': 'fanyi.youdao.com',
            'Referer': 'http://fanyi.youdao.com/',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
            'Cookie': 'OUTFOX_SEARCH_USER_ID=-846616837@1.80.219.201; OUTFOX_SEARCH_USER_ID_NCOO=129549097.60835753; UM_distinctid=15ff309f18ddc-094cb5494ad815-5d4e211f-1fa400-15ff309f18e449; _ga=GA1.2.184261795.1517119351; __guid=204659719.2556877880764680700.1518435624954.942; JSESSIONID=aaa3A5BLhtTrh4TPX_mgw; monitor_count=2; ___rl__test__cookies=1518488731567'
        }
        return header

    def getRequest(self,paydata,header):
        _data = urllib.parse.urlencode(paydata).encode('utf-8')
        _header = header
        response = requests.post(self.url,data=_data,headers=_header)
        return response.text

    def getResult(self,response):
        result_text = json.loads(response)
        #src = result_text['translateResult'][0][0]['src']
        tgt = result_text['translateResult'][0][0]['tgt']
        return tgt

    def main(self,search_name):
        app = search()
        paydata = app.getData(search_name)
        header = app.getHeader()
        response = app.getRequest(paydata, header)
        tgt = app.getResult(response)
        return tgt

windows.py代碼如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# _author:kaliarch

import tkinter as tk
from fanyi import search

class application:
    def __init__(self):
        self.windows = tk.Tk()
        self.windows.title("翻譯小工具")
        self.windows.geometry("280x350+700+300")

        #提交按鈕
        self.submit_btn = tk.Button(self.windows, text="查詢(xún)",command=self.submit)
        self.submit_btn.place(x=220, y=10, width=50, height=25)

        # 定義輸入框
        self.entry = tk.Entry(self.windows)
        self.entry.place(x=10, y=10, width=200, height=40)

        #輸出內(nèi)容
        self.result_text = tk.Text(self.windows, background="#ccc")
        self.result_text.place(x=10, y=90, width=260, height=245)

        # 翻譯結(jié)果標(biāo)題
        self.title_label = tk.Label(self.windows, text="翻譯結(jié)果:")
        self.title_label.place(x=10, y=65)
        self.search_result = search()

    def submit(self):
        #1.獲取用戶(hù)輸入
        context = self.entry.get()

        #2.利用有道翻譯
        result = self.search_result.main(context)
        #3.輸出
        self.result_text.delete(1.0,tk.END)
        self.result_text.insert(tk.END,result)

    def run(self):
        self.windows.mainloop()

if __name__ == '__main__':
    winapp = application()
    winapp.run()

此時(shí)運(yùn)行windows.py會(huì)出現(xiàn)界面,而且翻譯可用。


圖片.png

setup.py代碼如下:

# -*- coding:utf-8 -*-
# _author:kaliarch

import sys
from cx_Freeze import setup,Executable

import os

os.environ['TCL_LIBRARY'] = r"C:\Users\JayMo\Anaconda2\envs\py35\tcl\tcl8.6"
os.environ['TK_LIBRARY'] = r"C:\Users\JayMo\Anaconda2\envs\py35\tcl\tk8.6"

include_files = [
    r"C:\Users\JayMo\Anaconda2\envs\py35\DLLs\tcl86t.dll",
    r"C:\Users\JayMo\Anaconda2\envs\py35\DLLs\tk86t.dll",
]

build_exe_options = {
    "packages":["os","tkinter","requests","idna"],
    "include_files":include_files
}

base = None

if sys.platform == "win32":
    base = "Win32GUI"

setup(name = "translate_tool",
    version = "0.1",
    description = "fanyitools!",
    options = {"build_exe":build_exe_options},
    executables = {Executable("windows.py",base=base)}
    )

其中:

  • os.environ['TCL_LIBRARY']
  • os.environ['TK_LIBRARY']
  • include_files
    的四個(gè)目錄路徑我用everthing軟件搜索:如搜索:tk8.6:


    圖片.png

然后選擇對(duì)應(yīng)的路徑,比如我的是第一個(gè)。

setup.py是利用cx_Freeze打包成windows的mis安裝小程序,方便使用

切換到項(xiàng)目目錄下執(zhí)行

python setup.py bdist_msi

待執(zhí)行完畢,可以項(xiàng)目文件下生成兩個(gè)文件夾dist中為msi安裝文件,在其他windows服務(wù)器安裝后就為build下的文件內(nèi)容,在build下的exe.win-amd64-3.6下的windows.exe 就可打開(kāi)小工具

【注意:】要切換到python3.5,否則還要安裝用到的包。

生成exe文件后目錄.png

5.cx_Freeze 原理

cx_Freeze 需要通過(guò)一個(gè)簡(jiǎn)單的安裝腳本來(lái)進(jìn)行構(gòu)建。一般來(lái)說(shuō),只要 Python 腳本本身能無(wú)錯(cuò)運(yùn)行在自身環(huán)境,且 cx_Freeze distutils 安裝腳本配置得當(dāng),那么構(gòu)建出的可執(zhí)行文件就能在任何相同操作系統(tǒng)下運(yùn)行。作為開(kāi)始,首先充分調(diào)試自己的 Python 腳本(不妨假設(shè)其名為 main.py)。main.py 允許從任何庫(kù)或其他腳本中導(dǎo)入,甚至用 os.system() 或 subprocess.run() 等調(diào)用其他程序。確認(rèn)無(wú)誤后,在 windows.py 所在目錄下新建一個(gè)較簡(jiǎn)單的 cx_Freeze 腳本,不妨假設(shè)其名為 setup.py,內(nèi)容如下:

import sys
from cx_Freeze import setup, Executable

# Dependencies are automatically detected, but it might need fine tuning.
build_exe_options = {'packages': [], 'excludes': []}

setup(  name = '<程序名>',
        version = '<程序版本>',
        description = '<程序描述>',
        options = {'build_exe': build_exe_options},
        executables = [Executable('main.py')])

可見(jiàn)其基本遵照了官方文檔的示例,并去除了一些暫時(shí)用不到的語(yǔ)句。其中,build_exe_options 暫時(shí)留空,待第一次構(gòu)建后根據(jù)可能的報(bào)錯(cuò)信息補(bǔ)充;原例中的 base 實(shí)際上默認(rèn)就是 None,即命令行程序,除非需要構(gòu)建圖形界面程序,否則配置了反而是畫(huà)蛇添足?,F(xiàn)在可以打開(kāi)命令行終端,在此目錄下運(yùn)行

python setup.py build

由于 cx_Freeze 在編譯時(shí),實(shí)際上是將全部導(dǎo)入庫(kù)都編譯了一遍并放在子目錄中供主程序調(diào)用,從而真正獨(dú)立于 Python 環(huán)境。其自稱(chēng)能夠自動(dòng)分析哪些庫(kù)需要包含。然而事實(shí)上對(duì)深入一定層次后的導(dǎo)入分析有瑕疵(例如 windows.py 引用了一個(gè)庫(kù),該庫(kù)又引用了另一個(gè)庫(kù),則第三個(gè)庫(kù)有可能分析不出)。遇到這種錯(cuò)誤,絕大多數(shù)情況下可以手動(dòng)在 setup.py 中指定額外包含的庫(kù),既可以在 build_exe_options 下的 'packages' 中指定庫(kù)名,也可以在 build_exe_options 中新建一個(gè)鍵名為 'includes' 然后指定庫(kù)名,形如:

build_exe_options = {
    'packages': ['tkinter', 'scipy'], 
    'includes': ['numpy.core._methods']
}

這個(gè)過(guò)程有時(shí)要重復(fù)多次,直到添加完所有<del>屆不到</del>不能自動(dòng)檢測(cè)到的庫(kù)。據(jù)說(shuō)也可以直接在 setup.py 中導(dǎo)入(import)庫(kù),未親測(cè)。個(gè)別特例無(wú)效,請(qǐng)繼續(xù)閱讀。

【參考】

有相當(dāng)數(shù)量的 Python 庫(kù)可以實(shí)現(xiàn)此類(lèi)轉(zhuǎn)換,著名的有 py2exe、py2app、PyInstaller、cx_Freeze 等。其中,py2app 適用于 macOS,不在本文討論范圍內(nèi);py2exe、PyInstaller因?yàn)?Python 3.6 通過(guò) PEP 523 等修改了代碼對(duì)象(code object)的實(shí)現(xiàn)而暫未能繼續(xù)支持。因此,cx_Freeze 屬于目前可用的最佳方案之一。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容