欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

用Python實現(xiàn)QQ游戲大家來找茬輔助工具

 更新時間:2014年09月14日 12:04:10   投稿:hebedich  
這是一個用于QQ大家來找茬(美女找茬)的輔助外掛,開發(fā)的原因是看到老爸天天在玩這個游戲,分數(shù)是慘不忍睹的負4000多。本來是想寫個很簡單的東西,但由于過程中老爸的多次嘲諷,逼得我不得不盡力完善,最后形成了一個小小的產(chǎn)品。

好久沒寫技術相關的文章,這次寫篇有意思的,關于一個有意思的游戲——QQ找茬,關于一種有意思的語言——Python,關于一個有意思的庫——Qt。

這是一個用于QQ大家來找茬(美女找茬)的輔助外掛,開發(fā)的原因是看到老爸天天在玩這個游戲,分數(shù)是慘不忍睹的負4000多。他玩游戲有他的樂趣,并不很在意輸贏,我做這個也只是自我娛樂,順便討他個好,畢竟我們搞編程的實在難有機會在父輩面前露露手。本來是想寫個很簡單的東西,但由于過程中老爸的多次嘲諷,逼得我不得不盡力完善,最后形成了一個小小的產(chǎn)品。

接觸Python是2010年,相見恨晚,去年拿它寫了些小玩意,離職前給前公司留下了一個Python+wxPython的工作工具,還挺受歡迎。換公司后努力學習C++&Qt,很后悔當初選擇了wxPython而不是PyQt,沒能一脈相承。使用Qt越久,不得不越來越喜歡,寫這個東西正好就用上了。

話不多說,進入正題。這不是一篇完整的代碼講解,只是過程中的一些技術做個分享,包括后來被放棄的一些技術點。當初搜索這些東西也挺費力的,在這做個筆記,后來者也許能搜到收益。
先上個圖:

話說這位是游戲中出鏡最多的MM,和QQ什么關系???
輔助工具在游戲中增加了兩個按鈕,點擊“對比”則自動找“茬”,用藍色小框標識,點擊“擦除”清除標識。

游戲窗口探查
這得用PyWin32庫,它是對windows接口的Python封裝,VC能做的它基本都行。
下載地址:http://sourceforge.net/projects/pywin32/,但不能直接點Download圖標,不然下下來是一個Readme.txt,點“Browse All Files”尋找需要的版本。

#coding=gbk  import win32gui
 
game_hwnd = win32gui.FindWindow("#32770", "大家來找茬") print game_hwnd


QQ找茬是個對話框窗口,Class是“#32770”,這種窗口桌面上有很多,所以還配合了標題“大家來找茬”匹配,又因為是中文,所以第一行指定了使用gbk編碼,否則要么找不到,要么運行出錯。

游戲圖片提取
提取圖片采用了截屏的方式,找到窗口后將窗口提到最前,再作窗口截屏。截屏使用了大名鼎鼎的Python Imaging Library (PIL)庫。

import ImageGrab import win32con
 
win32gui.ShowWindow(game_hwnd, win32con.SW_RESTORE) # 強行顯示界面后才好截圖 win32gui.SetForegroundWindow(game_hwnd) # 將游戲窗口提到最前  # 裁剪得到全圖 game_rect = win32gui.GetWindowRect(game_hwnd)
src_image = ImageGrab.grab((game_rect[0] + 9, game_rect[1] + 190, game_rect[2] - 9, game_rect[1] + 190 + 450)) # src_image.show()  # 分別裁剪左右內(nèi)容圖片 left_box = (9, 0, 500, 450)
right_box = (517, 0, 517 + 500, 450)
image_left = src_image.crop(left_box)
image_right = src_image.crop(right_box) # image_left.show() # image_right.show()

