Check element exists using PHP Selenium 2 Webdriver? - php

I am trying to check if an element on a page exists by CSS using Selenium 2. Anyone have any examples using PHP Selenium Webdriver Facebook wrapper?
I have tried the below code:
if($driver->findElement(WebDriverBy::xpath("image-e4e")) != 0)
{
}
But gives me this error:
Fatal error: Uncaught exception 'NoSuchElementWebDriverError' with
message 'Unable to locate element:
{"method":"xpath","selector":"image-e4e"}

By design, findElement returns the WebDriverElement if it is found but it throws an exception when it is not found.
To check whether the element is on the page without getting an exception, the trick is to use findElements. findElements returns an array of all elements found on the page. It returns an empty array if nothing is found.
if (count($driver->findElements(WebDriverBy::xpath("image-e4e"))) === 0) {
echo 'not found';
}

Use: $driver->findElements intstead of findElement
findElements will return an empty array if element not exists and will not throw an exception.

You can also use the sizeof() builtin function in PHP:
$check = $driver->findElements(WebDriverBy::xpath('image-e4e'));
if (sizeof($check) > 0) {
echo "success";
}
OR can also be used to count() function:
if (count($driver->findElements(WebDriverBy::xpath('image-e4e'))) > 0) {
echo "success";
}
Output: If XPath element is available on a page then it will give you success
If you want to use findElement then:
$checkXpath = 'image-e4e';
$checkXpath = $this->findElementByXpath($driver, $checkXpath);
$check = $driver->findElement($checkXpath);
if (count($check) > 0) {
echo "success";
}
OR
$checkXpath = WebDriverBy::xpath('image-e4e');
$check = $driver->findElement($checkXpath);
if (count($check) > 0) {
echo "success";
}
Output: If XPath element is available on a page then it will give you success
Note: The findElement method throws a NoSuchElementException exception when the element is not available on the page. Whereas, the findElements method returns an empty list when the element is not available or doesn't exist on the page.

That's because your xpath is bad.
If you want to continue using xpath, then your seletor would be
//*[#id='image-e4e']
If you have an open mind, get used to CSS Selectors. They are faster and much more readable
WebDriverBy::cssSelector("#image-e4e")
This is of course assuming that the ID is image-e4e. The reason your xpath was failing was because xpath was attempting to locate an immedate child with tag name image-e4e. you want to parse the entire pom for an element with an attribute that equals image-e4e. Whether that's ID or name, I do not know.

if($driver->findElement(WebDriverBy::id("image-e4e")) != 0)
{
}
Try the above logic I am sure definitely it will work out.

Related

PHP - Simple HTML DOM Parser - Getting FATAL ERROR when html is OK

I am trying to parse a table and output the a plaintext in another table. I have gotten this far:
<?php
if (url_exists($url))
{
$html = file_get_html($url);
}
else
{
echo "URL doesn't exist.";
}
if ($html && is_object($html) && isset($html->nodes))
{
// Everything checks out
$table = $html->find('table[border]');
if (!empty($table))
{
$row = $table->find('tr');
}
}
else
{
echo "Fetched page is not ok.";
}
?>
This returns an error:
Fatal error: Call to a member function find() on a non-object in /var/www/html/jsudimak/mailman/webdev-test1.php on line 78
Line 78 is this one: $row = $table->find('tr');
This means that :
the html is valid
the table I am trying to parse is also valid
Therefore, I am bewildered by the fact that the find() method is still returning this error.
I have looked into the cause of this error extensively for the past few days and I have yet to find a solution. I have also tried some other parsing tools no still no luck. Help me with this fellow debuggers!!!!
By the way, I am using the Simple HTML Dom Parser to parse the table.
Use $table = $html->find('table[border]')[0];
The documentation says that, unless you specify an index in the function find(), it will return an array

image_container remains null therefore it throws the error? [duplicate]

