Skip to content

amhoho/php-webdriver

This branch is 20 commits ahead of, 443 commits behind php-webdriver/php-webdriver:main.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

7c8e733 · Dec 3, 2018
Dec 3, 2018
Jan 7, 2017
Oct 18, 2018
Jan 7, 2017
Feb 1, 2016
Feb 8, 2018
Mar 14, 2018
May 28, 2018
May 29, 2018
Nov 27, 2017
Jun 16, 2018
Jan 7, 2017
Oct 18, 2018
Dec 3, 2018
Mar 14, 2018
Oct 18, 2018
Dec 11, 2017
Feb 24, 2017

Repository files navigation

版本:

Latest commit 2dbfa70 on 19 Oct

改动文件:

修改addArguments

文件:/facebook/webdriver/lib/Chrome/ChromeOptions.php

新增TakeScreenshotByElement

文件:/facebook/webdriver/lib/Remote/RemoteWebDriver.php

环境安装

curl -sS https://getcomposer.org/installer | php
composer config -g repo.packagist composer https://packagist.phpcomposer.com
sudo mv composer.phar /usr/local/bin/composer
yum remove zip 
yum remove unzip 
yum install zip unzip php7.2-zip //7.2为对应版本
composer require ext-simplexml
php函数取消禁用
composer require facebook/webdriver
yum install php-xml 
yum install php-dom
service httpd restart
//安装驱动:
yum install java-1.8.0-openjdk(版本可通过yum search java | grep -i --color JDK查询)
前往http://selenium-release.storage.googleapis.com/index.html下载standalone selenium
并上传为/www/collector/collector.jar
前往https://sites.google.com/a/chromium.org/chromedriver/downloads并上传为/usr/bin/chromedriver
yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
chmod -R 777 /usr/bin/chromedriver
chmod -R 777 /usr/bin/chrome
chmod -R 777 /usr/bin/xvfb-firefox
export PATH="$PATH:/usr/local/chromedriver"
export JAVA_HOME=/usr/lib/jvm/jre-1.8.0-openjdk
export PATH=$JAVA_HOME/bin:$PATH:/www/server/mysql/bin:/www/server/apache/bin
source /etc/profile
yum install bitmap-fonts bitmap-fonts-cjk
yum provides */libgconf-2.so.4
yum install GConf2
yum install Xvfb -y
yum install xorg-x11-fonts* -y
yum -y install http://linuxdownload.adobe.com/linux/x86_64/adobe-release-x86_64-1.0-1.noarch.rpm
yum install flash-plugin
yum -y install *-fonts-*

//环境完成
/etc/rc.d/rc.local文件加入:
nohup /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -jar /www/collector/collector.jar
ln -s /etc/alternatives/google-chrome /usr/bin/chrome

安装测试:(截图test.png出现即成功)

namespace Facebook\WebDriver;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
require_once('vendor/autoload.php');
$caps = DesiredCapabilities::chrome();
$options = new ChromeOptions();
$addArguments=[
'enableImages'=> false, //禁止图像,可加速
'windowSize'=>[1920, 1000],//窗口尺寸
'isMobile'=>true,//使用使用移动端UA
'userDataDir'=>'/www/collector/data/'//如果往页面调试跨域js等信息必须.随便空目录路径
//'proxy'=>'127.0.0.1:8000'//代理
];
$options->addArguments($addArguments);
$caps->setCapability(ChromeOptions::CAPABILITY, $options);
$driver = RemoteWebDriver::create('http://127.0.0.1:4444/wd/hub', $caps, 5000);
$driver->get('https://baidu.com');
echo "The title is '" . $driver->getTitle() . "'\n";
echo "The current URI is '" . $driver->getCurrentURL() . "'\n";
$driver->takeScreenshot('./test.jpg');
$driver->quit();

API使用集合:

1. 启动浏览器与设置代理

<?php
namespace Facebook\WebDriver;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
require_once('vendor/autoload.php');

//启动参数
$options = new ChromeOptions();
$addArguments=[
'windowSize'=>[1920, 6000],//窗口尺寸
'userAgent'=>'your UA',
'userDataDir'=>'/www/collector/data/'//如果往页面调试跨域js等信息必须.随便空目录路径
'proxy'=>'127.0.0.1:8000'//代理
'other'=>[]//其它一些参数组成的数组
];
$options->addArguments($addArguments);

//启动时加载指定扩展
$options->addExtensions(array(
'/path/to/chrome/extension1.crx',
'/path/to/chrome/extension2.crx',
));