上面用到的坐標都為為了演示代碼簡單填的,實際上使用了變量參數(shù),而且要區(qū)分分辨率什么的。
PIL是一個強大的Python圖形庫(使用文檔),待會的對比分析也須要用到。ImageGrab是PIL的一個模塊,用于圖像的抓取。不帶參數(shù)的ImageGrab.grab()進行全屏截屏,返回一個Image對象,也可使用一個元組作為參數(shù)指定要截取的范圍(左上與右下兩點的坐標),這兩種截屏都是不帶鼠標指針的,還有一個ImageGrab.grabclipboard()可從系統(tǒng)剪貼板采集圖像。
得到Image圖像后可用show()方法,使用系統(tǒng)默認的圖像查看工具打開,方便調(diào)試,也可以用save(filename)保存成文件,對應的可以Image.open(filename)打開獲得。

grab得到了一個包含左右圖片的Image對象后,用crop(box)方法可裁剪得到其中指定的區(qū)域,分別拿到左右兩個游戲圖片。

對比獲得兩圖內(nèi)容不同的區(qū)域
很自然想到把兩圖裁剪成N個小圖片分別對比,左右統(tǒng)一區(qū)域?qū)男D片不相等則為“茬”區(qū),唯一的問題是怎么判斷兩個圖片內(nèi)容不一致?

一開始以為很會有些麻煩,直到發(fā)現(xiàn)了Image.histogram()函數(shù),該函數(shù)用于得到圖像的顏色直方圖。我平常也愛好攝影,知道直方圖可以表示一張圖片中各種亮度(或顏色)的數(shù)量,兩張自然圖片的直方圖基本是不一樣的,除非兩圖對稱、顏色一致但排列不一,但就算如此,將兩圖繼續(xù)分割下去,其子圖的直方圖也會不一樣。直方圖就是一種圖形到數(shù)值的轉(zhuǎn)換,對比兩圖的顏色數(shù)值就可知是否存在差異。

一張用RBG顏色格式的圖像,histogram()函數(shù)將返回一個長度為768的數(shù)組,第0-255表示紅色的0-255,第256-511表色綠色的0-255,第512-767表色藍色的0-255,數(shù)值表示該顏色像素的個數(shù)。因此,histogram()列表所有成員之和等于改圖像的像素值 x 3。

寫了一個函數(shù),用來獲得兩圖比較的數(shù)值差:

ef compare(image_a, image_b): '''返回兩圖的差異值
  返回兩圖紅綠藍差值萬分比之和''' histogram_a = image_a.histogram()
  histogram_b = image_b.histogram() if len(histogram_a) != 768 or len(histogram_b) != 768: return None 
  red_a = 0 red_b = 0 for i in xrange(0, 256):
    red_a += histogram_a[i + 0] * i
    red_b += histogram_b[i + 0] * i
  diff_red = 0 if red_a + red_b > 0:
    diff_red = abs(red_a - red_b) * 10000 / max(red_a, red_b)
 
  green_a = 0 green_b = 0 for i in xrange(0, 256):
    green_a += histogram_a[i + 256] * i
    green_b += histogram_b[i + 256] * i
  diff_green = 0 if green_a + green_b > 0:
    diff_green = abs(green_a - green_b) * 10000 / max(green_a, green_b)
 
  blue_a = 0 blue_b = 0 for i in xrange(0, 256):
    blue_a += histogram_a[i + 512] * i
    blue_b += histogram_b[i + 512] * i
  diff_blue = 0 if blue_a + blue_b > 0:
    diff_blue = abs(blue_a - blue_b) * 10000 / max(blue_a, blue_b)
 return diff_red, diff_green, diff_blue

將函數(shù)返回的紅綠藍差值相加,如果超過了預定定的閥值2000,則表示該區(qū)域不同。這個計算方式有點“土”,但對這次要解決的問題很有效,就沒再繼續(xù)改進。

將左右大圖裁剪成多個小圖分別進行對比 result = [[0 for a in xrange(0, 50)] for b in xrange(0, 45)] for col in xrange(0, 50):
  for row in xrange(0, 45):
    clip_box = (col * 10, row * 10, (col + 1) * 10, (row + 1) * 10)
    clip_image_left = image_left.crop(clip_box)
    clip_image_right = image_right.crop(clip_box)
    clip_diff = self.compare(clip_image_left, clip_image_right)
 
    if sum(clip_diff) > 2000:
      result[row][col] = 1