I am using this library (PHP Simple HTML DOM parser) to parse a link, here's the code:
function getSemanticRelevantKeywords($keyword){
$results = array();
$html = file_get_html("http://www.semager.de/api/keyword.php?q=". urlencode($keyword) ."&lang=de&out=html&count=2&threshold=");
foreach($html->find('span') as $e){
$results[] = $e->plaintext;
}
return $results;
}
but I am getting this error when I output the results:
Fatal error: Call to a member function find() on a non-object in
/var/www/vhosts/efamous.de/subdomains/sandbox/httpdocs/getNewTrusts.php
on line 25
(line 25 is the foreach loop), the odd thing is that it outputs everything (at least seemingly) correctly but I still get that error and can't figure out why.
The reason for this error is: the simple HTML DOM does not return the object if the size of the response from url is greater than 600000.
You can void it by changing the simple_html_dom.php file. Remove strlen($contents) > MAX_FILE_SIZE from the if condition of the file_get_html function.
This will solve your issue.
You just need to increase CONSTANT MAX_FILE_SIZE in file simple_html_dom.php.
For example:
define('MAX_FILE_SIZE', 999999999999999);
This error usually means that $html isn't an object.
It's odd that you say this seems to work. What happens if you output $html?
I'd imagine that the url isn't available and that $html is null.
Edit:
Looks like this may be an error in the parser. Someone has submitted a bug and added a check in his code as a workaround.
Before file_get_html/load_file method, you should first check if URL exists or not.
If the URL exists, you pass one step.
(Some servers, service a 404 page a valid HTML page. which has propriate HTML page structure like body, head, etc. But it has only text "This page couldn'!t find. 404 error bla bla..)
If URL is 200-OK, then you should check whether fetched thing is object and whether nodes are set.
That's the code i used in my pages.
function url_exists($url){
if ((strpos($url, "http")) === false) $url = "http://" . $url;
$headers = #get_headers($url);
// print_r($headers);
if (is_array($headers)){
if(strpos($headers[0], '404 Not Found'))
return false;
else
return true;
}
else
return false;
}
$pageAddress='http://www.google.com';
if ( url_exists($pageAddress) ) {
$htmlPage->load_file( $pageAddress );
} else {
echo 'url doesn t exist, i stop';
return;
}
if( $htmlPage && is_object($htmlPage) && isset($htmlPage->nodes) )
{
// do your work here...
} else {
echo 'fetched page is not ok, i stop';
return;
}
For those arriving here via a search engine (as I did), after reading the info (and linked bug-report) above, I started some code-prodding and ended up fixing my problems with 2 extra checks after loading the dom;
$html = file_get_html('<your url here>');
// first check if $html->find exists
if (method_exists($html,"find")) {
// then check if the html element exists to avoid trying to parse non-html
if ($html->find('html')) {
// and only then start searching (and manipulating) the dom
}
}
I'm having the same error come up in my logs and apart from the solutions mentioned above, it could also be that there is no 'span' in the document. I get the same error when searching for divs with a particular class that doesn't exist on the page, but when searching for something that I know exists on the page, the error doesn't pop up.
your script is OK.
I receive this error when it doase not find the element that i'm looking for on that page.
In your case, please check if the page that you are accessing it has 'SPAN' element
Simplest solution to this problem
if ($html = file_get_html("http://www.semager.de/api/keyword.php?q=". urlencode($keyword) ."&lang=de&out=html&count=2&threshold=") {
} else {
// do something else because couldn't find html
}
Error means, the find() function is either not defined yet or not available. Make sure you have loaded or include related function.

PHP return value after XML exploration

I got a PHP array with a lot of XML users-file URL :
$tab_users[0]=john.xml
$tab_users[1]=chris.xml
$tab_users[n...]=phil.xml
For each user a <zoom> tag is filled or not, depending if user filled it up or not:
john.xml = <zoom>Some content here</zoom>
chris.xml = <zoom/>
phil.xml = <zoom/>
I'm trying to explore the users datas and display the first filled <zoom> tag, but randomized: each time you reload the page the <div id="zoom"> content is different.
$rand=rand(0,$n); // $n is the number of users
$datas_zoom=zoom($n,$rand);
My PHP function
function zoom($n,$rand) {
global $tab_users;
$datas_user=new SimpleXMLElement($tab_users[$rand],null,true);
$tag=$datas_user->xpath('/user');
//if zoom found
if($tag[0]->zoom !='') {
$txt_zoom=$tag[0]->zoom;
}
... some other taff here
// no "zoom" value found
if ($txt_zoom =='') {
echo 'RAND='.$rand.' XML='.$tab_users[$rand].'<br />';
$datas_zoom=zoom($r,$n,$rand); } // random zoom fct again and again till...
}
else {
echo 'ZOOM='.$txt_zoom.'<br />';
return $txt_zoom; // we got it!
}
}
echo '<br />Return='.$datas_zoom;
The prob is: when by chance the first XML explored contains a "zoom" information the function returns it, but if not nothing returns... An exemple of results when the first one is by chance the good one:
// for RAND=0, XML=john.xml
ZOOM=Anything here
Return=Some content here // we're lucky
Unlucky:
RAND=1 XML=chris.xml
RAND=2 XML=phil.xml
// the for RAND=0 and XML=john.xml
ZOOM=Anything here
// content founded but Return is empty
Return=
What's wrong?
I suggest importing the values into a database table, generating a single local file or something like that. So that you don't have to open and parse all the XML files for each request.
Reading multiple files is a lot slower then reading a single file. And using a database even the random logic can be moved to SQL.
You're are currently using SimpleXML, but fetching a single value from an XML document is actually easier with DOM. SimpleXMLElement::xpath() only supports Xpath expression that return a node list, but DOMXpath::evaluate() can return the scalar value directly:
$document = new DOMDocument();
$document->load($xmlFile);
$xpath = new DOMXpath($document);
$zoomValue = $xpath->evaluate('string(//zoom[1])');
//zoom[1] will fetch the first zoom element node in a node list. Casting the list into a string will return the text content of the first node or an empty string if the list was empty (no node found).
For the sake of this example assume that you generated an XML like this
<zooms>
<zoom user="u1">z1</zoom>
<zoom user="u2">z2</zoom>
</zooms>
In this case you can use Xpath to fetch all zoom nodes and get a random node from the list.
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$zooms = $xpath->evaluate('//zoom');
$zoom = $zooms->item(mt_rand(0, $zooms->length - 1));
var_dump(
[
'user' => $zoom->getAttribute('user'),
'zoom' => $zoom->textContent
]
);
Your main issue is that you are not returning any value when there is no zoom found.
$datas_zoom=zoom($r,$n,$rand); // no return keyword here!
When you're using recursion, you usually want to "chain" return values on and on, till you find the one you need. $datas_zoom is not a global variable and it will not "leak out" outside of your function. Please read the php's variable scope documentation for more info.
Then again, you're calling zoom function with three arguments ($r,$n,$rand) while the function can only handle two ($n and $rand). Also the $r is undiefined, $n is not used at all and you are most likely trying to use the same $rand value again and again, which obviously cannot work.
Also note that there are too many closing braces in your code.
I think the best approach for your problem will be to shuffle the array and then to use it like FIFO without recursion (which should be slightly faster):
function zoom($tab_users) {
// shuffle an array once
shuffle($tab_users);
// init variable
$txt_zoom = null;
// repeat until zoom is found or there
// are no more elements in array
do {
$rand = array_pop($tab_users);
$datas_user = new SimpleXMLElement($rand, null, true);
$tag=$datas_user->xpath('/user');
//if zoom found
if($tag[0]->zoom !='') {
$txt_zoom=$tag[0]->zoom;
}
} while(!$txt_zoom && !empty($tab_users));
return $txt_zoom;
}
$datas_zoom = zoom($tab_users); // your zoom is here!
Please read more about php scopes, php functions and recursion.
There's no reason for recursion. A simple loop would do.
$datas_user=new SimpleXMLElement($tab_users[$rand],null,true);
$tag=$datas_user->xpath('/user');
$max = $tag->length;
while(true) {
$test_index = rand(0, $max);
if ($tag[$test_index]->zoom != "") {
break;
}
}
Of course, you might want to add a bit more logic to handle the case where NO zooms have text set, in which case the above would be an infinite loop.

How to find tag name using phpquery?

I am using phpquery to extract some data from a webpage. I need to identify the menu of the page. My implementation is to find each element that has sibilings > 0 and last-child is an "a". My code is:
foreach($this->doc['*'] as $tagObj){
$tag = pq($tagObj);
if(count($tag->siblings()) > 0){
if($tag->find(":last-child")->tagName === "a")
echo trim(strip_tags($tag->html())) . "<br/>";
}
}
However, I am not getting any output because of
$tag->find(":last-child")->tagName
which isn't returning anything. What would be the reason for this?
I don't know this library but perhaps something like this
$siblings = $tag->siblings();
if (($siblingCount = count($siblings)) && $siblings[$siblingCount - 1]->tagName === 'a') {
echo ...
}
You can do it in reverse check for a:last-child :
For example :
foreach($this->doc['*'] as $tagObj){
$tag = pq($tagObj);
if(count($tag->siblings()) > 0){
if($tag->find("a:last-child"))
echo trim(strip_tags($tag->html())) . "<br/>";
}
}
This will check for the a tag of last-child and you can get its content easily.
May this help you.
Maybe you should use :last instead of :last-child
According to the library Google Page:
$li = null;
$doc['ul > li']
->addClass('my-new-class')
->filter(':last') // <--- :last
->addClass('last-li')
// save it anywhere in the chain
->toReference($li);
Because phpQueryObject returned by pq implements the Iterator and uses a public array $elements to store all elements, we need to get the element using the get() function, which returns a DOMElement that is has the tagName and nodeName properties:
$q = phpQuery::newDocumentHTML('<div><span class="test-span">Testing test</span></div>');
echo $q->find('.test-span')->get(0)->tagName; // outputs "span"
//echo $q->find('.test-span')->get(0)->nodeName; // outputs "span"
Both properties will output the tag name that has the test-span class which of course is span.

SimpleHtmlDOM, PHP, Fatal Error: Call to a member function find() on a non-object in C:\xampp\htdocs [duplicate]

I am using this library (PHP Simple HTML DOM parser) to parse a link, here's the code:
function getSemanticRelevantKeywords($keyword){
$results = array();
$html = file_get_html("http://www.semager.de/api/keyword.php?q=". urlencode($keyword) ."&lang=de&out=html&count=2&threshold=");
foreach($html->find('span') as $e){
$results[] = $e->plaintext;
}
return $results;
}
but I am getting this error when I output the results:
Fatal error: Call to a member function find() on a non-object in
/var/www/vhosts/efamous.de/subdomains/sandbox/httpdocs/getNewTrusts.php
on line 25
(line 25 is the foreach loop), the odd thing is that it outputs everything (at least seemingly) correctly but I still get that error and can't figure out why.
The reason for this error is: the simple HTML DOM does not return the object if the size of the response from url is greater than 600000.
You can void it by changing the simple_html_dom.php file. Remove strlen($contents) > MAX_FILE_SIZE from the if condition of the file_get_html function.
This will solve your issue.
You just need to increase CONSTANT MAX_FILE_SIZE in file simple_html_dom.php.
For example:
define('MAX_FILE_SIZE', 999999999999999);
This error usually means that $html isn't an object.
It's odd that you say this seems to work. What happens if you output $html?
I'd imagine that the url isn't available and that $html is null.
Edit:
Looks like this may be an error in the parser. Someone has submitted a bug and added a check in his code as a workaround.
Before file_get_html/load_file method, you should first check if URL exists or not.
If the URL exists, you pass one step.
(Some servers, service a 404 page a valid HTML page. which has propriate HTML page structure like body, head, etc. But it has only text "This page couldn'!t find. 404 error bla bla..)
If URL is 200-OK, then you should check whether fetched thing is object and whether nodes are set.
That's the code i used in my pages.
function url_exists($url){
if ((strpos($url, "http")) === false) $url = "http://" . $url;
$headers = #get_headers($url);
// print_r($headers);
if (is_array($headers)){
if(strpos($headers[0], '404 Not Found'))
return false;
else
return true;
}
else
return false;
}
$pageAddress='http://www.google.com';
if ( url_exists($pageAddress) ) {
$htmlPage->load_file( $pageAddress );
} else {
echo 'url doesn t exist, i stop';
return;
}
if( $htmlPage && is_object($htmlPage) && isset($htmlPage->nodes) )
{
// do your work here...
} else {
echo 'fetched page is not ok, i stop';
return;
}
For those arriving here via a search engine (as I did), after reading the info (and linked bug-report) above, I started some code-prodding and ended up fixing my problems with 2 extra checks after loading the dom;
$html = file_get_html('<your url here>');
// first check if $html->find exists
if (method_exists($html,"find")) {
// then check if the html element exists to avoid trying to parse non-html
if ($html->find('html')) {
// and only then start searching (and manipulating) the dom
}
}
I'm having the same error come up in my logs and apart from the solutions mentioned above, it could also be that there is no 'span' in the document. I get the same error when searching for divs with a particular class that doesn't exist on the page, but when searching for something that I know exists on the page, the error doesn't pop up.
your script is OK.
I receive this error when it doase not find the element that i'm looking for on that page.
In your case, please check if the page that you are accessing it has 'SPAN' element
Simplest solution to this problem
if ($html = file_get_html("http://www.semager.de/api/keyword.php?q=". urlencode($keyword) ."&lang=de&out=html&count=2&threshold=") {
} else {
// do something else because couldn't find html
}
Error means, the find() function is either not defined yet or not available. Make sure you have loaded or include related function.

Categories