English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
ファイルアップロードはすべてのUI自動化テストで直面する厄介な問題です、今日はここで自分のファイルアップロードの経験を共有し、多くのファイルアップロードの罠に落ちたseleniumerの方々に助けになればと思います。
まず、アップロードボタンの種類を区別する必要があります、大まかに2種類に分類できます、1つはinputボックス、もう1つは比較的複雑で、js、flashなどで実現され、タグはinputではありません
この2つのことをそれぞれ分析します:
1.inputタグ
众所周知、inputタグは直接send_keysを使用できます、ここも例外ではありません、コード例を見てみましょう:
サンプルURL:http://www.sahitest.com/demo/php/fileUpload.htm
代码:
# -*- coding: utf-8 -*- from selenium import webdriver driver = webdriver.Firefox() driver.get('http:')//sahitest.com/demo/php/fileUpload.htm') upload = driver.find_element_by_id('file') upload.send_keys('d:\\baidu.py') # send_keys print upload.get_attribute('value') # check value driver.quit()
結果:
baidu.py
明らかに、inputアップロードの場合、直接send_keysを使用するのが最も簡単な解決策です。
2.非input型アップロード
次に、難度が上がります。inputフィールドで実装されていないアップロードはどうすればいいですか?この種のアップロードは非常に異なります。aタグ、div、button、objectを使用しています。これらのアップロードをウェブページ上で直接処理することはできません。唯一の方法は、OSのダイアログボックスを開き、ダイアログボックスを処理することです。
問題が再び発生しました。OSのダイアログボックスに関連するレベルは、seleniumでは解決できません。どうすればいいですか?非常に簡単です。OSレベルの操作を使用して処理します。ここでは、問題の解決方法を見つけました。
基本的な解決策は以下の通りです:
1.autoIT、外部の力を利用して、生成されたau3またはexeファイル。
2.Python pywin32ライブラリは、ダイアログのハンドルを識別し、操作を行います。
3.SendKeysライブラリ
4.keybd_event,跟3同様ですが、Ctrlを使用してキーボードをシミュレートしています。+a,ctrl+c,ctrl+v…
現在のところ、私は以上の4つの方法しか知りません。他の方法がある場合は、コメントを残して教えてください。それで学びましょう。
順番に見てみましょう:
1. autoIT
autoITのアップロードおよびパラメータ化の方法については、別のブログ記事で詳しく説明しました。seleniumのautoitコマンドラインパラメータを参照してください。ここでは詳細は省略します。
2.win32gui
話は長くなりますので、まずコードを紹介します:
サンプルURL:http://www.sahitest.com/demo/php/fileUpload.htm
代码:
# -*- coding: utf-8 -*- from selenium import webdriver import win32gui import win32con import time dr = webdriver.Firefox() dr.get('http://sahitest.com/demo/php/fileUpload.htm') upload = dr.find_element_by_id('file') upload.click() time.sleep(1) # win32gui dialog = win32gui.FindWindow('#32770', u'文件上传') # 对话框 ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None) ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None) Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None) # 上面三句依次寻找对象,直到找到输入框Edit对象的句柄 button = win32gui.FindWindowEx(dialog, 0, 'Button', None) # 确定按钮Button win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, 'd:\\baidu.py') # 往输入框输入绝对地址 win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1button) # 按button print upload.get_attribute('value') dr.quit()
結果:
baidu.py
ここで非常に重要な小さなツールが必要です:Spy++百度で検索すると多くの情報があります。もちろん、autoITの標準ツールも使用できますが、これより良いものがありますので、他のものをダウンロードすることをお勧めします。
そして、pywinをインストールする必要があります32のライブラリ、あなたはここでに対応するライブラリを見つけます、注意32のバージョンであっても、64のバージョンと一致するものを見つけてください。
インストールが完了した後、【スタートメニューのPythonフォルダ】でPyWin32のドキュメント【Python for Windows Documentation】で、対応するメソッドAPIを見つけることができます。
使用しているものを簡単に紹介します:
win32gui.FindWindow(lpClassName=None, lpWindowName=None):
•自上層ウィンドウから条件に一致するウィンドウを検索し、そのウィンドウのハンドルを返します。
•lpClassName:クラス名、Spy++で見えます
•lpWindowName:ウィンドウ名、タイトルバーに見える名前
•コードサンプルでは、アップロードウィンドウを探すために使用しています、その中の1つを使うだけで良いです。classnameを使うと他のものに干渉されやすく、windownameを使うと不安定です。異なるアップロードダイアログには異なるwindow_nameがあります、どのように定位するかは状況に応じて決めます。
win32gui.FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None)
•クラス名とウィンドウ名が一致するウィンドウを検索し、そのウィンドウのハンドルを返します。見つからない場合は0を返します。
•hwndParent:0でない場合、hwndParentウィンドウの子ウィンドウを検索します。
•hwndChildAfter:0でない場合、z-indexの順序でhwndChildAfterから子ウィンドウを検索し始めます。そうでない場合は、最初の子ウィンドウから検索を開始します。
•lpClassName:文字型、ウィンドウのクラス名、これはSpy++で見つける。
•lpWindowName:文字型、ウィンドウ名、タイトルバーに見える名前です。
•コードサンプルでは、入力フィールドと確認ボタンを階層的に探すために使用しています
win32gui.SendMessage(hWnd, Msg, wParam, lParam)
•hWnd:整数型、メッセージを受け取るウィンドウのハンドル
•Msg:整数型、送信するメッセージ、これらのメッセージはWindowsが事前に定義したものであり、システム定義メッセージ(System-定義されたメッセージ)
•wParam:整数型、メッセージのwParamパラメータ
•lParam:整数型、メッセージのlParamパラメータ
•コードサンプルでは、入力フィールドにファイルパスを入力し、確認ボタンをクリックするために使用しています
そしてwinについて}32apiモジュールおよび他のメソッドについては、ここでは詳細に説明しません。興味がある場合は、自分で百度やpywinで調べてください。32ドキュメント。
3.SendKeys
まずSendKeysライブラリをインストールする必要があります。pipを使用してインストールできます。
pip install SendKeys
コード例:
サンプルURL:http://www.sahitest.com/demo/php/fileUpload.htm
代码:
# -*- coding: utf-8 -*- from selenium import webdriver import win32gui import win32con import time dr = webdriver.Firefox() dr.get('http://sahitest.com/demo/php/fileUpload.htm') upload = dr.find_element_by_id('file') upload.click() time.sleep(1) # SendKeys SendKeys.SendKeys('D:\\baidu.py') # ファイルアドレスを送信 SendKeys.SendKeys("{ENTER}") # Enterキーを送信 print upload.get_attribute('value') dr.quit()
結果:
baidu.py
SendKeysライブラリを使用して焦点に情報を直接入力できますが、ウィンドウを開く際には少し待機時間を設定すると良いです。そうしないと、最初の文字がsendに入力されないことがあります(またはアドレスの前に無用な文字を追加することもできます)。ただし、この方法は不安定なので推奨しません。
4.keybd_event
win32apiはkeybd_event()メソッドを提供してキーボードイベントをシミュレートしますが、このメソッドは少し複雑で不安定なので、推奨しません。以下に一部のコード例を示します。研究したい場合は、自分で百度で学習してください。
# まずinputボックスを見つけて、アップロードしたいファイルのアドレスを入力し、クリップボードにコピーする video.send_keys('C:\\Users\\Administrator\\Pictures\\04b20919fc78baf41fc993fd8ee2c5c9.jpg') video.send_keys(Keys.CONTROL, 'a') # seleniumのsend_keys(ctrl+a) video.send_keys(Keys.CONTROL, 'x') # (ctrl+x) driver.find_element_by_id('uploadImage').click() # 上传ボタンをクリックしてアップロードボックスを開く # 貼り付け(ctrl + v) win32api.keybd_event(17, 0, 0, 0) # ボタンを押す ctrl win32api.keybd_event(86, 0, 0, 0) # ボタンを押す v win32api.keybd_event(86, 0, win32con.KEYEVENTF_KEYUP, 0) # ボタンをリリースする v win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0) # 升起按键 ctrl time.sleep(1) # 回车(enter) win32api.keybd_event(13, 0, 0, 0) # 按下按键 enter win32api.keybd_event(13, 0, win32con.KEYEVENTF_KEYUP, 0) # 升起按键 enter ...
是不是很麻烦,当然,你甚至可以用按键把整个路径输入进去,不过,我想没人愿意这么做的。而且在此过程中你不能随意移动鼠标,不能使用剪贴板,太不稳定了,所以非常不建议你用这种办法。。
3.多文件上传
接下来还有一种情况值得我们考虑,那就是多文件上传。如何上传多个文件,当然我们还是往输入框里输入文件路径,所以唯一要搞清楚的就是多文件上传时,文件路径是怎么写的。
我来告诉你吧,多文件上传就是在文件路径框里用引号括起单个路径,然后用逗号隔开多个路径,就是这么简单,例如:
"D:\a.txt" "D:\b.txt"
但需要注意的是:只有多个文件在同一路径下,才能这样用,否则是会失败的(下面的写法是不可以的):
"C:\a.txt" "D:\b.txt"
接下里找一个例子试试:
示例网址:http://www.sucaijiayuan.com/api/demo.php?url=/demo/20150128-1
代码:
# -*- coding: utf-8 -*- from selenium import webdriver import win32gui import win32con import time dr = webdriver.Firefox() dr.get('http://www.sucaijiayuan.com/api/demo.php?url=/demo/20150128-1) dr.switch_to.frame('iframe') # 一定要注意frame dr.find_element_by_class_name('filePicker').click() time.sleep(1) dialog = win32gui.FindWindow('#32770', None) ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None) ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None) Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None) button = win32gui.FindWindowEx(dialog, 0, 'Button', None) # 上記の例のコードと同じですが、ここではパラメータが異なります。必要に応じて、アップロード機能をエンキャップするアップロード関数を書くことができます win32gui.SendMessage(Edit, win32con.WM_SETTEXT, 0, '"d:\\baidu.py" "d:\\upload.py" "d:\\1.html"') win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button) print dr.find_element_by_id('status_info').text dr.quit()
結果:
選択3件のファイル、合計1.17KB。
したがって、多ファイルアップロードはそれほど複雑ではなく、非常に簡単です。唯一の違いは、入力パラメータが異なることだけです。autoITでも実現できます。興味がある場合は、自分で試してみてください。
また、上記のウィンドウのコードは前の例と基本的に同じであることがわかります。これにより、アップロード部分を抽出して、関数を作成することができます。アップロードが必要な場合、関数を呼び出し、パラメータを渡すだけで済みます。
見ての通り、アップロードは非常に簡単です。
これでこの記事のすべての内容が終わりました。皆様の学習に役立つことを願っています。また、ナイアラ・チュートリアルのサポートをどうぞお願いします。
声明:この記事の内容はインターネットから収集され、著作権者に帰属します。インターネットユーザーが自発的に貢献し、自己でアップロードしたものであり、このサイトは所有権を持ちません。また、人工編集は行われていません。著作権侵害を疑う内容が見つかった場合は、以下のメールアドレスまでご連絡ください:notice#oldtoolbag.com(メールを送信する際、#を@に置き換えてください。侵害を報告する場合、関連する証拠を提供してください。一旦確認が取れましたら、このサイトは即座に侵害を疑う内容を削除します。)