selenium自動化過程當中如何操做Flash動畫

最近在看python的爬蟲框架(scrapy),一個詞歸納就是:"酸爽"!等把selenium自動化版塊講完後,打算寫一寫關於scrapy相關的知識,打算從源碼角度解析下scrapy這個框架。個人想法是它不只僅是用來爬網頁的,更重要的是如何檢測一個網站全部頁面的健康性...回到正題,我想講講這個話題的原由是同事在自動化過程當中遇到了flash的點擊操做,查閱網上的相關資料也得不到有效解決。今天我想一想談談這個flash的自動化操做問題!!html

隨着頁面作的愈來愈炫酷,flash被愈來愈多的嵌入到html網頁中。可是每每因爲對flash的簡單操做,卻阻斷了咱們整個自動化的測試過程!selenium目前的版本是3.0了對flash操做仍然沒有提出解決方案。其實我以爲,不是selenium不做爲,而是它無能爲力!!爲何這麼說呢?咱們知道flash是as語言開發的,咱們想在網頁中操做flash,那麼就必須經過js這個媒介來操做,問題是:開發有沒有開放操做flash的js接口?咱們知道js若是要調用as,那麼as源碼中必須使用ExternalInterface.addCallback函數,把as的接口綁定給js,這樣的話咱們能夠輕鬆的調用js以達到控制flash的目的...咱們搜索selenium對flash的解決方案:99.99%都是向flex工程注入SeleniumFlexAPI.swc,而後經過調用js的接口來控制flash。java

對於一些IT基礎比較薄弱的同窗來講,始終不知道如何按照網上的步驟來進行下去,這裏我對這個方案作個簡單的解釋以下:python

1.這個是須要原flash工程的,不是你獲得的一個簡單的swf文件就能從新編譯的。簡單的說就是找大家開發吧,讓他把SeleniumFlexAPI.swc加入到被操做Flash(Flex)的工程文件的Build庫中,從新Build Flash,而後從新發布到web上。這樣你對這個新的flash可能用js進行操做了。web

2.SeleniumFlexAPI.swc這個文件以及很久很久沒更新了...不知道是否對如今的flash可否操做有效,因此我在1中用了可能。windows

3.我總以爲這個方法有點脫褲子放屁的感受,既然找開發幫你引入SeleniumFlexAPI.swc這個文件,還不如給你直接開放js接口,不是更好? 瀏覽器

吐槽了網上的方法,來講說站在一個測試者角度的解決方案oracle

1、利用AutoIt框架

從某種意義上來講,我有點對這個工具產生依賴。當我在自動化過程當中絕望的時候,我就會第一時間想到它,而它也每每能帶給我驚喜,就像上篇用fiddler錄製接口同樣(其實還有不少..)!來講說我用這個工具來操做flash。我所操做的Flash圖片以下:eclipse

這個Flash是有動畫效果的,通過一段動畫後出現上面圖片的效果。個人任務就是點擊上面圖片中的小鼠標。下面貼出來AutoIt的腳本(最終轉換成exe程序,在控制檯中執行):
scrapy

 

#include <MsgBoxConstants.au3>
Example()
Func Example()
    Local $win = WinWait("[CLASS:MozillaWindowClass;Title:Mozilla Firefox]","",10)
    WinActivate($win);激活當前窗口
    $pos =WinGetPos($win)
    $high=$pos[3];表示窗口的的實際高度
    $weight=$pos[2];表示窗口的實際寬度
    $click_x=970*$weight/1382;970表示我在當前電腦分辨率寬度爲1382下的X座標值
    $click_y=540*$high/744;744表示我再當前電腦分辨率高度爲744下的Y座標值
    $num=1
    While 1
      $icolor=PixelGetColor($click_x,$click_y)
      If $icolor==6671717 Or $icolor==1321236 Or $num==5 Then
         ExitLoop
      EndIf
      Sleep(2000)
      $num=$num+1 WEnd
   MouseClick("left",$click_x,$click_y,1)
 EndFunc   ;

 

