Python 3爬虫实现有道翻译+GUI并打包成exe文件

之前写过爬虫爬取有道翻译实现简单翻译,并且不带GUI页面,而且当时写的时候有道官网还没没有反爬虫机制,时隔几月,有道翻译的网页版有了很大声的变化,所以正好在网易云课堂上找到一个有关破解有道翻译反爬虫机制的课程,顺带加上了使用tkinter时间桌面话,并采用cx_Freeze打包成在没有预装Python环境的windows环境下可以执行的exe文件,其实现在导包成可执行的exe文件,好像py2exe比较常用的,后期我会在好好研究研究,
只是一个非常简单的翻译软件,没有其他功能,只有翻译功能,具体开发流程如下:

  1. 写爬虫代码,实现翻译功能,
  2. 破解有道翻译的反爬虫机制(这是比较关键的)
  3. 使用tkinter写GUI页面
  4. 将后台爬虫代码和前台GUI页面结合起来
  5. 打包成exe文件(其实是生成了一个安装程序,msi文件,打包的时候顺带将exe文件也生成了)

    首先爬取的网页url:
    http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
    这里写图片描述
    然后再找到发送个给服务器的表单
    这里写图片描述

这表单里面的内容是都需要在代码中发送给服务器的,主要难在表单中的内容,反爬虫的主要就是加密向服务器提交表单的动态值,在这里面,可以很容易的就看出来安歇键值对是动态的,即哪些键对应的值是每次都有变化的,可以看出来,salt和sign对应的值是每次都变的,所以就找这两个值是怎么升成的,其实一般网站生成的反爬加密值都是采用的时间戳,以及将一下字符串使用加密算法加密一下,这里我们在网页源代码中找到提交给服务器表单的js文件
如图这里写图片描述
在浏览器上打开js文件复制下来(因为直接看的话,没有代码格式,很痛苦,找不到有用的信息)
然后有个在线js代码格式化网站 http://tool.oschina.net/codeformat/js
格式化一下复制到sublime中(我使用的是sublime)然后查询salt 和sign 可以很快找到表单
如图:
这里写图片描述
简单分析一下可以发现salt和sign所对应的值是怎么生成的,具体实现代码:

#获取的是秒
timestamp = int(time.time()*1000) + random.randint(0,10) #转换为毫秒 再扎转换为整型
print("发送给服务器的salt字符串:",timestamp)
word = input('请输入单词或者句子:')

#i = n.md5("fanyideskweb" + t + r + "aNPG!!u6sesA>hBAW1@(-");

u = "fanyideskweb"
t = word
r = str(timestamp)
s =  "aNPG!!u6sesA>hBAW1@(-"

#sign所对应的值是采用md5加密的,在Python中,有专门的库可以实现此加密算法
sign = hashlib.md5((u+t+r+s).encode('utf-8')).hexdigest()
print("发送给服务器的sign字符串",sign)

这样就获得到了salt和sign的值,剩下的就是写爬虫代码了,就很简单了,直接贴代码:

import urllib.request
import urllib.parse
import time
import random
import hashlib # 加密
import json


#获取的是秒
timestamp = int(time.time()*1000) + random.randint(0,10) #转换为毫秒 再扎转换为整型
print("发送给服务器的salt字符串:",timestamp)
word = input('请输入单词或者句子:')

#i = n.md5("fanyideskweb" + t + r + "aNPG!!u6sesA>hBAW1@(-");

u = "fanyideskweb"
t = word
r = str(timestamp)
s =  "aNPG!!u6sesA>hBAW1@(-"

