【问题标题】:Unable to perform drag and drop with Selenium (python)无法使用 Selenium 执行拖放(python)
【发布时间】:2020-02-05 14:09:09
【问题描述】:

我正在努力在私有网络应用程序的 python 中使用 Selenium 执行拖放或单击并按住操作。

我尝试在此处的公开示例中重现我的错误: http://the-internet.herokuapp.com/drag_and_drop

下面是我的拖放/单击并按住的基本代码

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('http://the-internet.herokuapp.com/drag_and_drop')
dragged = driver.find_element(By.ID, "column-a")
dropped = driver.find_element(By.ID, "column-b")

#Drag and drop

actions = ActionChains(driver)
actions.drag_and_drop(dragged, dropped).perform() 
#column A is selected but not dragged

#Click and hold
actions = ActionChains(driver)
actions.move_to_element(dragged).click_and_hold().move_to_element(dropped).release().perform()
#Same result : column a is selected but not dragged

通过 stackoverflow 搜索,我发现了一个使用 javascript 的公共示例的“解决方案”。 How to simulate HTML5 Drag and Drop in Selenium Webdriver?

import os
with open(os.path.abspath('C:/Users/Admin/PycharmProjects/AutoTestIntro/drag_and_drop_helper.js'), 'r') as js_file:
    line = js_file.readline()
    script = ''
    while line:
        script += line 
        line = js_file.readline()

driver.execute_script(script+"$('#column-a').simulateDragDrop({ dropTarget: '#column-b'});")

这完美地直接在 python 中工作,但要求拖放的元素有 id。我目前正在从事的私人项目并非如此。

我对 Selenium 做错了什么吗? JS中是否有任何解决方法来指定xpath而不是id?

【问题讨论】:

  • “拖拽元素”的目的地是低于还是高于原位置?
  • 它们在提供的示例中完全相同。
  • 发布你需要获取的元素的html。他们正在使用 css 选择器,这是一个列表。 w3schools.com/cssref/css_selectors.asp
  • 嗨 Jortega,感谢您的回答,但我想我不明白您的意思。我的示例中提供的这个演示网站中提供了所有内容:the-internet.herokuapp.com/drag_and_drop 我尝试使用 id、css 选择器、xpath 进行选择.... 没有工作。你可以在演示网站上试试吗?
  • 如果您可以提供 html,我们可以在 CSS 中构建您需要的 xpath。我无法让辅助函数 simulateDragDrop 接受 xpath.... 没有完全重建它。

标签: python selenium drag-and-drop


【解决方案1】:

我终于找到答案了!!!

见下文:

https://gist.github.com/florentbr/60ef7cb8d9b1ae690cafc82aad52da73

我使用的是 drag-drop.min.js 中的函数

这里有一个简短的python示例:

JS_DRAG_AND_DROP = "function h(a,b,c,d){var k=l.createEvent('DragEvent');k.initMouseEvent(b,!0,!0,l.defaultView,0,0,0,m,n,w,x,y,!1,0,null);Object.setPrototypeOf(k,null);k.dataTransfer=g;Object.setPrototypeOf(k,DragEvent.prototype);a.dispatchEvent(k);setTimeout(d,c)}var a=arguments,c=a[0],d=a[1],q=a[2]||0,r=a[3]||0,t=a[4]||1;a=a[5]||'';var x='alt'===a||'\ue00a'===a,w='ctrl'===a||'\ue009'===a,y='shift'===a||'\ue008'===a,l=c.ownerDocument;a=c.getBoundingClientRect();var e=d?d.getBoundingClientRect():a,m=a.left+a.width/2,n=a.top+a.height/2,u=e.left+(q?q:e.width/2),v=e.top+(r?r:e.height/2),p=l.elementFromPoint(m,n),f=l.elementFromPoint(u,v);for(d=p;d&&!d.draggable;)d=d.parentElement;if(!d||!c.contains(p))throw c=Error('source element is not interactable/draggable'),c.code=15,c;if(!f)throw c=Error('target element is not interactable'),c.code=15,c;var g={constructor:DataTransfer,effectAllowed:null,dropEffect:null,types:[],files:Object.setPrototypeOf([],null),_items:Object.setPrototypeOf([],{add:function(a,b){this[this.length]={_data:''+_data,kind:'string',type:b,getAsFile:function(){},getAsString:function(a){a(this._data)}};g.types.push(b)},remove:function(a){Array.prototype.splice.call(this,a&65535,1);g.types.splice(a&65535,1)},clear:function(a,b){this.length=0;g.types.length=0}}),setData:function(a,b){this.clearData(a);this._items.add(b,a)},getData:function(a){for(var b=this._items.length;b--&&this._items[b].type!==a;);return 0<=b?this._items[b]._data:null},clearData:function(a){for(var b=this._items.length;b--&&this._items[b].type!==a;);this._items.remove(b)},setDragImage:function(a){}};'items'in DataTransfer.prototype&&(g.items=g._items);e=f.getBoundingClientRect();h(p,'dragstart',t,function(){var a=f.getBoundingClientRect();m=a.left+u-e.left;n=a.top+v-e.top;h(f,'dragenter',1,function(){h(f,'dragover',t,function(){f=l.elementFromPoint(m,n);h(f,'drop',1,function(){h(p,'dragend',1,function(){})})})})})"

def drag_and_drop(driver, source, target=None, offsetX=0, offsetY=0, delay=25, key=None) :
  driver.execute_script(JS_DRAG_AND_DROP, source, target, offsetX, offsetY, delay, key)
  time.sleep(delay * 2 / 1000)

driver = webdriver.Chrome()
driver.get("http://the-internet.herokuapp.com/drag_and_drop")


# drag and drop Glass
source = driver.find_element_by_xpath("//*[@id='column-a']")
target = driver.find_element_by_xpath("//*[@id='column-b']")
drag_and_drop(driver, source, target)

【讨论】:

  • 我认为您的 JS_DRAG_AND_DROP 函数有一个小错误:在 _items.add 函数中,您希望将 _data 设置为 ' '+a,而不是设置为 _data,因为这不存在并引发错误 - - add:function(a,b){ this[this.length]={ _data:''+a, kind:'string', type:b, getAsFile:function(){}, getAsString:function(a){ a(this._data) } }; g.types.push(b) }, --- 也许你可以做一个多行字符串
【解决方案2】:

我希望下面的代码可以解决您在 Java 中遇到的问题

public class darganddropTest {

public static void main(String[] args) {

// TODO Auto-generated method stub

System.setProperty("webdriver.chrome.driver","./chromedriver_win32/chromedriver.exe");

WebDriver driver = new ChromeDriver();

driver.get("https://jqueryui.com/droppable/");

System.out.println(driver.findElements(By.tagName("iframe")).size());

driver.switchTo().frame(driver.findElement(By.className("demo-frame")));

driver.findElement(By.id("draggable")).click();

Actions a = new Actions(driver);

WebElement drag = driver.findElement(By.id("draggable"));

WebElement drop = driver.findElement(By.id("droppable"));

a.dragAndDrop(drag, drop).build().perform();

driver.switchTo().defaultContent();

}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    相关资源
    最近更新 更多