須要注意的是,因爲Firefox中嵌入的flash是非windows標準控件,咱們只能用相對座標來點擊。關於以上座標值得獲取,依然用Autoit windows info這個工具獲取以下:

 

而咱們當前電腦分辨率下,取得的整個控件的大小信息以下:

上面腳本很簡單很簡單,你應該明白我什麼意思。還有一點說明的就是上面標紅的部分。我說過了個人flash是個動畫,通過大概5-6後會出現這個小鼠標。那麼咱們在autoit中若是動態的判斷這個小鼠標出現了呢?固然你能夠在腳本中Sleep(10000)等待10S鍾。可是我以爲這樣不太好,個人作法是:在一個循環中實時的取得我所點擊區域的顏色值用PixelGetColor這個函數取得(返回的是一個十進制的值)。當咱們等待的這個控件出現時,即該區域的顏色值等於某個值時,跳出這個循環,而後對這個控件用座標進行點擊!這個color的值我在第二張中也圈出了,這是個16進制的值,轉換成10進制便可!上面的腳本我在2臺不一樣的分辨率大小的電腦上測試過,基本能運行成功!!可是用autoit操做flash也是有一點的缺點。最大的缺點就是相對座標計算的準確性!不過通常我以爲是沒問題的。

上面第一種方案是經過autoit操做flash點擊的,固然autoit也能夠模擬其餘咱們人爲的操做,好比在輸入框中輸入、雙擊某個按鈕等...注意的是,對於非標準控件你要儘量的保證相對座標計算的準確性!

2、利用Sikuli

這個工具也是個神器,關於他的介紹我很少說了,他的原理大概就是:在當前可視窗口中,尋找與你截圖相同的區域,而後操做該區域的中心點座標。說下他的安裝和用法。

1.安裝

