多語言按鍵映射校驗demo

  • 實現(xiàn)不同語種通過輸入法上屏后與預(yù)期上屏內(nèi)容結(jié)果對比
流程.png

一 、測試數(shù)據(jù)集收集

test_data.py:通過https://www.cnblogs.com/yiven/p/7118056.html收集物理鍵盤各按鍵對應(yīng)的映射碼,根據(jù)需要存放test_data.py文件,各語種均基于物理鍵盤的四排按鍵操作,所以每個測試數(shù)據(jù)中均分為四套數(shù)據(jù)。

  • 默認按鍵映射碼

僅做最終數(shù)據(jù)對比,獲取某個按鍵對比結(jié)果時候正確。

    def default_data(self):
        '''默認按鍵映射碼'''
        data = {
                '`~': '192', '1!': '49', '2@': '50', '3#': '51', '4$': '52', '5%': '53', '6^': '54', '7&': '55',
                '8*': '56', '9(': '57','0)': '48', '-_': '189', '=+': '187',
                # 中文二排鍵盤
                'q': '81', 'w': '87', 'e': '69', 'r': '82', 't': '84', 'y': '89', 'u': '85', 'i': '73', 'o': '79',
                'p': '80', '[{':'219',']}':'221','|':'220',
                # 中文三排鍵盤
                'a': '65', 's': '83', 'd': '68', 'f': '70', 'g': '71', 'h': '72', 'j': '74', 'k': '75', 'l': '76',
                ';:': '186','’“':'222',
                # 中文四排鍵盤
                'z': '90', 'x': '88', 'c': '67', 'v': '86', 'b': '66', 'n': '78', 'm': '77',',<':'188','.>':'190','/?':'191',
            }
        return data 
  • 測試數(shù)據(jù)映射碼:韓語

四排按鍵對應(yīng)的直接輸入結(jié)果、按shift+按鍵輸入結(jié)果、開啟capslock+按鍵輸入結(jié)果

    def hy(self):
        '''韓語按鍵映射碼'''
        # 韓語第一排按鍵   [直接點擊,開啟shift點擊,開啟capslock點擊]
        list1 = [
            {'`': '192', '1': '49', '2': '50', '3': '51', '4': '52', '5': '53', '6': '54', '7': '55', '8': '56', '9': '57', '0': '48', '-': '189', '=': '187', },
            {'~': '192', '!': '49', '@': '50', '#': '51', '$': '52', '%': '53', '^': '54', '&': '55', '*': '56', '(': '57', ')': '48', '_': '189', '+': '187', },
            {'`': '192', '1': '49', '2': '50', '3': '51', '4': '52', '5': '53', '6': '54', '7': '55', '8': '56', '9': '57', '0': '48', '-': '189', '=': '187', },
        ]
        # 韓語第二排按鍵
        list2 = [
            {'?': '81', '?': '87', '?': '69', '?': '82', '?': '84', '?': '89', '?': '85', '?': '73', '?': '79', '?': '80', },
            {'?': '81', '?': '87', '?': '69', '?': '82', '?': '84', '?': '89', '?': '85', '?': '73', '?': '79', '?': '80', },
            {'?': '81', '?': '87', '?': '69', '?': '82', '?': '84', '?': '89', '?': '85', '?': '73', '?': '79', '?': '80', },
        ]
        # 韓語第三排按鍵
        list3 = [
            {'?': '65', '?': '83', '?': '68', '?': '70', '?': '71', '?': '72', '?': '74', '?': '75', '?': '76', },
            {'?': '65', '?': '83', '?': '68', '?': '70', '?': '71', '?': '72', '?': '74', '?': '75', '?': '76', },
            {'?': '65', '?': '83', '?': '68', '?': '70', '?': '71', '?': '72', '?': '74', '?': '75', '?': '76', },
        ]
        # 韓語第四排按鍵
        list4 = [
            {'?': '90', '?': '88', '?': '67', '?': '86', '?': '66', '?': '78', '?': '77', },
            {'?': '90', '?': '88', '?': '67', '?': '86', '?': '66', '?': '78', '?': '77', },
            {'?': '90', '?': '88', '?': '67', '?': '86', '?': '66', '?': '78', '?': '77', },
        ]
        return list1, list2, list3, list4

二 、 文件處理

1.打開一個xx.txt文件輸入窗口,可通過subprocess庫完成

subprocess.Popen('ceshi.txt',shell=True)

2.刪除與保存文件內(nèi)容,刪除與保存均在同一文件內(nèi)操作,避免重復(fù)開啟關(guān)閉文件,使用pynput調(diào)用快捷鍵映射碼處理