大圖是500x450,分隔成10x10的小塊,定義一個50x45的二位數(shù)組存儲結(jié)果,分別比較后將差值大于閥值的數(shù)組區(qū)域標記為1.
在游戲上標記兩邊不同的區(qū)域

最初我用了PyWin32的一些函數(shù),獲得游戲窗口句柄后直接在上面繪制,但我不太熟悉Windows編程,不知道如何解決游戲自身重繪后將我的標記擦除的問題,然后搬來了Qt。用Qt創(chuàng)建了一個和游戲大小一樣透明的QWidget窗口,疊加在游戲窗口上,用遮罩來繪制標記。標記數(shù)據(jù)已記錄在result數(shù)組中,在指定的位置繪制一個方格則表示該區(qū)域左右不同,要注意兩個方格間的邊界不要繪制,避免格子太多干擾了游戲。除標記外,還繪制了兩個按鈕來觸發(fā)對比與擦除。

ef paintEvent(self, event): # 重置遮罩圖像 self.pixmap.fill()
 # 創(chuàng)建繪制用的QPainter,筆畫粗細為2像素 # 事先已經(jīng)在Qt窗體上鋪了一個藍色的背景圖片,因此投過遮罩圖案看下去標記線條是藍色的 p = QPainter(self.pixmap)
  p.setPen(QPen(QBrush(QColor(0, 0, 0)), 2))
 for row in xrange(len(self.result)): for col in xrange(len(self.result[0])): if self.result[row][col] != 0: # 定一個基點,避免算數(shù)太難看 base_l_x = self.ANCHOR_LEFT_X + self.CLIP_WIDTH * col
        base_r_x = self.ANCHOR_RIGHT_X + self.CLIP_WIDTH * col
        base_y = self.ANCHOR_Y + self.CLIP_HEIGHT * row
 if row == 0 or self.result[row - 1][col] == 0: # 如果是第一行,或者上面的格子為空,畫一條上邊 p.drawLine(base_l_x, base_y, base_l_x + self.CLIP_WIDTH, base_y)
          p.drawLine(base_r_x, base_y, base_r_x + self.CLIP_WIDTH, base_y) if row == len(self.result) - 1 or self.result[row + 1][col] == 0: # 如果是最后一行,或者下面的格子為空,畫一條下邊 p.drawLine(base_l_x, base_y + self.CLIP_HEIGHT, base_l_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT)
          p.drawLine(base_r_x, base_y + self.CLIP_HEIGHT, base_r_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT) if col == 0 or self.result[row][col - 1] == 0: # 如果是第一列,或者左邊的格子為空,畫一條左邊 p.drawLine(base_l_x, base_y, base_l_x, base_y + self.CLIP_HEIGHT)
          p.drawLine(base_r_x, base_y, base_r_x, base_y + self.CLIP_HEIGHT) if col == len(self.result[0]) - 1 or self.result[row][col + 1] == 0: # 如果是第一列,或者右邊的格子為空,畫一條右邊 p.drawLine(base_l_x + self.CLIP_WIDTH, base_y, base_l_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT)
          p.drawLine(base_r_x + self.CLIP_WIDTH, base_y, base_r_x + self.CLIP_WIDTH, base_y + self.CLIP_HEIGHT)
 # 在遮罩上繪制按鈕區(qū)域,避免按鈕被遮罩擋住看不見 p.fillRect(self.btn_compare.geometry(), QBrush(QColor(0, 0, 0)))
  p.fillRect(self.btn_toggle.geometry(), QBrush(QColor(0, 0, 0)))
 # 將遮罩圖像作為遮罩 self.setMask(QBitmap(self.pixmap))


這里我沒有替換變量,太麻煩了,能看清楚算法就行。
讓PyQt程序在任務欄隱藏
為了讓PyQt程序不出現(xiàn)在任務欄,構(gòu)造QWidget設置了這些屬性

