我一直在使用Selenium Webdriver for Python来自动执行我的工作中的一些日常任务。想要了解更多信息,我一直在使用Selenium在业余时间编写一些脚本。我已经取得了一些成功,但最近,在尝试为neopets.com制作机器人以进行日常活动时,我遇到了一个我无法在自动化方面获得任何牵引力的情景。
迷你游戏基本上只是一个随机确定的老虎机游戏,名为Trudy的惊喜(网址:http://www.neopets.com/trudys_surprise.phtml,您可能需要创建一个帐户才能访问它)。我想要完成的功能就是单击Selenium的“播放”按钮,或以其他方式执行插槽游戏。虽然这个功能非常简单,但在我看来(可能是因为我无法自行解决)这里有学习经验,因为解决方案并不像使用webelem.click()
那样简单。告诉。
我一直在使用Chrome的Inspect功能来查看游戏的底层脚本。如果您导航到老虎机游戏,请右键单击游戏框架中的任意位置,然后单击“检查”控制台应显示突出显示的<canvas>
元素。此<canvas>
元素位于<iframe>
内,我将在本文中引用该内容。
所以这就是我面临的问题(我试过的AKA事情不起作用):
我无法获得该按钮的xpath,因为游戏本身位于iframe内。我尝试使用driver.switch_to.frame()
函数浏览iframe中所有元素的列表,然后执行driver.find_elements_by_xpath("//*")
,并且只找到页面中描述的html元素(没有开始按钮)。
由于我找不到该元素,我想我会尝试复制它的效果。老虎机的源脚本位于http://www.neopets.com/trudydaily/js/slotsgame.js?v=1525633042。我会在这里复制它,但它很长。我几乎没有使用html或Javascript的经验,但似乎这个脚本是在iframe的标题中调用的
<script src="/trudydaily/js/slotsgame.js?v=1525633042">
</script>
创建一个SlotsGame对象,然后由iframe主体中的脚本调用。 SlotsGame对象只有三个可调用的成员函数:Initialize,LoadAssets和Start。它看起来像脚本发布jQuery并等待来自服务器的响应,允许用户根据响应旋转或不旋转。调用SlotsGame对象的脚本看起来像
var ajaxurl = '/trudydaily/ajax/claimprize.php';
//var data = {'action': 'getslotstate'};
var data = {
'action': 'getslotstate','key': '2nA6BqsTIM1IT785Di08dqyFKnLCM1M7VTcOfSnC41I%3D'};
var resp;
parent.$.post(ajaxurl, data, function (response){
resp = JSON.parse(response);
if(resp.error == ""){
SlotsGame.LoadAssets(AssetLoadComplete, "http://images.neopets.com");
}
else{
parent.CloseSlotsGame();
}
}
);
SlotsGame.Initialize();
function AssetLoadComplete(){
SlotsGame.Start(resp);
}
function CloseGame(){
parent.CloseSlotsGame();
};
每次加载页面时key
值都会更改。
来自driver.execute_script("SlotsGame.LoadAssets()")
和...Initialize()...
的呼叫都可以在iframe的上下文中调用(他们在iframe中创建了一个插槽游戏的副本),所以我知道我在正确的轨道上。但是,我尝试在iframe的上下文中执行SlotsGame.Start(i)
i=1,2,3
而不是骰子(或不是插槽)。我也尝试使用driver.execute_script(webelem.get_attribute('innerHTML'))
执行整个上述脚本,但没有任何反应。
我确信我错过了一种自动激活这台机器的简单方法,但我已经尝试了几乎所有我能想到的但没有成功。
对于任何不精确的术语或类似的道歉,我仍然试图选择这个技能。我希望了解html,Javascript和JSON的人会理解这个问题。如果您能想出我可以编辑问题的方式,请告诉我,以使其更精确或更普遍适用。提前感谢您的帮助。
答案 0 :(得分:0)
如果只有Selenium可以简化发布请求,这将非常简单。幸运的是,有一个软件包! https://github.com/cryzed/Selenium-Requests
import re
import time
from seleniumrequests import Firefox
from selenium.webdriver.support.ui import WebDriverWait as wait
# Selenium-Requests way of launching a browser instance
browser = Firefox()
然后在您登录后,
browser.get("http://www.neopets.com/trudys_surprise.phtml")
# Waits for trudys iframe to be loaded, and then switches to the iframe
wait(browser, 10).until(EC.frame_to_be_available_and_switch_to_it("frameTest"))
time.sleep(1)
# gets key from the iframe page_source; not the worlds best regex
matchobj = re.search(r"\'action\'\: \'\w*\',\'key\'\: \'(.*)\'\}\;", str(browser.page_source))
if(matchobj):
key = str(matchobj.group(1))
postPage = ('http://www.neopets.com/trudydaily/ajax/claimprize.php')
response = browser.request('POST', postPage, data={'action':'getslotstate','key':key})
time.sleep(2)
response = browser.request('POST', postPage, data={'action':'beginroll'})
time.sleep(2)
response = browser.request('POST', postPage, data={'action':'prizeclaimed'})
time.sleep(2)
# switches back from the iframe to the main window
browser.switch_to.default_content()