import pynput,time
class Handle_txt():
    def __init__(self):
        self.ctr = pynput.keyboard.Controller()

    def save_data(self):
        '''保存模塊:正序 按下ctrl s 按鍵列表'''
        with self.ctr.pressed(pynput.keyboard.KeyCode.from_vk(17),
                              pynput.keyboard.KeyCode.from_vk(83)):
            pass
        # 逆序 釋放按鍵列表
        with self.ctr.pressed(pynput.keyboard.Key.esc):
            pass

    def clear_data(self):
        '''清空模塊:正序 按下ctrl a  backspace 按鍵列表'''
        with self.ctr.pressed(pynput.keyboard.KeyCode.from_vk(17),
                              pynput.keyboard.KeyCode.from_vk(65),
                              pynput.keyboard.KeyCode.from_vk(8)):
            pass

        time.sleep(0.5)
        # 逆序 釋放按鍵列表
        with self.ctr.pressed(pynput.keyboard.Key.esc):
            pass

三 、 獲取測試數(shù)據(jù)集

  1. ini配置文件
  • 根據(jù)語種、按鍵布局及上屏方式編輯配置文件 [sectio] > key = values
;測試語言種類   0 中文
; 1.0 -> 韓語     2.0 -> 藏語     3.0 ->   日語Romaji     4.0 -> 日語kana
; 3.1:日語hiragana   3.2:日語-f-katakana  3.3:日語-f-aiphanumeric   3.4:日語-h-katakana    3.5:日語-h-aiphanumeric
; 4.1:日語hiragana   4.2:日語-f-katakana  4.3:日語-f-aiphanumeric   4.4:日語-h-katakana    4.5:日語-h-aiphanumeric
[test_data]
language = 0
[model]
hanyu = ['基礎(chǔ)布局','shift布局','capslock布局'],'32'
  • 獲取配置文件內(nèi)容 configparser

configparser.ConfigParser() 使配置文件生效

class Handle_ini():

    def load_ini(self):
        '''獲取配置文件內(nèi)容'''
        file_path = BasePath + '/Config/config.ini'
        #使配置文件生效
        cf = configparser.ConfigParser()
        cf.read(file_path,encoding='utf-8')
        return cf

    def get_value(self,key,node=None):
        '''獲取配置文件內(nèi)具體值'''
        if node == None:
            node = 'TEST'
        cf = self.load_ini()

        try:
            data = cf.get(node,key)
            # logger.info('測試 -> 獲取配置文件的值-成功:node:{} -> key:{} -> data:{}'.format(node,key,data))
        except Exception as e:
            # logger.exception('測試 -> 獲取配置文件的值-失敗,node:{} -> key:{} -> error:{}'.format(node, key,e))
            data = None
        return data

2.獲取被測語種對應(yīng)的布局及數(shù)據(jù)

HanleIni().get_value('language','test_data') 根據(jù)值判斷當前被測語種
HanleIni().get_value('hanyu','model')獲取被測語種的所有數(shù)據(jù)

def test_data():
    ''' 判斷測試哪種語言 return : 測試數(shù)據(jù)(四排鍵盤) 布局  上屏方式'''
    language = Handle_ini().get_value('language', 'test_data')

    if int(language.split('.')[0]) == 0:
        title = '《中文 字母》數(shù)據(jù)'
        testdata = list(Testdata().china())
        layout = list(ast.literal_eval(Handle_ini().get_value('china', 'model')))[0]
        way = int(list(ast.literal_eval(Handle_ini().get_value('china', 'model')))[1])
        label = False
        return title, testdata, layout, way, label

    elif int(language.split('.')[0]) == 1:
        if int(language.split('.')[1]) == 0:
            title = '《韓語》數(shù)據(jù)'
            # 獲取該語言的測試數(shù)據(jù)
            testdata = list(Testdata().hy())
            # 獲取該語言有幾種布局
            layout = list(ast.literal_eval(Handle_ini().get_value('hanyu', 'model')))[0]
            # 獲取該語言合適的上屏方式
            way = int(list(ast.literal_eval(Handle_ini().get_value('hanyu', 'model')))[1])
            # 特殊處理標識            
            label = False
            return title, testdata, layout, way, label
        else:
            return '錯誤:檢查{0}數(shù)據(jù)是否存在'.format(language)

3.獲取各布局下的測試數(shù)據(jù)

def keyboard(layouts,datas):
    '''  layouts:布局       datas:測試數(shù)據(jù)
        以鍵盤按鍵為基礎(chǔ):四排按鍵,分別獲取每個布局下的按鍵數(shù)據(jù)
    '''
    lists = []
    for i in range(len(layouts)):
        list = []
        for data in datas:
            list.append(data[i])
        lists.append(list)
    return lists

四、獲取到的數(shù)據(jù)進行映射

pynput 支持鼠標和鍵盤輸入和監(jiān)控 。詳細使用見:https://pypi.org/project/pynput/

  • 按下按鍵 pynput.keyboard.Controller().press()
  • 釋放按鍵 pynput.keyboard.Controller().release()
