English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

جمع طرق تحميل الملفات في selenium Python

يعد تحميل الملف من المشاكل التي تواجه جميع اختبارات UI الآلية، اليوم سأشارككم تجربتي في معالجة تحميل الملفات، آمل أن تكون مفيدة لكل من تعاني من هذه المشكلة السابقة.

أولاً، يجب علينا تحديد نوع زر التحميل، يمكن تقسيمه إلى نوعين، واحد هو نافذة input، والآخر أكثر تعقيدًا، يتم تنفيذه عن طريق js أو flash، علامات غير input

سنقوم بتحليل هذين النوعين على حدة:

1. علامة input

من المعروف أن علامة input يمكن استخدامها مباشرة send_keys، لا يختلف الأمر عن هذا، دعونا نرى مثالًا على الكود:

عنوان مثال: 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')) # تحقق من القيمة
driver.quit()

النتيجة:

baidu.py

من الواضح، بالنسبة للتحميل من نوع input، يمكن استخدام send_keys كحل بسيط.

2. تحميل غير input

الآن يجب أن نرفع مستوى الصعوبة، ماذا نفعل إذا لم يتم تنفيذ التحميل عبر نافذة input؟ هذا التحميل يأتي في أنواع غريبة ومتنوعة، بعضها يستخدم علامات a، وبعضها يستخدم div، وبعضها يستخدم button، وبعضها يستخدم object، لا يمكننا معالجة هذه التحميلات مباشرة على صفحة الويب، والطريقة الوحيدة هي فتح نافذة النظام، ومعالجة النافذة.

إذاً، هناك مشكلة أخرى، نافذة النظام المعنية ليست قابلة للحل باستخدام selenium، ماذا نفعل؟ ببساطة، نستخدم عمليات النظام لمعالجة النافذة، وقد وجدنا بالفعل طريقة معالجة المشكلة.

بشكل عام، هناك عدة حلول كما يلي:
 1.autoIT، نستخدم القوة الخارجية، لنطلق ملفات au3 أو exe التي أنشأها
 2. مكتبة pywin32 لـ Python، تتعرف على معرف نافذة الحوار، وتعمل على تشغيلها
 3. مكتبة SendKeys
 4.keybd_event، مشابهة لـ3، ولكنها تُقوم بمحاكاة الضغط على الأزرار، ctrl+a، ctrl+c، ctrl+v... 

اليوم أعرف فقط هذه الطرق الأربعة، إذا كنت تعرف طرق أخرى، فمن فضلك اكتب لي واعلميها، شكرًا لك.

سننظر في ذلك بشكل تدريجي:

1. autoIT

لقد شرحت بالفعل طرق التحميل باستخدام autoIT وتبسيط المعلمات في مدونة أخرى، يرجى الرجوع إلى selenium autoit command line parameters. لن أكرر ذلك.

2.win32gui

لا نكثر من الكلام، لنبدأ بالكود أولاً:

عنوان مثال: 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, 1, button) # اضغط على button
print upload.get_attribute('value')
dr.quit()

النتيجة:

baidu.py

في هذا المكان تحتاج إلى أداة صغيرة جدًا مهمة: Spy++، يمكنك العثور عليها عبر البحث في بايدو، بالطبع يمكنك أيضًا استخدام أدوات autoIT المدمجة، ولكن ليست مفعمة بالفائدة، أقترح الحصول على واحدة أخرى.

وعلاوة على ذلك، يجب عليك تثبيت مكتبة pywin32، يمكنك الذهاب إلىهناابحث عن مكتبة التوافق مع إصدار Python الخاص بك، تأكد من أن 32 بت أو 64 بت يتوافق مع إصدار Python الذي قمت بتثبيته.

بعد إكمال التثبيت، يمكنك رؤية وثائق PyWin32 في مجلد [Python for Windows Documentation] في مجلد [Python] في قائمة البدء، حيث يمكنك العثور على واجهات البرمجة المحددة.

سأقوم بشرح بعض من المفاهيم المستخدمة:

win32gui.FindWindow(lpClassName=None, lpWindowName=None):
 •البحث عن النافذة التي تتوافق مع الشروط من نافذة التسلسل من الأعلى إلى الأسفل، وعودة معرف النافذة هذه.
 •lpClassName: اسم الصنف، يمكن رؤيته في Spy++.
 •lpWindowName: اسم النافذة، يمكن رؤيته في شريط العنوان.
 •مثال الكود الذي نستخدمه للبحث عن نافذة التحميل، يمكنك استخدام واحد فقط منهم، استخدم classname لتحديد الموقع لأنه يتعرض للتشويه من قبل أشياء أخرى، استخدم windowname لتحديد الموقع غير المستقر، قد تكون قيم window_name مختلفة في نافذات التحميل المختلفة، كيفية تحديد الموقع تعتمد على حالتك. 