通常的安裝教程網上有(https://launchpad.net/sikuli/+download這上面有所有的sikuli包信息)個人補充以下:

第1、最新的下載地址爲: Sikuli-X-1.0rc3 (r905)-win32.exe 這個應用只有32位的,在32位系統上安裝運行應該都沒有問題(須要32位jre6以前的環境)。

第2、若是你對這個較爲熟悉不須要IDE,你能夠僅僅下載 Sikuli-X-1.0rc3 (r905)-win32.zip 

第3、若是你非要在64位系統上安裝sikuli的IDE,直接運行 Sikuli-X-1.0rc3 (r905)-win32.exe無視彈出的錯誤信息,不過最終要運行在32位的jre6環境下。

對於32位系統的要注意jre最好是在jre6(包括)以前的,省得可能會出現閃退的狀況。對於64位系統的要保證其運行在32位的jre6下!可能有的同窗不高興了,我這已經搭建好了java環境,難不成要卸載了,從新裝個32位的開發環境?答案是否認的。咱們系統上能夠運行多個版本的java環境。咱們要作的只是保證其運行環境是32位的jre6就能夠了。爲了不你在oracel官網上對jre6進行尋找,我直接給出鏈接:http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase6-419409.html#jre-6u35-oth-JPR這個是jre6第35次編譯的,注意的是:你僅僅須要下載運行環境,不須要下載開發環境。也不須要從新配置環境變量之類的操做,你須要的僅僅是更改安裝目錄下的Sikuli-IDE-w.bat這個dos腳本,將其中JAVA_EXE指向你新安裝的32位jre6的安裝目錄

說了這麼多你應該明白了環境搭建方面的問題,固然若是有任何問題,你能夠留言!下面說說這個腳本的編寫,首先咱們說說java環境下如何用這個腳原本操做flash;再看看如何在python中如何利用sikuli操做flash。在java中你須要幹三件事:

1.將sikuli安裝目錄下的libs文件夾放在系統的環境變量中。

2.將eclipse的運行環境設置爲32位jre。(不必定jre6只要32位jre就行。上文sikuli IDE須要jre6的緣由是這個IDE應該是在jdk6下開發的,而咱們這裏只是在eclipse運行sikuli-script.jar包中的相關方法)。

3.引入sikuli-script.jar包

簡單的java測試代碼以下:

 

/**
 * 
 */
/**
 * @author PF-211X3
 *
 */
package com;
import org.sikuli.script.*;
public class STest {
    public static void main(String[] args) throws FindFailed, InterruptedException {
        Screen s = new Screen();
        String imgpath = "D:/img/";
s.wait(imgpath+"firfox.png", 5); s.doubleClick(imgpath
+"firfox.png"); System.out.println("end"); } }

 

這個firfox.png就是咱們用任何截圖工具截取桌面上firefox快捷圖標的照片。上面的操做就能夠點擊桌面上的firefox快捷圖標打開火狐瀏覽器了。是否是很神奇!!因此我上文說了其實不須要安裝sikuli的IDE。只須要sikuli-script.jar包與libs文件下的內容便可,相關的函數的用法你徹底能夠猜出來不行看看文檔介紹!固然你想安裝個IDE玩玩也是能夠的~~

對於1沒問題吧,添加環境變量你們都會。對於只會python徹底沒有接觸過java的同事我給出2,3的步驟,java同窗跳過!(個人pc是64位的,且我也已經下載好了32位的jre6的環境。)

如何將eclipse以32位的jre6運行該工程?

1、打開eclipse菜單window-》preferences彈出框,在左邊的樹形圖找到java選項點開後選擇Installed JRES在右邊的選擇框中選擇Add添加咱們32位jre個人截圖以下:

上圖大箭頭部分是咱們新安裝的32位jre路徑,咱們選擇改jre並點擊Apply。

2、右鍵點擊工程選擇Build Path下的子菜單項Add Libraies...添加咱們選擇的jre

 

 

 選擇咱們JRE System library-next->Workspace default JRE(jire6)點擊Finish。

 3.考慮運行的兼容性(不一樣版本的jdk與jre配合須要此配置,相同版本的不須要),右擊該工程選擇菜單項Project->Properties。在彈出框中作一下配置:

如何添加外部包?

選中該工程右鍵點擊該工程選擇Build Path->Add  External Archives...後導入本地目錄下的sikuli-script.jar便可

上面咱們從sikuli角度來操做flash。總結下這種解決方案遇到的坑和注意點。

1.32系統上sikuli的環境搭建是問題不大的,除了sikuli ide的運行環境須要配置成jre6。64位系統上有點坑。上文中我也較詳細的說明了ide的配置以及如何在eclipse中運行sikuli腳本,我相信你確定能運行起來。

2.注意點:sikuli對咱們截圖的匹配查找是在咱們當前可視範圍內的。這句話怎麼理解呢?好比上文中我在桌面上截了一個firefox快捷圖標的圖片,當運行到點擊這個快捷圖標時,忽然彈出了一段小廣告擋住了這個快捷圖標,那麼咱們的sikuli是找不到該圖片的。個人解決辦法是在運行sikuli腳本以前,最好先運行下AutoIt的一個小腳本,就是上文中咱們頻繁使用到的WinActivate($hWnd)函數,能夠確保某個窗口控件是可視的。

說到這來java部分也就這樣了,可是本篇尚未結束,由於咱們尚未講python中如何使用sikuli-script.jar這個包!

sikuli-script.jar是java下的包,python使用java的包最早想到的就是jpython。可是就爲了操做個flash把python解析器設置爲jpython我認爲沒人能接受。那麼有一種神器能夠鏈接python與java還能保證你的運行環境是cpython的,那這個包就是jpype。

對於32位系統,安裝這個是最簡單的你能夠下載jpype.exe程序直接安裝。jpype.exe暫時是沒有64位,咱們選擇安裝包安裝。路徑爲:https://pypi.python.org/pypi/JPype1。咱們下載後運行python setup.py install。發現多是有問題的,緣由是在windows平臺上沒法安裝python c extension的擴展包,咱們下載專用的編譯器Microsoft Visual C++ Compiler for Python 2.7就行了下載地址:https://www.microsoft.com/en-us/download/details.aspx?id=44266。

對於jpype的使用也是很是簡單的,對於32位系統操做sikuli-script.jar這個包太簡單就幾行代碼:

 

#coding=utf-8
import jpype
jvmPath = jpype.getDefaultJVMPath()
jpype.startJVM(jvmPath,"-ea",r"-Djava.class.path=D:\\tutorial\\tutorial\spiders\sikuli-script.jar")#jvmPath爲jvm.dll的路徑能夠人爲指定並指定外部包的加載路徑
JDClass =jpype.JClass("org.sikuli.script.Screen")
s=JDClass()
imgpath = "D:/img/"
s.wait(imgpath + "firfox.png", 5)
s.doubleClick(imgpath + "firfox.png");
jpype.shutdownJVM()

 

 這段代碼與咱們上文的java代碼意義是同樣。爲何說對於32位是沒有問題的,難道64位python解析器沒法這樣用嗎?

首先,並非說64位解析器沒法經過jpype來啓動一個虛擬機,可是問題是咱們只能啓動一個64位的jvm。可是咱們上文說了sikuli-script.jar這個包沒法在64位的jre中運行的,咱們嘗試經過手動給出32位jre下面jvm.dll的路徑來啓用JVM進而運行sikuli-script.jar這個包。個人嘗試代碼:

 

#coding=utf-8
import jpype
jpype.startJVM(r"C:\Program Files (x86)\Java\jre6\bin\client\jvm.dll","-ea",r"-Djava.class.path=D:\\tutorial\\tutorial\spiders\sikuli-script.jar")#jvmPath爲32位jre的jvm.dll路徑
JDClass =jpype.JClass("org.sikuli.script.Screen")
s=JDClass()
imgpath = "D:/img/"
s.wait(imgpath + "firfox.png", 5)
s.doubleClick(imgpath + "firfox.png");
jpype.shutdownJVM()

 

 發現是沒法啓動jvm的,緣由可能很簡單咱們在64位的python解析器上運行32位jvm.dll多少有點問題。那麼咱們在64位上如何使用sikuli呢?沒辦法我能想到的就只有曲線救國了...對的,就是用python調用控制檯來運eclipse裏的工程。個人作法以下:

1.導出該工程爲jar包。

步驟:選擇該工程選擇菜單的File->Export,選擇JAR File,而後一路向西導出到某個路徑下,我直接放桌面了。

2.修改改jar包中的MANIFEST.MF文件。

步驟1、修改改jar包後綴名爲zip。好比將abc.jar變成abc.zip

步驟2、修改裏面的META-INF中的MANIFEST.MF文件,添加Main-Class: com.STest

 

 

 

步驟3、保存後修改abc.zip爲abc.jar

3.修改完jar包後咱們直接編寫運行這個jar的dos腳本以下:

cmd命令:"C:\Program Files (x86)\Java\jre6\\bin\java" -Djava.ext.dirs=C:\lib -jar C:\Users\PF-211X3\Desktop\\abc.jar

 這個簡單的說明吧!

1、C:\Program Files (x86)\Java\jre6\\bin\java是咱們32位jre的路徑下java命令

2、-Djava.ext.dirs命令參數如同jpype中的參數-Djava.class.path同樣爲咱們外部引用包,我這裏是把sikuli-script.jar這個包放在C盤的lib下的

3、-jar參數後面跟的是咱們剛修改過的jar包

以上只是個例子,具體路徑配置按本身我的狀況界定。

咱們發如今個在cmd中是能正常運行的,那麼咱們如何在python中運行這個我相信,不須要我多說了吧

 

import os
cmd="\"C:\Program Files (x86)\Java\jre6\\bin\java\" -Djava.ext.dirs=C:\lib -jar C:\Users\PF-211X3\Desktop\\abc.jar"
os.popen(cmd)

 

 好吧,咱們總算經過曲線救國的方式使得python在64系統上用sikuli操做flash。在32位上仍是用jpype吧!

最後咱們作個簡單的總結吧:

咱們上面使用Autoit與sikuli方法操做flash,2種方法各有特點吧!固然可能還有其餘更好更方便的方法操做flash,但願知道的大神們能寫出來~~