Selenium - iframe 的烦恼 - 无法解决
我在这个问题上纠结了很久,现在终于决定来这里求助。
我有一个包含iframe的页面:
<iframe frameborder="0" allowtransparency="true" tabindex="0" src="" title="Rich text editor, listing_description" aria-describedby="cke_18" style="width:100%;height:100%">
当我使用以下xpath获取元素时:
'//*[@aria-describedby="cke_18"]'
我得到了一个网页元素,如下所示:
>>> elem
<selenium.webdriver.remote.webelement.WebElement object at 0x104327b50>
>>> elem.id
u'{3dfc8264-71bc-c948-882a-acd6a8b93ab5}'
>>> elem.is_displayed
<bound method WebElement.is_displayed of <selenium.webdriver.remote.webelement.WebElement object at 0x104327b50>>
但是,当我尝试在这个iframe中提取信息时,出现了如下错误:
追踪记录(最近的调用在最前):
文件 "<stdin>",第 1 行,在 <module>
文件 "/Applications/Spyder.app/Contents/Resources/lib/python2.7/spyderlib/widgets/externalshell/sitecustomize.py",第 560 行,在 debugfile
debugger.run("runfile(%r, args=%r, wdir=%r)" % (filename, args, wdir))
文件 "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/bdb.py",第 400 行,在 run
exec cmd in globals, locals
文件 "<string>",第 1 行,在 <module>
文件 "/Applications/Spyder.app/Contents/Resources/lib/python2.7/spyderlib/widgets/externalshell/sitecustomize.py",第 540 行,在 runfile
execfile(filename, namespace)
文件 "/Users/jasonmellone/Documents/PythonProjects/nakedApts.py",第 88 行,在 <module>
a = elem.find_element_by_xpath(".//*")
文件 "/Library/Python/2.7/site-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webelement.py",第 201 行,在 find_element_by_xpath
return self.find_element(by=By.XPATH, value=xpath)
文件 "/Library/Python/2.7/site-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webelement.py",第 377 行,在 find_element
{"using": by, "value": value})['value']
文件 "/Library/Python/2.7/site-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webelement.py",第 370 行,在 _execute
return self._parent.execute(command, params)
文件 "/Library/Python/2.7/site-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/webdriver.py",第 166 行,在 execute
self.error_handler.check_response(response)
文件 "/Library/Python/2.7/site-packages/selenium-2.41.0-py2.7.egg/selenium/webdriver/remote/errorhandler.py",第 164 行,在 check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: 消息: u'无法找到元素: {"method":"xpath","selector":".//*"}' ; 堆栈跟踪:
在 FirefoxDriver.prototype.findElementInternal_ (file:///var/folders/8x/0msd5dd13l9453ff9739rj7w0000gn/T/tmpmH4ARe/extensions/fxdriver@googlecode.com/components/driver_component.js:8905)
在 FirefoxDriver.prototype.findChildElement (file:///var/folders/8x/0msd5dd13l9453ff9739rj7w0000gn/T/tmpmH4ARe/extensions/fxdriver@googlecode.com/components/driver_component.js:8917)
在 DelayedCommand.prototype.executeInternal_/h (file:///var/folders/8x/0msd5dd13l9453ff9739rj7w0000gn/T/tmpmH4ARe/extensions/fxdriver@googlecode.com/components/command_processor.js:10884)
在 DelayedCommand.prototype.executeInternal_ (file:///var/folders/8x/0msd5dd13l9453ff9739rj7w0000gn/T/tmpmH4ARe/extensions/fxdriver@googlecode.com/components/command_processor.js:10889)
在 DelayedCommand.prototype.execute/< (file:///var/folders/8x/0msd5dd13l9453ff9739rj7w0000gn/T/tmpmH4ARe/extensions/fxdriver@googlecode.com/components/command_processor.js:10831)
现在,我并不是一个selenium开发者,所以我对这个错误完全不懂。
当我运行以下代码时:
elem = Helper.getElementByxPath(mydriver,'//*[@aria-describedby="cke_18"]',"ABC");
mydriver.switch_to_frame(elem);
上面的代码可以运行,其中 Helper.getElementByxPath
是:
def getElementByxPath(mydriver,xPath,valueString):
try:
a = mydriver.find_element_by_xpath(xPath);
a.send_keys(valueString);
return a;
except:
print "Unexpected error:", sys.exc_info()[0];
return 0;
a = elem.find_element_by_xpath(".//*")
这给了我以下结果:
>>> elem.id
u'{8be4819b-f828-534a-9eb2-5b791f42b99a}'
而以下语句:
a = elem.find_element_by_xpath(".//*")
又给了我一个巨大的错误。
让我感到沮丧的是:
- 我并不需要从iframe中的嵌入输入框获取信息,我只是想发送键入。
- 我很乐意一直按“Keys.TAB”直到到达正确的输入框,然后用Cursor.location.element.send_keys(伪代码)。
- 我只想在页面上输入文本,因为光标已经在正确的位置(难道我不能简单地做到这一点吗?)
我的目标只是发送键入,而不是做更复杂的事情,但我似乎无法解决这个问题,结果总是出现上面的错误。
有没有办法解决这个问题?我感到很沮丧,希望有人能给我答案。
谢谢!
2 个回答
Selenium只能访问当前框架中的元素。如果你想切换到更深层的框架,可以这样做:
driver.switch_to_frame(IDENTIFIER)
这里的IDENTIFIER可以是:
- 框架的名称
- 指向框架的网页元素引用
- 框架的数字索引
你可以在这里查看API的详细信息:http://selenium-python.readthedocs.org/en/latest/api.html
当你在iframe
中完成操作后,可以用下面的代码切换回最顶层:
driver.switch_to_default_content()
解决我具体问题的代码片段如下:
elem = Helper.getElementByxPath(mydriver,".//iframe[@title='theTitleOfMyIframe']","ABC");
mydriver.switch_to_frame(elem);
elem2 = Helper.getElementByxPath(mydriver,"//body[@contentEditable='true']","ABC");
我的 xpath 函数是:
def getElementByxPath(mydriver,xPath,valueString):
try:
a = mydriver.find_element_by_xpath(xPath);
a.send_keys(valueString);
return a;
except:
print "Unexpected error:", sys.exc_info()[0];
return 0;
一旦你确认你的 ckeditor 在范围内,你就可以运行以下代码:
mydriver.execute_script(str("arguments[0].innerHTML = 'test'"), elem2)
这样应该就能像你预期的那样工作!希望这能帮助其他人节省时间!