衝頂,百萬答題助手改進(python)

答題遊戲現在很火,但是,價值卻不如以前了。爲什麼這麼晚纔想着去寫這種助手呢!煩躁

這次改進主要是讓效果更好,操作更爲簡單(這是最大的改進),現在只需要運行,按回車,就可以了,不再需要外部軟件輔助。不過,這裏卻損失了一點效率,畢竟答題時間就10秒,效率也是很重要的。所以呀,實際上效果不是很好,現在多數娛樂效果吧,有興趣的小夥伴可以拿去玩玩。

本次程序用到的工具:python3.6,adb驅動,我已經打包成exe了,所以,只是想玩玩的就不必在意這些了,下載鏈接:鏈接:https://pan.baidu.com/s/1ggMaOqn 密碼:f8eo(csdn上傳不了zip文件,莫名其妙)
本次代碼相比上次主體部分改動不大,註釋我也沒做更新,但應該也看得懂的,直接上代碼了:

 # _*_ coding:UTF-8 _*_
import numpy as np
import win32con
import ctypes
import ctypes.wintypes
import threading
import time
import os
import subprocess
from PIL import Image
from aip import AipOcr#百度的api,百度官網有教程
import shutil
import string
import urllib


#熱鍵功能,獨立的一個線程
class Hotkey(threading.Thread):  #創建一個Thread.threading的擴展類  

    def run(self):  
        global EXIT #定義全局變量,這個可以在不同線程間共用
        global RUN #定義全局變量,這個可以在不同線程間共用
        user32 = ctypes.windll.user32  #加載user32.dll

        try:
            if not user32.RegisterHotKey(None, ID1, 0, HOTKEY_RUN):   # 註冊快捷鍵F10並判斷是否成功,該熱鍵用於結束程序,且最好這麼結束,否則影響下一次註冊熱鍵。  
                print ("Unable to register id"), ID1 # 返回一個錯誤信息

            if not user32.RegisterHotKey(None, ID2, 0, HOTKEY_EXIT):   # 註冊快捷鍵F10並判斷是否成功,該熱鍵用於結束程序,且最好這麼結束,否則影響下一次註冊熱鍵。  
                print ("Unable to register id"), ID2 # 返回一個錯誤信息

            #以下爲檢測熱鍵是否被按下,並在最後釋放快捷鍵  
            msg = ctypes.wintypes.MSG()  

            while True:
                if user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
                    if msg.message == win32con.WM_HOTKEY:
                        if msg.wParam == ID2:
                            EXIT=True
                            return
                        elif msg.wParam == ID1:
                            RUN=True

                    user32.TranslateMessage(ctypes.byref(msg))  
                    user32.DispatchMessageA(ctypes.byref(msg))   

        finally:
            user32.UnregisterHotKey(None, ID1)#必須得釋放熱鍵,否則下次就會註冊失敗,所以當程序異常退出,沒有釋放熱鍵,
                                              #那麼下次很可能就沒辦法註冊成功了,這時可以換一個熱鍵測試
            user32.UnregisterHotKey(None, ID2)