//启动预设,例如下载目录
$prefs = ['download.default_directory' => 'c:/temp'];
$options->setExperimentalOption('prefs', $prefs);

//启动浏览器
$caps = DesiredCapabilities::chrome();
$caps ->setPlatform('Linux');
//这是一个刚补的坑,此处必须setPlatform
//否则将因`--disable-gpu`导致出现"Curl error thrown for http POST to /session with params"
//通常这个错误是因为url为空,jar未启动,或chrome未启动.

//除了上方的代理方式还可以用这个
$caps = [
    WebDriverCapabilityType::BROWSER_NAME => 'chrome',
    WebDriverCapabilityType::PROXY => [
        'proxyType' => 'manual',
        'httpProxy' => '127.0.0.1:2043',
        'sslProxy' => '127.0.0.1:2043',
    ]
];

$caps->setCapability(ChromeOptions::CAPABILITY, $options);
$driver = RemoteWebDriver::create('http://127.0.0.1:4444/wd/hub', $caps, 5000);
//超时处理
$driver->manage()->timeouts()->pageLoadTimeout(10);
try {
$driver->get('https://www.google.com');
} catch (TimeOutException $e) {
//something
}

2. 窗口,会话,alert,iframe

//取得当前窗口句柄(句柄为每个窗口的唯一ID)
$handle = $driver->getWindowHandle();

//取得所有窗口的句柄为数组
$handles = $driver->getWindowHandles();

//切换到指定句柄的窗口
$driver->switchTo()->window($handle);

//比较有用的一点:每一次点击后应该切换到最新的一个窗口,比如_blank的时候就获得新窗口的句柄了.
$submitButton->click();
$driver->switchTo()->window(end($driver->getWindowHandles()));

//创建新标签页
$driver->getKeyboard()->sendKeys(array(WebDriverKeys::CONTROL, 't'));

//创建新窗口
$driver->getKeyboard()->sendKeys(array(WebDriverKeys::CONTROL, 'n'));

//最大化浏览器
$driver->manage()->window()->maximize();

//获得当前url
$driver->getCurrentURL();

//获得源码
$driver->getPageSource();

//命令参数
$driver->getCommandExecutor()

//前进,后退,刷新
$linkElement = $this->driver->findElement(WebDriverBy::id('a-form'));
$linkElement->click();//点击链接a-form等待浏览器打开/form
$driver->wait()->until(WebDriverExpectedCondition::urlContains('/form'));

$driver->navigate()->back();//从/form后退回/index
$driver->wait()->until(WebDriverExpectedCondition::urlContains('/index'));

$driver->navigate()->forward();//从/index前进至/form
$driver->wait()->until(WebDriverExpectedCondition::urlContains('/form'));

$driver->navigate()->refresh();//刷新一下

//获得会话ID
$driver->getSessionID();

//所有的会话
$driver->getAllSessions();

//退出驱动
$driver->close();
$driver->quit();

//等待alert弹出
$this->driver->wait()->until(WebDriverExpectedCondition::alertIsPresent(), 'I am expecting an alert!',);

//确定alert
$driver->switchTo()->alert()->accept(); 

//取消alert
$driver->switchTo()->alert()->dismiss();

//取得alert正文
$message =$driver->switchTo()->alert()->getText();

//回应alert,如(你的名字是?,此时回应test)
$driver->switchTo()->alert()->sendKeys('test'); 

//按元素ID或内容查找iframe
$iframe = $driver->findElement(WebDriverBy::id('my_frame'));
$iframe = $driver->findElement(WebDriverBy::tagName('iframe'));

//获取iframe的属性
$frameId = $iframe->getAttribute('id');

//切至指定ID的iframe,这样就可以操作iframe中的内容了,比如点击之类
$driver->switchTo()->frame($frameId);

//切回主框架
$driver->switchTo()->defaultContent(); 

//切至focus元素,没有切至body
$active_element = $driver->switchTo()->activeElement();

3.Dom元素

//筛选元素
WebDriverBy::cssSelector('h1.foo > small');//按Css选择器
WebDriverBy::xpath('(//hr)[1]/following-sibling::div[2]');//按Xpath
WebDriverBy::id('heading');//按ID
WebDriverBy::className('warning');//按className
WebDriverBy::name('email');//按input的name
WebDriverBy::tagName('h1');//按tagName比如h1,div,span
WebDriverBy::linkText('测试链接');//按链接所在文本,如<a href>测试链接</a>
WebDriverBy::partialLinkText('测试');//按部分匹配链接所在文本,如<a href>测试链接</a>

