I can not understand why only part of the links are returned without sleep(1); function. Although the script works synchronously and after $web_driver->executeScript the object is already loaded, all links have already been loaded.
<?php
require_once('vendor/autoload.php');
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
$caps = array("platform"=>"SIERRA", "browserName" => "chrome", "version" => "69");
$web_driver = RemoteWebDriver::create(
"http://localhost:4444/wd/hub",
$caps
);
$web_driver->get("https://winestyle.ru/wine/gerard-bertrand/");
$web_driver->executeScript('window.scrollTo(0,document.body.scrollHeight);');
sleep(1);
$element = $web_driver->findElements(WebDriverBy::cssSelector(".bg-text[title='Артикул']"));
foreach ($element as $e){
echo $e->getText().'<br>';
}
$web_driver->quit();
?>
return without sleep:
Артикул:в101222
Артикул:в99863
Артикул:в99981
Артикул:в101225
Артикул:в101212
Артикул:в101224
Артикул:в101211
Артикул:в92722
Артикул:в92723
Артикул:в101208
Артикул:в101210
Артикул:в99979
Артикул:в101223
Артикул:в101220
Артикул:в101213
Артикул:в101221
Артикул:в101227
Артикул:в101218
Артикул:в101217
Артикул:в101215
return with sleep:
Артикул:в101222
Артикул:в99863
Артикул:в99981
Артикул:в101225
Артикул:в101212
Артикул:в101224
Артикул:в101211
Артикул:в92722
Артикул:в92723
Артикул:в101208
Артикул:в101210
Артикул:в99979
Артикул:в101223
Артикул:в101220
Артикул:в101213
Артикул:в101221
Артикул:в101227
Артикул:в101218
Артикул:в101217
Артикул:в101215
Артикул:в101226
Артикул:в99980
Артикул:в85254
Артикул:в66382
Артикул:в66386
Артикул:в66387
Артикул:в85253
Артикул:в101214
Артикул:в101219
Most probably the page has implemented lazy loading - any extra information - new elements, are request through ajax only when the user scrolls to the end of the page.
And this is what's happening in your script - you've executed the js to scroll to the end. If you at that moment execute findElements without the sleep, the page would not have time to send the ajax request, wait for an parse the respone, and update the DOM. Thus you will get only the currently present elements.
With the sleep you give it that possibility.
Have in mind the hardcoded value 1s may sometimes work, and sometimes - not; if the backend takes more time to generate the response, or the network is slow - new data may not be received in time.
An alternative solution would be to poll the DOM for the number of target elements every X milliseconds, and continue once that number increases. This though must accommodate for the case where there are no more results (no more артикулы Russian? артикули Bulgarian? :), and to break out of the polling loop (could be done if there's a total results counter on the page, or similar).
Related
I've script which get some values from XML record.
There's code:
<?php
//Data
$xml_data = '<image_process_call><image_url>https://i.pinimg.com/originals/e4/41/54/e44154308e3466d987665c6d50887f06.jpg</image_url><methods_list><method><name>collage</name><params>template_name=Nun Face in Hole;</params></method></methods_list><result_format>jpg</result_format><result_size>800</result_size><template_watermark>false</template_watermark></image_process_call>';
//Settings
$app_id = '';
$key = '';
$sign_data = hash_hmac('SHA1', $xml_data, $key);
//Send request
$request_url = 'http://opeapi.ws.pho.to/addtask?data='. $xml_data .'&sign_data='. $sign_data .'&app_id='. $app_id;
$request_xml = simplexml_load_file($request_url);
$request_id = strval($request_xml -> request_id);
if (isset($request_id)) {
$result_url = 'http://opeapi.ws.pho.to/getresult?request_id='. $request_id;
sleep(6);
$result_xml = simplexml_load_file($result_url);
$result_status = strval($result_xml -> status);
$result_img = strval($result_xml -> result_url);
if (isset($result_img)) {
echo $result_img;
} else {
echo 'Result image not found';
}
} else {
echo 'Request ID not found';
}
?>
The problem depends on time to generate the second XML file. $result_xml took few seconds so I have to use sleep(6) function.
If I remove this, I need to refresh the page (minimum three times) to get a link to generated image from second XML.
Do you have an idea how to do it more professionally? I can't be sure that every image will be generated in 6 seconds (sometimes shorter sometimes longer).
Is there any method for genereting the result only after receiving $result_img? Thanks in advance for your help!
I think it is worth writing.
In practice, it looks like this:
Script does $request_xml and XML from site return:
<image_process_response>
<request_id>2d8d4dec-4344-4df0-a1e1-0c8df304ad11</request_id>
<status>OK</status>
<description/>
<err_code>0</err_code>
</image_process_response>
Script gets request_id from this XML and do $result_xml. However, this is XML and script doesn't get image's url immediately. It needs to wait a few seconds.
After three times refreshing the page or using sleep(6) function finally we get:
<image_process_response>
<request_id>2d8d4dec-4344-4df0-a1e1-0c8df304ad11</request_id>
<status>OK</status>
<result_url>
http://worker-images.ws.pho.to/i1/9F1E2EAF-5B31-4407-8779-9A85F35862D3.jpg
</result_url>
<result_url_alt>
http://worker-images.ws.pho.to.s3.amazonaws.com/i1/9F1E2EAF-5B31-4407-8779-9A85F35862D3.jpg
</result_url_alt>
<limited_image_url>
http://worker-images.ws.pho.to/i1/3F797C83-2C2E-401C-B4AF-C4D36BBD442D.jpg
</limited_image_url>
<nowm_image_url>
http://worker-images.ws.pho.to/i1/9F1E2EAF-5B31-4407-8779-9A85F35862D3.jpg
</nowm_image_url>
<duration>2950.879097ms</duration>
<total_duration>2956.124067ms</total_duration>
</image_process_response>
Edit:
After trying to immediately generate the image I get such an XML:
<image_process_response>
<request_id>e615f0a1-ddee-4d81-94c4-a392f8f123e8</request_id>
<status>InProgress</status>
<description>The task is in progress, you need to wait for sometime.</description>
</image_process_response>
So this is reason why I see blank page...
Do someone have an idea how to force a script to reconnect with the second XML until it finds a result_url?
The problem depends on time to generate the second XML file.
$result_xml took few seconds so I have to use sleep(6) function. If I
remove this, I need to refresh the page (minimum three times) to get a
link to generated image from second XML.
Do you have an idea how to do it more professionally? I can't be sure
that every image will be generated in 6 seconds (sometimes shorter
sometimes longer). Is there any method for genereting the result only
after receiving $result_img? Thanks in advance for your help!
According to Pho.to API, An add task request is a queued POST request.
In my opinion, Send request in while-loop, but wait for smaller time instead of fixed 6 seconds, Check the status in image_process_response, Keep looping until it is not InProgress, After that, You can safely send second request to get processed image result.
You may encounter timeout issue due to low timeout configuration for DoS protection if you run this script on web server (via CGI/FastCGI), To resolve this situation, You need a queue for adding task in your HTTP request, and then process it offline (means without web environment).
I'm trying to figure out a way to create a function to have the user be able to start a project by clicking a button and the timer would start. At the same time, I would like the user to be able to pause as well as stop the timer. When finished with a task, they can then hit 'Finished' to record the total amount of recorded time, minus any paused time, for the task to a variable in which I can record.
I have been researching and found that a Javascript timer wouldn't be very reliable which is why I wanted to go with Php. I figured I could take a Timestamp on 'Start' and 'Stop', but since I'm needing a 'Pause' as well, it's throwing a whole new kink into my plans.
Anyone know of a good way to accomplish this? I know that one Timestamp to another will get the total time, but how can you calculate one to another if the process had been paused?
I don't think "Javascript timer wouldn't be very accurate" is an accurate statement.
However, if you decide to use PHP, you will not be having the script running for the whole duration of the project. What you need is simply a number of markers in an object. You can store the object in a database table or as JSON string in a file. Here's an example using JSON:
[
[1440264185, "start"],
[1440280217, "pause"],
[1440288349, "resume"],
[1440292161, "pause"],
[1440317465, "resume"],
[1440325597, "stop"]
]
The object is built progressively with each event adding the timestamp of the signal received with the signal type (start, pause, resume, stop).
Then, when you want to calculate the amount of time spent working on the project/task you can use code like this:
$markers = json_decode($json_markers, true);
$num_markers = count($markers);
$markers[] = $markers[$num_markers-1];
$time_worked = 0;
for($i = 0; $i < $num_markers; $i++) {
if(in_array($markers[$i][1], array("start","resume"))) {
$time_worked += $markers[$i+1][0] - $markers[$i][0];
}
}
var_dump($time_worked); // int(27976)
Here's the code above.
I am making a php chat and am starting the php checking database part. So when a user types something into the chat, it gets recorded in the MySQL database, how would I check the database every 10 seconds so that one user's chat would update with new messages from other users. I know that you can use an ajax request to a page with an interval, but I want the php to be on the same page, instead of having to use numerous pages. This is the code for checking the database
<?php
$con = mysqli_connect('host','user','pass','database');
$query = mysqli_query($con,"SELECT * FROM `messages`");
while ($row=mysqli_fetch_assoc($query)) {
$user = $row['user'];
$message = $row['message'];
echo 'User: ',$user,' Message: ',$message;
}
?>
Thanks in advance anyone!
Use MySQL Event Scheduler.
Below link will guide you through .
http://www.9lessons.info/2012/10/mysql-event-scheduler.html.
I think best option in your case .
AJAX is probably the simplest solution. You can perform an AJAX request on the same page your PHP code is executing on if you really want to.
(function check() {
$.get('mypage.php', function(data) {
doSomethingWith(data);
setTimeout(check, 5000); // every 5 seconds
});
})();
PHP doesn't have a setInterval function. While I'm sure you can use a crontask to automate it on the server, you can also achieve this with some simple Javascript.
The concept you are trying to achieve is known as Short Polling. What you want to do is to have a setInterval function in Javascript that constantly makes AJAX requests to your PHP file which performs the check to the database for new messages. Your PHP should return that information to your script where you can then simply populate the user's screen.
There is also Long Polling where you simply maintain the connection and have a setTimeout to wait for messages to come in. You can find more information yourself and if you have questions, you can come back here.
A good video about this:
https://www.youtube.com/watch?v=wHmSqFor1HU
Hope this helps.
This is what you need. We need set time for ajax auto reload. Don't put everything in one page. Because you must reload page to refresh data. That is bad solution.
Call jQuery Ajax Request Each X Minutes
Make a while for 30 seconds, and check the db every second, once you find a record the while is being broken, also it is being broken when 30 secs are expired.
$sec = 1;
while($sec <= 30) {
if(has record)
Send to the user;
$sec++;
sleep(one sec here);
}
Use sleep for 10 secs in order to check every 10 secs...
Purely hypothetical at this point, no code yet. Trying to figure out the best way to do this. We are company "A" and we have two partners, company "B" and company "C". On a sign up form, we collect data and then pass it on to either partner "B" or parnter "C" - this part is good to go and working fine. I do this with ajax on the front end and a cURL processor on the back end so no one leaves our site and just post the data directly to the partner's form.
Unfortunately due to partner "B" and "C"'s required data the forms we post to are different and we have to have 2 separate html form files, one for each partner. The problem is that we need to do this all from one URL, not a separate one for each partner.
I would guess we would use a 'handler' page that has the specific url - http://www.example.com/parterForm.php
Then in the 'handler' page we would make the switch serve the correct content. I need a way to evenly split who we send data to. I'd like to do the switch on a very granular, MS level for example:
if the time = 0-500 ms - serve Parter B page;
if time = 501-1000ms -serve Partner C page;
all done within the 'handler' page - calling the forms as php includes?
I realize this is not a specific code question and I aplogize, this is something I've never done before and am trying to figure out how to do this. I'm a Creative Director btw who codes, no other resource avail.
thanks.
Hmm, yes, you could do that. That would work reasonably well, in fact. The important thing is to make sure the form goes to the right partner. You could use $_SESSION for that, or check which fields were sent and deduce from that which partner was chosen.
For example:
if( fmod(microtime(),1) < 0.5) include("forms/partner1.php");
else include("forms/partner2.php");
Then when submitted:
$partner1fields = array("name","email","country","dateofbirth");
$partner2fields = array("name","address","postcode","ethnicity");
// the above are examples - they should correspond to the $_POST keys you expect
// now check if they match. Array equality depends on order, so sort first
$postkeys = array_keys($_POST);
sort($postkeys);
sort($partner1fields);
sort($partner2fields);
if( $postkeys == $partner1fields) { /* submit to partner 1 */ }
elseif( $postkeys == $partner2fields) { /* submit to partner 2 */ }
else {
echo "<p>Given keys did not match either partner</p>";
echo "<p>POST keys: ".implode(", ",$postkeys)."</p>";
echo "<p>Partner 1 keys: ".implode(", ",$partner1keys)."</p>";
echo "<p>Partner 2 keys: ".implode(", ",$partner2keys)."</p>";
echo "<p>Please report this error to the site administrator.</p>";
exit;
}
First, by MS I assume you mean the latency between client and server?
Use javascript to either load a tiny image from the server or make an ajax call that gets one char or something and time this. For testing you'll need to do some real pings and adjust your js time to reflect the ping round trip. For example, if the js time to load the image is 500ms but ping time is only 80ms then maybe divide by 6 for the result. This will never be very precise as the client and the server both have processing overhead. Make sure to echo no cache headers or past expire times with the image or ajax response.
Easy, if time <= 500 redirect to form A, if time > 500 redirect to form B or use ajax to load them up.
Ever stumbled on a tutorial that you feel is of great value but not quite explained properly? That's my dilemma. I know THIS TUTORIAL has some value but I just can't get it.
Where do you call each function?
Which function should be called
first and which next, and which
third?
Will all functions be called in all files in an application?
Does anyone know of a better way cure the "Back Button Blues"?
I'm wondering if this will stir some good conversation that includes the author of the article. The part I'm particularly interested in is controlling the back button in order to prevent form duplicate entries into a database when the back button is pressed. Basically, you want to control the back button by calling the following three functions during the execution of the scripts in your application. In what order exactly to call the functions (see questions above) is not clear from the tutorial.
All forwards movement is performed by
using my scriptNext function. This is
called within the current script in
order to activate the new script.
function scriptNext($script_id)
// proceed forwards to a new script
{
if (empty($script_id)) {
trigger_error("script id is not defined", E_USER_ERROR);
} // if
// get list of screens used in this session
$page_stack = $_SESSION['page_stack'];
if (in_array($script_id, $page_stack)) {
// remove this item and any following items from the stack array
do {
$last = array_pop($page_stack);
} while ($last != $script_id);
} // if
// add next script to end of array and update session data
$page_stack[] = $script_id;
$_SESSION['page_stack'] = $page_stack;
// now pass control to the designated script
$location = 'http://' .$_SERVER['HTTP_HOST'] .$script_id;
header('Location: ' .$location);
exit;
} // scriptNext
When any script has finished its
processing it terminates by calling my
scriptPrevious function. This will
drop the current script from the end
of the stack array and reactivate the
previous script in the array.
function scriptPrevious()
// go back to the previous script (as defined in PAGE_STACK)
{
// get id of current script
$script_id = $_SERVER['PHP_SELF'];
// get list of screens used in this session
$page_stack = $_SESSION['page_stack'];
if (in_array($script_id, $page_stack)) {
// remove this item and any following items from the stack array
do {
$last = array_pop($page_stack);
} while ($last != $script_id);
// update session data
$_SESSION['page_stack'] = $page_stack;
} // if
if (count($page_stack) > 0) {
$previous = array_pop($page_stack);
// reactivate previous script
$location = 'http://' .$_SERVER['HTTP_HOST'] .$previous;
} else {
// no previous scripts, so terminate session
session_unset();
session_destroy();
// revert to default start page
$location = 'http://' .$_SERVER['HTTP_HOST'] .'/index.php';
} // if
header('Location: ' .$location);
exit;
} // scriptPrevious
Whenever a script is activated, which
can be either through the scriptNext
or scriptPrevious functions, or
because of the BACK button in the
browser, it will call the following
function to verify that it is the
current script according to the
contents of the program stack and take
appropriate action if it is not.
function initSession()
// initialise session data
{
// get program stack
if (isset($_SESSION['page_stack'])) {
// use existing stack
$page_stack = $_SESSION['page_stack'];
} else {
// create new stack which starts with current script
$page_stack[] = $_SERVER['PHP_SELF'];
$_SESSION['page_stack'] = $page_stack;
} // if
// check that this script is at the end of the current stack
$actual = $_SERVER['PHP_SELF'];
$expected = $page_stack[count($page_stack)-1];
if ($expected != $actual) {
if (in_array($actual, $page_stack)) {// script is within current stack, so remove anything which follows
while ($page_stack[count($page_stack)-1] != $actual ) {
$null = array_pop($page_stack);
} // while
$_SESSION['page_stack'] = $page_stack;
} // if
// set script id to last entry in program stack
$actual = $page_stack[count($page_stack)-1];
$location = 'http://' .$_SERVER['HTTP_HOST'] .$actual;
header('Location: ' .$location);
exit;
} // if
... // continue processing
} // initSession
The action taken depends on whether
the current script exists within the
program stack or not. There are three
possibilities:
The current script is not in the $page_stack array, in which case it is
not allowed to continue. Instead it is
replaced by the script which is at the
end of the array.
The current script is in the
$page_stack array, but it is not the
last entry. In this case all
following entries in the array are
removed.
The current script is the last entry
in the $page_stack array. This is
the expected situation. Drinks all
round!
That is a good discussion but more to the point you should be looking into Post Redirect Get (PRG) also known as "Get after Post."
http://www.theserverside.com/patterns/thread.tss?thread_id=20936
If you do not understand my article then you should take a close look at figure 1 which depicts a typical scenario where a user passes through a series of screens – logon, menu, list, search, add and update. When I describe a movement of FORWARDS I mean that the current screen is suspended while a new screen is activated. This happens when the user presses a link in the current screen. When I describe a movement as BACKWARDS I mean that the user terminates the current screen (by pressing the QUIT or SUBMIT button) and returns to the previous screen, which resumes processing from where it left off. This may include incorporating any changes made in the screen which has just been terminated.
This is where maintaining a page stack which is independent of the browser history is crucial – the page stack is maintained by the application and is used to verify all requests. These may be valid as far as the browser is concerned, but may be identified by the application as invalid and dealt with accordingly.
The page stack is maintained by two functions:
scriptNext() is used to process a
FORWARDS movement, which adds a new
entry at the end of the stack and
activates the new entry.
scriptPrevious() is used to process
a BACKWARDS movement, which removes
the last entry from the stack and
re-activates the previous entry.
Now take the situation in the example where the user has navigated to page 4 of the LIST screen, gone into the ADD screen, then returned to page 5 of the LIST screen. The last action in the ADD screen was to press the SUBMIT button which used the POST method to send details to the server which were added to the database, after which it terminated automatically and returned to the LIST screen.
If you therefore press the BACK button while in page 5 of the LIST screen the browser history will generate a request for the last action on the ADD screen, which was a POST. This is a valid request as far as the browser is concerned, but is not as far as the application is concerned. How can the application decide that the request is invalid? By checking with its page stack. When the ADD screen was terminated its entry was deleted from the page stack, therefore any request for a screen which is not in the page stack can always be treated as invalid. In this case the invalid request can be redirected to the last entry in the stack.
The answers to your questions should therefore be obvious:
Q: Where do you call each function?
A: You call the scriptNext()
function when the user chooses to
navigate forwards to a new screen,
and call the scriptPrevious()
function when the user terminates
the current screen.
Q: Which function should be called
first and which next, and which
third?
A: Each function is called in
response to an action chosen by the
user, so only one function is used
at a time.
Q: Will all functions be called in
all files in an application?
A: All functions should be available
in all files in an application, but
only called when chosen by the user.
It you wish to see these ideas in action then you can download my sample application.
The part I'm particularly interested in is controlling the back button in order to prevent form duplicate entries into a database when the back button is pressed.
Your premise is wrong. There is no such thing as "Back Button Blues", if you design your application as a web application. If you design your application without any server side state, you will never run into this problem in the first case. This minimalistic approach to web applications works remarkably well, and is usually known as REST.
# troelskn
If you design your application without any server side state ....
It is not possible to design an effective application which does not have state, otherwise all you have is a collection of individual pages which do not communicate with each other. As maintaining state on the client is fraught with issues there is no effective alternative but to maintain state on the server.
#Marston.
I solved the problem with post/redirect/get but I believe the tutorial has some merit and perhaps Tony Marston can elaborate on it. And how it could be used to solve not necessarily my particular problem but perhaps something similar. Or how is it better than post/redirect/get if the functions can in fact be used in solving my particular problem. I think this will be a good addition to the community here.
if ($_POST) {
process_input($_POST);
header("Location: $_SERVER[HTTP_REFERER]");
exit;
}