self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Popup | Qt.Tool)


讓PyQt程序加入系統(tǒng)托盤、資源文件使用
PyQt添加托盤菜單非常容易,幾行代碼就可以

創(chuàng)建托盤 self.icon = QIcon(":\icon.png")
 self.trayIcon = QSystemTrayIcon(self) self.trayIcon.setIcon(self.icon) self.trayIcon.setToolTip(u"QQ找茬助手") self.trayIcon.show()
 # 托盤氣泡消息 self.trayIcon.showMessage(u"QQ找茬助手", u"QQ找茬助手已經(jīng)待命,進入游戲即可激活")
 # 托盤菜單 self.action = QAction(u"退出QQ找茬助手", self, triggered = sys.exit) # 觸發(fā)點擊后調(diào)用sys.exit()命令,即退出 self.menu = QMenu(self) self.menu.addAction(self.action) self.trayIcon.setContextMenu(self.menu)

最初我是用的托盤圖標是一個.ico文件,執(zhí)行腳本可以正常顯示,但打包成exe后執(zhí)行在托盤上顯示為一個空白圖標,用Python的idle工具編譯運行也是空白。嘗試多次后發(fā)現(xiàn):PyQt的托盤圖標不能使用.ico文件,否則會顯示空白,換成png格式素材就沒問題!
PyQt資源文件打包
Qt使用一個.qrc格式的xml文件管理素材,代碼用可用:\xxx\xxx.png的方式引用資源文件中的素材,這在PyQt中同樣支持。
這里我創(chuàng)建了一個resources.qrc文件

<!DOCTYPE RCC> <RCC version="1.0"> <qresource> <file>icon.png</file> </qresource> </RCC>


然后用

pyrcc4 resources.qrc > resources.py


命令,將資源文件轉(zhuǎn)成一個python模塊,在代碼中import resources,則可以用這樣的方式使用圖像素材

self.icon = QIcon(":\icon.png")


打包成可執(zhí)行程序
這個工具是給別人用的,肯定不能以py腳本的形式發(fā)布,我使用了cx_Freeze來打包為可執(zhí)行程序。
為此要寫一個打包命令腳本convert2exe.py

#!Python #coding=gbk  # python轉(zhuǎn)exe腳本 # # 安裝cx_Freeze # 執(zhí)行 python convert2exe.py build # 將自動生成build目錄, 其下所有文件都必須打包 #  import sys from cx_Freeze import setup, Executable
 
base = None if sys.platform == "win32":
  base = "Win32GUI" 
buildOptions = dict(
  compressed = True)
 
setup(
    name = "ZhaoChaAssistant", version = "1.0", description = "ZhaoChaAssistant", options = dict(build_exe = buildOptions), executables = [Executable("zhaochaassistant.py", base = base, icon = "icon.ico")])


最后執(zhí)行一個命令

python convert2exe.py build

則會在當前路徑下創(chuàng)建個build目錄,打包的程序就在其中一個exe.win-amd64-2.7的目錄中,運行exe即可執(zhí)行,與Python無二??上н@個包太大了一些,整個目錄達到了30M。

為了讓exe程序也有一個好看的圖標,在最后一行中的executables參數(shù)中指定了icon = "icon.ico",這個圖標就最好使用多頁的.ico格式(16x16,32x32,48x48...),讓程序在各種顯示環(huán)境下(桌面、文件夾)都有原生的顯示。

如果打包的時候必須使用獨立的資源,可在buildOptions字典參數(shù)中增加一條include_files = ['xxx.dat']配置,這樣在打包時會將python腳本目錄中的xxx.dat文件拷貝到exe目錄中,不寫的話就得人工拷貝了。

