我想解决的问题如下:
我需要通过PHP管理外部网页,例如登录,然后在我自己的网站上发送ajax请求后更改外部网站上的个人资料信息。
为此,我从PHP调用PhantomJS来执行这些任务,但在登录外部Web之前,我需要填写验证码输入。因此,我想将Captcha图像发送回我的网站,编写正确的代码并将其发送回PhantomJS的WebPage模块,以便使用该代码登录。
换句话说,我需要一个同步的'程序是这样的:
1)PHP - >发送登录请求并获取验证码图像。
2)PhantomJS - >打开WebPage实例并将验证码代码渲染为图像。
3)PHP - >获取验证码图像,将其显示给用户并将文本输入发送到PhantomJS。
4)PhantomJS - >从PHP获取文本代码,使用' page.evaluate'填充验证码输入。并登录。向PHP发送一些数据('登录成功','登录失败'等)
5)PHP - >获取回调并发送另一个任务或数据。
callback = 'Login successfull' --> Change profile picture or update user info.
callback = 'Login failed' --> Try to login again (like point 1)
等等...
有许多事情我不知道如何处理。例如:
1)如何保持WebPage模块打开并等待验证码的文本代码?如果我关闭它,下次会出现一个新的验证码,我需要一种方法来等待代码并获得它。我需要为此启动服务器吗?
2)从PHP获取验证码图像不是问题(因为' page.render'),但我如何将文本发送回PhantomJS的WebPage实例?我认为最好在两个系统之间双向发送数据。我需要一台服务器吗?
我想在PhantomJS中需要一个套接字服务器(如何做到这一点?)。这个服务器应该有我需要保持打开的WebPage实例,但我对此并不完全确定。
感谢。
答案 0 :(得分:1)
我最近发布了一个项目,可以让PHP访问浏览器。得到它:https://github.com/merlinthemagic/MTS,引擎盖是PhantomJS的一个实例。
主要问题是在初始执行后保持资源存活。这是我建议你这样做的方式。
下载并设置后,您只需使用以下代码:
开始"设置"会话:
if (isset($_POST['sessionUID']) === false) {
//set the execution timeout long enough to cover the entire process (setup and working time), it dictates when phantomJS shuts down automatically.
ini_set('max_execution_time', 300);
//open the login page:
$myUrl = "http://www.example.com";
$browserObj = \MTS\Factories::getDevices()->getLocalHost()->getBrowser('phantomjs');
//allow the page to live after php shuts down.
$browserObj->setKeepalive(true);
$windowObj = $browserObj->getNewWindow($myUrl);
//find the username input box, here it has id=username
$windowObj->mouseEventOnElement("[id=username]", 'leftclick');
//type your username
$windowObj->sendKeyPresses("yourUsername");
//find the password input box, here it has id=passwd
$windowObj->mouseEventOnElement("[id=passwd]", 'leftclick');
//type your password
$windowObj->sendKeyPresses("yourPassword");
//click on the login button, here it has id=login
$windowObj->mouseEventOnElement("[id=login]", 'leftclick');
//i assume this is when you encounter the CAPTCHA image
//find the CAPTCHA image element, here it has id=captchaImage
$element = $windowObj->getElement("[id=captchaImage]");
$loc = $element['location'];
//tell the screenshot to only get the CAPTCHA image
$windowObj->setRasterSize($loc['top'], $loc['left'], ($loc['right'] - $loc['left']), ($loc['bottom'] - $loc['top']));
$imageData = $windowObj->screenshot("png");
$sessionUID = uniqid();
$saveWindowObj = serialize($windowObj);
//save the window object so we can pick it up again
file_put_contents("/tmp/" . $sessionUID, $saveWindowObj);
}
//now render the CAPTCHA image to the user as part of a form they can resubmit and make sure to keep the $sessionUId as a hidden variable in the form on the page
"设置"结束会话,php在这里关闭。
开始"工作"会议: 我们假设用户提交表单,它是一个包含$ sessionUID和CAPTCHA文本字符串的帖子。
if (isset($_POST['sessionUID']) === true && isset($_POST['captchaTxt']) === true) {
$savedWindow = file_get_contents("/tmp/" . $sessionUID);
//delete the saved object
unlink("/tmp/" . $sessionUID);
//bring back the object to life
$windowObj = unserialize($savedWindow);
//make sure the browser is now shutdown on exit
$windowObj->getBrowser()->setKeepalive(false);
//find the CAPTCHA input box, here it has id=captchaInput
$windowObj->mouseEventOnElement("[id=captchaInput]", 'leftclick');
//type the CAPTCHA string
$windowObj->sendKeyPresses($_POST['captchaTxt']);
//click on the button to accept CAPTCHA, here it has id=captchaOK
$windowObj->mouseEventOnElement("[id=captchaOK]", 'leftclick');
//now use the clickElement() etc functions on $windowObj to do what you need to do.
}
结束"工作"会话,php在这里关闭。