class Keyboard():
    def __init__(self):
        self.ctr = pynput.keyboard.Controller()
        self.num = ''
    def key_mapping(self, layouts, key_list, way, label):

        '''以布局為基礎(chǔ) 傳遞 按鍵參數(shù) ,發(fā)起按鍵映射'''
        if label == False:
            for layout in layouts:
                print(layout)
                if layout == '基礎(chǔ)布局':
                    # print('*********')
                    for keys in key_list[0]:
                        for key,values in keys.items():
                            self.ctr.press(pynput.keyboard.KeyCode.from_vk(int(values)))
                            self.ctr.release(pynput.keyboard.KeyCode.from_vk(int(values)))

                            self.ctr.press(pynput.keyboard.KeyCode.from_vk(int(way)))
                            self.ctr.release(pynput.keyboard.KeyCode.from_vk(int(way)))

                            self.get_txt(key,values)
                    time.sleep(1)
                elif layout == 'shift布局':
                    # print('*********')
                    for keys in key_list[1]:
                        for key,values in keys.items():
                            self.ctr.press(pynput.keyboard.KeyCode.from_vk(16))
                            self.ctr.press(pynput.keyboard.KeyCode.from_vk(int(values)))
                            self.ctr.release(pynput.keyboard.KeyCode.from_vk(int(values)))
                            self.ctr.release(pynput.keyboard.KeyCode.from_vk(16))

                            self.ctr.press(pynput.keyboard.KeyCode.from_vk(int(way)))
                            self.ctr.release(pynput.keyboard.KeyCode.from_vk(int(way)))

                            self.get_txt(key,values)
                    time.sleep(1)
                elif layout == 'capslock布局':
                    # print('*********')
                    '''
                    先開啟caps,按下每個按鍵保存對比,全部按鍵執(zhí)行完畢后,釋放caps
                    '''
                    self.ctr.press(pynput.keyboard.KeyCode.from_vk(20))
                    for keys in key_list[2]:
                        for key,values in keys.items():
                            self.ctr.press(pynput.keyboard.KeyCode.from_vk(int(values)))
                            self.ctr.release(pynput.keyboard.KeyCode.from_vk(int(values)))

                            self.ctr.press(pynput.keyboard.KeyCode.from_vk(int(way)))
                            self.ctr.release(pynput.keyboard.KeyCode.from_vk(int(way)))

                            self.get_txt(key, values)

                    self.ctr.release(pynput.keyboard.KeyCode.from_vk(20))
                    time.sleep(1)
                else:
                    logger.error('當前布局類型錯誤:{0}'.format(list(layout.keys())))
                    break
                time.sleep(1)    

五、結(jié)果對比

1.按鍵輸入內(nèi)容后,保存獲取文本內(nèi)容;
2.如果韓語某按鍵預(yù)期結(jié)果與文本內(nèi)容一致,則通過;
3.若果韓語某按鍵預(yù)期結(jié)果與文本內(nèi)容不一致,則獲取該按鍵對應(yīng)鍵值對的值,獲取default數(shù)據(jù)中鍵盤的按鍵,返回失敗。

    def get_txt(self,key,values):
        '''獲取文件內(nèi)容,進行比對校驗'''
        Handle_txt().save_data()
        Handle_txt().clear_data()
        with open('ceshi.txt','r',encoding='utf-8') as f:
            data = f.read()
            default = Testdata().default_data()
            if key == data.split(' ')[0]:
                i = [i for i, j in default.items() if values == j]
                print('鍵盤:{0} 鍵映射正常:預(yù)期結(jié)果:{1} -> 實際結(jié)果{2}'.format(i,key,data))
                # logger.info('鍵盤:{0} 鍵映射正常:預(yù)期結(jié)果:{1} -> 實際結(jié)果{2}'.format(i,key,data))

            else:
                i= [i for i, j in default.items() if values == j]
                logger.error('鍵盤{0} 鍵映射異常:預(yù)期結(jié)果{1} -> 實際結(jié)果{2}'.format(i, key, data))

六、問題小結(jié)

  • ※※ 使用pynput的.press模擬按下按鍵后,必須有對應(yīng)的.release將該按鍵給釋放掉,不然會出現(xiàn)異常。
  • ※※ 文件對比:按正常流程,輸入內(nèi)容后先保存,獲取文本內(nèi)容進行對比,最后清除文件內(nèi)容,獲取的結(jié)果是不正確的。必須先保存,再清除,最后獲取文件內(nèi)容進行對比。
  • ※※ 因使用pynput庫的原因,造成在linux系統(tǒng)運行該腳本,存在報錯:X11lib
    答:初步判斷是因為.press(pynput.keyboard.KeyCode.from_vk(16))16對應(yīng)的shift按鍵,這種特殊的功能按鍵使用映射碼直接調(diào)用影響,所以出錯。解決辦法:監(jiān)聽鍵盤shift按鍵名稱為:shift_l 所以使用.press(pynput.keyboard.Key.shift_l)避免。注:待校驗。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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