//替换元素内容
$driver->findElement(WebDriverBy::id("element id"))->sendKeys("新文本");

//清空元素内容
$driver->findElement(WebDriverBy::id("element id"))->clear();

//如何检查元素是否可见
$element = $driver->findElement(WebDriverBy::id('element id'));
if ($element->isDisplayed()){
    // do something...
}

//获取指定元素的属性值
$title = $driver->findElement(WebDriverBy::id('signin'))->getAttribute('title');

//获取input的值
$value  = $driver->findElement(WebDriverBy::id('username'))->getAttribute('value');

//获取指定元素文本
$result = $driver->findElement(WebDriverBy::id('signin'))->getText();

//获取css的值
$elementWithBorder =$this->driver->findElement(WebDriverBy::id('text-simple')->getCSSValue('display')

//获得尺寸
$elementSize = $element->getSize();

//清空
$input->clear();
$textarea->clear();

//是否可输入
$input->isEnabled();

//获得坐标
$element->getLocation();
$elementLocation->getX();
$elementLocation->getY();

//获得元素数组
$elements = $driver->findElements(WebDriverBy::cssSelector('ul.foo > li'));
foreach ($elements as $element) {
    var_dump($element->getText());
}

4.内容的等待(隐性等待和显性等待)

//隐性等待:对任何人都永远坚持'30秒内你不能来,我就去接别人了.你来了我们立马开车'.
//这种原则性的事情在启动浏览器时说一次就够了.
$driver->manage()->timeouts()->implicitlyWait(30);
//接下来不管等谁,我都最多只等30秒,比如get.
$driver->get('https://www.baidu.com/');
//虽然方便,但我不推荐这个,因为等的人要是没来又去接别人,最后就得丢三落四不齐全.


//显示等待:30秒内你不能来,我就抛个异常罢工了,也不接别人了.来了还是立马走,下文都是这样.

格式:
//等待标题匹配
$driver->wait()->until( WebDriverExpectedCondition::titleIs('My Page'));
//按500ms的频率循环,最多等待10秒
$driver->wait(10, 500)->until(WebDriverExpectedCondition::titleIs('My Page'));

类似WebDriverExpectedCondition::titleIs()的还有:

//等待标题
titleIs()
titleContains()
titleMatches()

//等待URL
urlIs()
urlContains()
urlMatches()

//等待元素文本或value
presenceOfElementLocated()
presenceOfAllElementsLocatedBy()
elementTextIs()
elementTextContains()
elementTextMatches()
textToBePresentInElementValue()

//等待元素或其可见性
visibilityOfElementLocated()
visibilityOf()//注意该方法前提是dom中已存在该元素,等待的是可见性,而不是元素本身.
invisibilityOfElementLocated()
invisibilityOfElementWithText()

//框架,alert,窗口
frameToBeAvailableAndSwitchToIt()
elementToBeClickable()
alertIsPresent()
numberOfWindowsToBe()

//还有这些
stalenessOf()
refreshed()
not()
elementToBeSelected()
elementSelectionStateToBe()

//还可以自定义,下文等待 li.foo 的数量超过5个.
$driver->wait()->until(
   function () use ($driver) {
       $elements = $driver->findElements(WebDriverBy::cssSelector('li.foo'));
       return count($elements) > 5;
   },
   '未定位到5个以上的li.foo'
);

5. 鼠标的操作:

//MouseOver在指定元素上
$element = $driver->findElement(WebDriverBy::id('some_id'));
$driver->getMouse()->mouseMove( $element->getCoordinates());

//单击元素(链接,复选框等)
$driver->findElement(WebDriverBy::id('signin'))->click();

6. 截图

//整页截图
$driver->takeScreenshot('./00001.jpg');

//局部截图:实际是从整页截图中按元素的x,y,width,height截取,通常用于如验证码之类的截图.
$findElement=$driver->findElement(WebDriverBy::xpath("//img[@class='test']"));
$screenshot_of_element = $driver->TakeScreenshotByElement($findElement,'./1.jpg');

7. 日志

$caps->setCapability( 'loggingPrefs', ['browser' => 'ALL']);
$driver->manage()->getLog('driver');//driver,browser,server

8. Cookie

//获取
$driver->manage()->getCookieNamed('CookieName');
$driver->manage()->getCookies();
//设置
$driver->manage()->addCookie(['CookieName'=>'CookieValue']);
//删除或清空
$driver->manage()->deleteCookieNamed('CookieName');
$driver->manage()->deleteAllCookies();

9.Js的操作

//执行js,全局加上window.
$sScriptResult = $driver->executeScript('return window.document.location.hostname',array());

//滚动到底部
$driver->executeScript("window.scrollTo(0,document.body.scrollHeight)");
//滚动到顶部
$driver->executeScript("window.scrollTo(0,0)");

//执行异步js
$driver->executeAsyncScript('return window.document.location.hostname',array());

//异步,5秒后无结果则取消,全局加上window.
$driver->timeouts()->async_script(array('ms'=>5000));

//从js中断并返回php
$sResult = $driver->executeAsyncScript('arguments[arguments.length-1]("done");', array());
if($sResult =='done'){
//do something;
}

//js定时轮询
$sJavascript = <<<END_JAVASCRIPT
var callback = arguments[arguments.length-1], //返回php驱动的callback
    nIntervalId; //setInterval的名称
//测试定时
function checkDone() {
  if( window.MY_STUFF_DONE ) {
    window.clearInterval(nIntervalId);//清除clearInterval
    callback("done"); //执行回调
  }
}
nIntervalId = window.setInterval( checkDone,50); //定时轮询
END_JAVASCRIPT;
$sResult = $driver->executeAsyncScript($sJavascript,array());

//等待ajax提交后的回调并筛选元素
$submitButton = $driver->findElement(WebDriverBy::id('Submit'));
$submitButton->click();
waitForAjax($driver,'jquery'); 
//waitForAjax($driver, 'prototype');
//waitForAjax($driver, 'dojo');
$anotherButton = $driver->findElement(WebDriverBy::id('secondButton'));
function waitForAjax($driver, $framework='jquery')
{
    //不同框架
    switch($framework){
        case 'jquery':
            $code = "return jQuery.active;"; break;
        case 'prototype':
            $code = "return Ajax.activeRequestCount;"; break;
        case 'dojo':
            $code = "return dojo.io.XMLHTTPTransport.inFlight.length;"; break;
        default:
            throw new Exception('Not supported framework');
    }

    //按2000ms的频率循环,最多等待30秒
    $driver->wait(30, 2000)->until(
        function ($driver, $code) {
            return !$driver->executeScript($code);
        }
    );
}

10. select操作

示例Html:

<select name="language">
    <option value="cs">Czech</option>
    <option value="de">German</option>
    <option value="en_GB" selected>English (UK)</option>
    <option value="fr">French</option>
</select>
//找到<select>
$selectElement = $driver->findElement(WebDriverBy::name('language'));

//构造select
$select = new WebDriverSelect($selectElement);

//是否被选中
$select->isSelected();

//获得select的value
echo $select->getFirstSelectedOption()->getAttribute('value'); //"en_GB"
echo $select->getFirstSelectedOption()->getText(); //"English(UK)"

//获取所有<options>元素的数组
$options = $select->getOptions();

//获得所有已选中项组成的数组
$selectedOptions = $select->getAllSelectedOptions();

//各种方式选中
$select->selectByValue('fr');//按value
$select->selectByIndex(1); //按index
$select->selectByVisibleText('Czech');//按要选中Option的text内容
$select->selectByVisiblePartialText('UK'); //按要选中Option的text内容是否包含指定值'UK'

//还可以取消选中,比如全不选
$select->deselectAll();
$select->deselectByValue('...');
$select->deselectByIndex(0);
$select->deselectByVisibleText('...');
$select->deselectByVisiblePartialText('...');

//表单的提交
$formElement = $driver->findElement(WebDriverBy::cssSelector('form'));
$formElement->submit();

11. 表单文本上传

示例Html:

//示例:
<input type="file" id="file_input"></input>
//设置一个临时副本
  $remote_image = __DIR__ . '/tmp/image-'.time().'.jpg';
  copy('http://www.site.com/image/photo.jpg', $remote_image);
  
//获取上传框
  $fileInput = $driver->findElement(WebDriverBy::id('file_input'));
  
//设置文件类型
  $fileInput->setFileDetector(new LocalFileDetector());
  
//上传并提交
$fileInput->sendKeys($remote_image)->submit();

//删除临时副本
unlink($remote_image);

About

php驱动chrome

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 98.3%
  • HTML 1.7%