win32gui.FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None)
 • البحث عن النافذة التي تطابق اسم النافذة والاسم المطلوب، ويعود معامل النافذة. إذا لم يتم العثور على شيء، يتم العودة بـ 0.
 • hwndParent: إذا كان غير صفر، سيتم البحث عن النافذة التي هي نافذة ابن hwndParent
 • hwndChildAfter: إذا كان غير صفر، فإن البحث سيبدأ من hwndChildAfter وفقًا للترتيب منz-index، وإلا سيبدأ من النافذة الأولى
 • lpClassName: نوع بيانات نصي، هو اسم النافذة، يمكنك العثور عليه في Spy++.
 • lpWindowName: نوع بيانات نصي، هو اسم النافذة، وهو العنوان الذي يمكنك رؤيته في شريط العنوان
 • في مثال الكود، نستخدمها للبحث عن نافذة الإدخال والبحث عن زر الاعتماد 

win32gui.SendMessage(hWnd, Msg, wParam, lParam)
 • hWnd: نوع بيانات كامل، هو معامل hWnd للنافذة التي سيتم إرسال الرسالة إليها
 • Msg: نوع بيانات كامل، هي الرسالة التي سيتم إرسالها، هذه الرسائل هي مسبقة التحديد في Windows، يمكنك الرجوع إلى رسائل النظام المحددة (System-Defined Messages).
 • wParam: نوع بيانات كامل، هو معامل wParam للرسالة
 • lParam: نوع بيانات كامل، هو معامل lParam للرسالة
 • في مثال الكود، نستخدمها لوضع عنوان الملف في نافذة الإدخال وضرب زر الاعتماد 

بخصوص مكتبة win32api وطرق أخرى، لن يتم ذكرها بشكل مفصل هنا، إذا كنت ترغب في معرفة المزيد، يمكنك البحث على بaidu أو قراءة مستندات pywin32.

3.SendKeys

أولاً، يجب تثبيت مكتبة SendKeys، يمكن تثبيتها باستخدام pip

pip install SendKeys 

مثال على الكود:

عنوان مثال: 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 لتحديد معلومات داخل التركيز،لكن يجب أن تعطي بعض الوقت للانتظار عند فتح النافذة،إلا فإنك قد لا تستطيع إدخال الحرف الأول (أو يمكنك إضافة حرف غير مفيد قبل العنوان)،لكنني أعتقد أن هذه الطريقة غير مستقرة،لا أوصي بها.

4.keybd_event

يقدم win32api طريقة keybd_event لإنشاء ضغط الأزرار،لكن هذه الطريقة معقدة وغير مستقرة،لذلك لا أوصي بها،أعطي هنا جزءًا من مثال للكود،إذا كنت ترغب في البحث عنها،فأنت بحاجة إلى البحث في البحث

# أولاً إيجاد حقل إدخال،إدخال عنوان الملف الذي تريد تحميله،ثم نسخه إلى لوحة المفاتيح 
video.send_keys('C:\\Users\\Administrator\\Pictures\\04b20919fc78baf41fc993fd8ee2c5c9.jpg')
video.send_keys(Keys.CONTROL, 'a') # send_keys من selenium (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.17 كيلوبايت.

من الواضح أن تحميل الملفات المتعددة ليس معقدًا جدًا، وهو بسيط جدًا، والفرق الوحيد هو المعلمات المدخلة فقط. يمكن أيضًا تنفيذ autoIT، إذا كنت مهتمًا، يمكنك تجربتها بنفسك.

ويمكننا ملاحظة نقطة واحدة، وهي أن رمز النافذة المذكورة أعلاه مشابه بشكل أساسي لرمز المثال السابق، مما يعني أننا يمكننا استخراج جزء التحميل وكتابة دالة، بحيث يمكننا في كل مرة التحميل، التوجه إلى الدالة وتقديم المعلمات.

انظروا، يمكن معالجة التحميل بسهولة.

هذا هو نهاية محتوى هذا المقال، آمل أن يكون قد ساعدكم في التعلم، وأتمنى أن تدعموا تعليمات النطق بشكل أكبر.

إعلان: محتوى هذا المقال تم جمعه من الإنترنت، ويتمتع صاحب الحقوق الأصلية به، ويتم توفير المحتوى من قبل مستخدمي الإنترنت الذين يقدمون المساهمات بشكل تلقائي ويتم تحميلها، ويتمتع هذا الموقع بلا حقوق ملكية، ولا يتم تعديل المحتوى بشكل يدوي، ولا يتحمل هذا الموقع أي مسؤولية قانونية. إذا وجدت محتوى يشتبه في انتهاك حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال # ب @) لإبلاغنا، وقدم الدليل على الأدلة، وسيتم حذف المحتوى المزعوم عن حقوق النسخ فور التحقق منه.

النصائح التي قد تعجبك