class Ans():

    def main(self):
        #im_name=os.listdir(filePath)#獲取圖片名
        self.cut()#對圖片進行裁剪

        f=open('im.jpg','rb')#二進制方式打開圖文件
        image=f.read()#這裏好像必須命名爲image,百度的api限定,有點不能理解,有待考察
        #im=base64.b64encode(f.read()) #讀取文件內容,轉換爲base64編碼

        #這裏是每個百度雲賬號獨立的一些ID
        APP_ID='10687373'
        API_KEY='BIziiO4FQbN7n7iu5kPCuEMF'
        SECRET_KEY='yOxbhG3qZp0KvNkB42hstT4aNWXHOitZ'


        client = AipOcr(APP_ID, API_KEY, SECRET_KEY)#這個就是百度的api,可以獲取一個相當於實例對象的東西,可以調用函數
        information=client.basicGeneral(image)#ocr函數,打印出來是json格式的

        #這裏是普通版的
        STR=''#存儲識別出來的文字
        num=information['words_result_num']
        for i in range(0,num):#根據格式得出來的循環,答案放在前面,題目放在後面,保證題目能完成搜索到
            if i>=0 and i<3:
                STR+=information['words_result'][num-i-1]['words']
                STR+=' '
            else:
                STR+=information['words_result'][i-3]['words']

        #下面幾行是對得到的字符串做一些處理,去掉一些符號,因爲百度搜索限制38個字以內,個人覺得這裏寫的很醜,無奈沒找到好的方法
        #STR=STR[1:len(STR)]
        STR=STR.translate(string.punctuation)

        DEL=['以下','哪個','是','的','什麼','下列','哪種']#這鞋子替換成空格,好處在於百度效果很好吧,親測結果
        for x in DEL:
            STR = STR.replace(x,' ')

        self.find(STR)#調用百度搜索,並保存到本地,再用默認瀏覽器打開
        print (STR)
        f.close()#關閉文件,不然後面刪除不掉
        #shutil.rmtree(path)#刪除之前獲得的圖片文件以及這個文件夾,以便下次判斷是否已經截屏

    #打開圖片並裁剪
    def cut(self):
        #im_name=os.listdir(filePath)#獲取圖片名,因爲截屏靠的外部軟件,沒辦法修改截屏圖片的名字
        im=Image.open(filePath+'\\'+"screenshot.jpg")
        if len(im.split()) == 4:
            r, g, b, a = im.split()#圖片有四通道
            im=Image.merge("RGB",(r,g,b))

        #下面這篇代碼也寫的不夠優雅,可是沒找到好的辦法
        box=(80,330,1000,1300)
        crop_im=im.crop(box)#裁剪函數
        array_im=np.array(crop_im.convert('L'))
        im.close()
        x=970#記錄最下邊界
        for i in range(300):
            if array_im[969-i][0]==255:
                x=969-i-50
                break
        crop_im2=crop_im.crop((0,0,919,x))
        crop_im2.save('im.jpg')#保存本地,有不保存就直接用二進制打開的方式嗎??求教


    #調用百度搜索,並保存到本地,再用默認瀏覽器打開,參考百度的資料,具體哪篇忘記了,,如有問題請聯繫我。。
    def find(self,STR):
        url = "http://www.baidu.com/s"
        search = [('w',STR)]
        getString = url + "?" + urllib.parse.urlencode(search)

        req = urllib.request.Request(getString)
        fd = urllib.request.urlopen(req)
        baiduResponse=fd.read()

        fobj=open("baidu.html",'wb+')
        fobj.write(baiduResponse)
        os.startfile('baidu.html')#這個函數就很剛好的解決了大問題,可以用瀏覽器打開網頁,不然就得手點了
        fobj.close()

    def getPicture(self,filePath,ADBpath):
        #ADBpath=filePath+'\\adb\\adb '
        subprocess.call(ADBpath+"shell /system/bin/screencap -p /sdcard/screenshot.jpg",stdout=subprocess.PIPE, shell=subprocess.PIPE)
        subprocess.call(ADBpath+"pull /sdcard/screenshot.jpg "+filePath+"/screenshot.jpg",stdout=subprocess.PIPE, shell=subprocess.PIPE)

if __name__ == '__main__':
        HOTKEY_RUN=0x0D
        HOTKEY_EXIT=win32con.VK_F8#結束程序的快捷鍵F6,自行根據需要修改,一定要手動關閉程序,否則下次這個快捷鍵就用不了了(python3.6沒這個問題?)

        EXIT = False #用來傳遞退出的參數
        RUN = False
        ID1=106 #註冊熱鍵的唯一id,用來區分熱鍵
        ID2=105

        filePath=os.path.split(os.path.realpath(__file__))[0]
        ADBpath=filePath+'\\adb\\adb '

        ans=Ans()#創建實例

        hotkey = Hotkey()  
        hotkey.start()#啓動線程
        print ("等待手機設備連接USB...如無設備需要連接請按F8結束程序")

        subprocess.call(ADBpath+" wait-for-device",stdout=subprocess.PIPE, shell=subprocess.PIPE)
        print ("截屏快捷鍵:回車,關閉程序快捷鍵:F8")
        while(True):
            if RUN==True:
                print ("開始識別")
                start=time.time()
                ans.getPicture(filePath,ADBpath)
                ans.main()
                subprocess.call(ADBpath+' shell rm /sdcard/screenshot.jpg',stdout=subprocess.PIPE, shell=subprocess.PIPE)
                end=time.time()
                print ("一次識別結束,用時:",end-start)
                print ()
                RUN=False

            elif EXIT==True: #退出程序
                break

效率還是這個程序最大的問題,但是,目前沒想到解決辦法,就先這樣吧,不過,還是有那麼一點幫助的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章