小技巧:Python獲得自己的絕對路徑
Python中有個魔術變量可以得到腳本自身的名稱,但轉(zhuǎn)換成exe后該變量失效,這時得改用sys.executable獲得可執(zhí)行程序的名稱,可用hasattr(sys, "frozen")判斷自己是否已被打包,下面是一個方便取絕對路徑的函數(shù):
import sys   def module_path(): if hasattr(sys, "frozen"): return os.path.dirname(os.path.abspath(unicode(sys.executable, sys.getfilesystemencoding()))) return os.path.dirname(os.path.abspath(unicode(__file__, sys.getfilesystemencoding())))

結(jié)束語

Python可能是程序員最好的玩具,什么都能粘起來,日常寫點小工具再合適不過了。
文中的第三方模塊都可以Google獲得下載地址,有些庫沒有Win7 64位的原始版本(比如PIL),但可到
http://www.lfd.uci.edu/~gohlke/pythonlibs/
下載別人編譯好的,也很方便。

相關文章

  • pyecharts繪制各種數(shù)據(jù)可視化圖表案例附效果+代碼

    pyecharts繪制各種數(shù)據(jù)可視化圖表案例附效果+代碼

    這篇文章主要介紹了pyecharts繪制各種數(shù)據(jù)可視化圖表案例并附效果和代碼,文章圍繞主題展開詳細的內(nèi)容介紹,感興趣的小伙伴可以參考一下
    2022-06-06
  • python爬蟲 爬取超清壁紙代碼實例

    python爬蟲 爬取超清壁紙代碼實例

    這篇文章主要介紹了python爬蟲學習 爬取超清壁紙代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-08-08
  • 關于numpy兩個array疊加操作詳解

    關于numpy兩個array疊加操作詳解

    numpy是Python用來科學計算的一個非常重要的庫,numpy主要用來處理一些矩陣對象,可以說numpy讓Python有了Matlab的味道,下面這篇文章主要給大家介紹了關于numpy兩個array疊加操作的相關資料,需要的朋友可以參考下
    2022-08-08
  • 使用Python中的Argparse實現(xiàn)將列表作為命令行參數(shù)傳遞

    使用Python中的Argparse實現(xiàn)將列表作為命令行參數(shù)傳遞

    Argparse?是一個?Python?庫,用于以用戶友好的方式解析命令行參數(shù),本文我們將討論如何使用?Python?中的?Argparse?庫將列表作為命令行參數(shù)傳遞,感興趣的可以了解下
    2023-08-08
  • 通過Python實現(xiàn)一個簡單的html頁面

    通過Python實現(xiàn)一個簡單的html頁面

    這篇文章主要介紹了通過Python寫一個簡單的html頁面,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • Python實現(xiàn)繪制3D地球旋轉(zhuǎn)效果

    Python實現(xiàn)繪制3D地球旋轉(zhuǎn)效果

    這篇文章主要為大家詳細介紹了如何利用Python實現(xiàn)繪制出3D地球旋轉(zhuǎn)的效果,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以參考一下
    2023-02-02
  • 基于Python實現(xiàn)火車票搶票軟件

    基于Python實現(xiàn)火車票搶票軟件

    每年的節(jié)假日一到,大家頭疼的總時同一個問題:你買到回家的票了嗎?尤其是大型的節(jié)日:國慶、春節(jié)等。本文將利用Python編寫一個火車票搶票軟件,感興趣的可以了解一下
    2022-07-07
  • python中讀取txt文件時split()函數(shù)的妙用

    python中讀取txt文件時split()函數(shù)的妙用

    這篇文章主要介紹了python中讀取txt文件時split()函數(shù)的妙用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Python隨機生成彩票號碼的方法

    Python隨機生成彩票號碼的方法

    這篇文章主要介紹了Python隨機生成彩票號碼的方法,涉及Python操作隨機數(shù)及字符串的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • Python繪制線圖之plt.plot()的介紹以及使用

    Python繪制線圖之plt.plot()的介紹以及使用

    在Python中plt.plot是matplotlib庫中的一個函數(shù),用于繪制點和線,并對其樣式進行控制,下面這篇文章主要給大家介紹了關于Python繪制線圖之plt.plot()的介紹以及使用的相關資料,需要的朋友可以參考下
    2023-12-12

最新評論