#sign所对应的值是采用md5加密的,在Python中,有专门的库可以实现此加密算法
sign = hashlib.md5((u+t+r+s).encode('utf-8')).hexdigest()
print("发送给服务器的sign字符串",sign)
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
head = {}
head['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'
data = {
        'i':word,
        'from':'AUTO',
        'to':'AUTO',
        'smartresult':'dict',
        'client':'fanyideskweb',
        #'salt':'1516344328939',
        'salt' : timestamp,
        #'sign':'1f7d7e01ed5c59afae4176155d82f446',
        'sign': sign,
        'doctype':'json',
        'version':'2.1',
        'keyfrom':'fanyi.web',
        'action':'FY_BY_ENTER',
        'typoResult':'true',

        #'ue':'UTF-8'#设置翻译支持中文

    }

data = urllib.parse.urlencode(data)

req = urllib.request.Request(url,data.encode(),head)
response = urllib.request.urlopen(req)
transresult = response.read().decode('utf-8')
print(transresult)
result_dict = json.loads(transresult)
result = result_dict['translateResult'][0][0]['tgt']
print(result)

以上只是爬虫的代码
结果:
这里写图片描述
至此,后台的爬虫代码就结束了

接下来下一步,使用Tkinter写GUI,


class Application(object):
    def __init__(self):
        self.window = Tk()
        #self.fanyi = YouDaoFanyi()


        self.window.title(u'小坤翻译')
        #设置窗口大小和位置
        self.window.geometry('310x370+500+300')
        self.window.minsize(310,370)
        self.window.maxsize(310,370)
        #创建一个文本框
        #self.entry = Entry(self.window)
        #self.entry.place(x=10,y=10,width=200,height=25)
        #self.entry.bind("<Key-Return>",self.submit1)
        self.result_text1 = Text(self.window,background = '#ccc')
        self.result_text1.place(x = 10,y = 5,width = 285,height = 155)
        self.result_text1.bind("<Key-Return>",self.submit1)

        #创建一个按钮
        #为按钮添加事件
        self.submit_btn = Button(self.window,text=u'自动翻译',command=self.submit)
        self.submit_btn.place(x=170,y=165,width=70,height=25)
        self.submit_btn2 = Button(self.window,text=u'清空',command = self.clean)
        self.submit_btn2.place(x=250,y=165,width=35,height=25)

        #翻译结果标题
        self.title_label = Label(self.window,text=u'翻译结果:')
        self.title_label.place(x=10,y=165)
        #翻译结果

        self.result_text = Text(self.window,background = '#ccc')
        self.result_text.place(x = 10,y = 190,width = 285,height = 165)
        #回车翻译
    def submit1(self,event):
        #从输入框获取用户输入的值
        content = self.result_text1.get(0.0,END).strip().replace("\n"," ")
        #把这个值传送给服务器进行翻译

        #result = self.fanyi.crawl(content)
        #将结果显示在窗口中的文本框中

        self.result_text.delete(0.0,END)

        #self.result_text.insert(END,result)

        #print(content)

    def submit(self):
        #从输入框获取用户输入的值
        content = self.result_text1.get(0.0,END).strip().replace("\n"," ")
        #把这个值传送给服务器进行翻译

        #result = self.fanyi.crawl(content)
        #将结果显示在窗口中的文本框中

        self.result_text.delete(0.0,END)
        #self.result_text.insert(END,result)
        print(content)
    #清空文本域中的内容
    def clean(self):
        self.result_text1.delete(0.0,END)
        self.result_text.delete(0.0,END)

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


if __name__=="__main__":
    app = Application()
    app.run()

由于没怎么使用过tkinter,第一次使用还不是太会用,因为想实现在文本域中直接回车可以实现翻译,所以就搞的笨了点,写了两个提交的函数,一个是点击按钮翻译,一个是回车翻译,其实应该这两个函数完全是合并为一个就可以的。
然后在GUI函数中添加事件,与后台爬虫代码联系起来,基本上程序就算写完了,最后附上完整代码。

import urllib.request
import urllib.parse
import time
import random
import hashlib # 加密
import json



from tkinter import Tk,Button,Entry,Label,Text,END


#后台爬虫翻译程序代码

class YouDaoFanyi(object):
    def __init__(self):
        pass
    def crawl(self,word):
        #获取的是秒
        timestamp = int(time.time()*1000) + random.randint(0,10) #转换为毫秒 再扎转换为整型

        u = "fanyideskweb"
        t = word
        r = str(timestamp)
        s =  "aNPG!!u6sesA>hBAW1@(-"

        sign = hashlib.md5((u+t+r+s).encode('utf-8')).hexdigest()
        url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
        head = {}
        head['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'
        data = {
                'i':word,
                'from':'AUTO',
                'to':'AUTO',
                'smartresult':'dict',
                'client':'fanyideskweb',
                #'salt':'1516344328939',
                'salt' : timestamp,
                #'sign':'1f7d7e01ed5c59afae4176155d82f446',
                'sign': sign,
                'doctype':'json',
                'version':'2.1',
                'keyfrom':'fanyi.web',
                'action':'FY_BY_ENTER',
                'typoResult':'true',

                #'ue':'UTF-8'#设置翻译支持中文

            }

        data = urllib.parse.urlencode(data)

        req = urllib.request.Request(url,data.encode(),head)
        response = urllib.request.urlopen(req)
        trans_result = response.read().decode('utf-8')
        result_dict = json.loads(trans_result)
        #print(trans_result)
        result = result_dict['translateResult'][0][0]['tgt']
        #print(result_dict['translateResult'][0][0]['tgt'])
        return result



class Application(object):
    def __init__(self):
        self.window = Tk()
        self.fanyi = YouDaoFanyi()


        self.window.title(u'小坤翻译')
        #设置窗口大小和位置
        self.window.geometry('310x370+500+300')
        self.window.minsize(310,370)
        self.window.maxsize(310,370)
        #创建一个文本框
        #self.entry = Entry(self.window)
        #self.entry.place(x=10,y=10,width=200,height=25)
        #self.entry.bind("<Key-Return>",self.submit1)
        self.result_text1 = Text(self.window,background = '#ccc')
        self.result_text1.place(x = 10,y = 5,width = 285,height = 155)
        self.result_text1.bind("<Key-Return>",self.submit1)

        #创建一个按钮
        #为按钮添加事件
        self.submit_btn = Button(self.window,text=u'自动翻译',command=self.submit)
        self.submit_btn.place(x=170,y=165,width=70,height=25)
        self.submit_btn2 = Button(self.window,text=u'清空',command = self.clean)
        self.submit_btn2.place(x=250,y=165,width=35,height=25)

        #翻译结果标题
        self.title_label = Label(self.window,text=u'翻译结果:')
        self.title_label.place(x=10,y=165)
        #翻译结果

        self.result_text = Text(self.window,background = '#ccc')
        self.result_text.place(x = 10,y = 190,width = 285,height = 165)
        #回车翻译
    def submit1(self,event):
        #从输入框获取用户输入的值
        content = self.result_text1.get(0.0,END).strip().replace("\n"," ")
        #把这个值传送给服务器进行翻译

        result = self.fanyi.crawl(content)
        #将结果显示在窗口中的文本框中

        self.result_text.delete(0.0,END)
        self.result_text.insert(END,result)

        #print(content)

    def submit(self):
        #从输入框获取用户输入的值
        content = self.result_text1.get(0.0,END).strip().replace("\n"," ")
        #把这个值传送给服务器进行翻译

        result = self.fanyi.crawl(content)
        #将结果显示在窗口中的文本框中

        self.result_text.delete(0.0,END)
        self.result_text.insert(END,result)
        print(content)
    #清空文本域中的内容
    def clean(self):
        self.result_text1.delete(0.0,END)
        self.result_text.delete(0.0,END)

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


if __name__=="__main__":
    app = Application()
    app.run()

运行效果如图:
这里写图片描述

由于能力有限,没有添加太多的功能,只是一个非常简单的翻译小软件。
剩下的就是建立一个setup.py文件将项目打包了

import sys
#from cx_Freeze import setup,Executable
from cx_Freeze import *
import os
#这里面的tcl和tk文件路径一般在本机安装的Python目录下面,由于我这里是安装了anaconda,所以就在anaconda目录下面了
#以及下面的路径,都很重要,如果写错了会打包失败
os.environ['TCL_LIBRARY'] = r'C:\ProgramData\Anaconda3\tcl\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\ProgramData\Anaconda3\tcl\tk8.6'

include_files=[
    r'C:\ProgramData\Anaconda3\DLLs\tcl86t.dll',
    r'C:\ProgramData\Anaconda3\DLLs\tk86t.dll'

]

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

base = None
if sys.platform == "win32":
    base = "Win32GUI"
setup(

    name = " 小坤翻译",
    version = "2.0",
    description = "xiaokun fanyi",
    options = {"build_exe":build_exe_options},
    executables = [Executable("xiaokunFanyi2.0.py",base=base)]
)
#打包命令
#python setup.py bdist_msi

所需的文件目录
这里写图片描述

因为我开发此项目的环境是在MACOS平台下,但是要打宝成windows平台运行的程序,所以最后打包这一环节就在虚拟机中进行了,
以管理员身份打开CMD窗口进入到项目目录下面,,然后命令

python setup.py bdist_msi

其实这是打包成msi安装程序了,不过顺带在此平台下直接安装了
以下是打包完成后的项目目录这里写图片描述
以下是打包后的msi文件
这里写图片描述
可以直接双击安装
以下是安装完成后的目录文件
这里写图片描述

至此,此翻译小程序就此马马虎虎完成,总共代码其实也就一百多行,非常简单易上手。
其实打包成可执行的文件还是相对简单的,以后有需要的话可以学一下使用py2exe打包成exe文件,好像更加好用。
核心其实是爬虫代码以及如何破解有道翻译的反爬机制,
最后,网易云课堂该课程地址
http://study.163.com/course/courseMain.htm?courseId=1004108008

猜你喜欢

转载自blog.csdn.net/karmacode/article/details/79145728
今日推荐