Capture and decrease values of multiple Ivs and inputs

Asked

Viewed 330 times

2

I got it with the help of @Qmechanic73 , make a parser on a remote site, and capture the values between the tags span that is within several div with his determined id, and the span with their class and values between their tags, had to capture and decrease the original values in -20%, the code looked exactly like this:

$opts = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Accept-language: en\r\n" .
              "Cookie: foo=bar\r\n"
  )
);
$context = stream_context_create($opts);
$html = file_get_contents('https://pt.sportingbet.com/services/InPlayApp.mvc/GetInPlaySports?CurrentOddsFormat=', false, $context);
$DOM =  new DOMDocument();
$DOM->loadHTML($html);

$xpath = new DomXpath($DOM);

$prices = $xpath->query('//*[contains(concat(" ", normalize-space(@class), " "), "priceText ")]');
$percent = 20.0 / 100.0; // 20%

foreach($prices as $price){
    $value = $price->nodeValue;
    $floatValue = floatval($value);
    $finalValue = $floatValue - ($percent * $floatValue);
    $price->nodeValue = $finalValue; // Salva o valor final com desconto de 20%
}
echo $DOM->saveHTML();

Okay, it all worked out cute and according to what I wanted, but then I saw that for the site to recover this information I need to change more than the values of span, need to change values between 2 fields input.

HTML

<div id="isOffered">      
    <a class="price  " href="javascript:;">
        <span class="priceText wide  UK">1/4</span>
        <span class="priceText wide  EU">1.25</span>
        <span class="priceText wide  US">-400</span>
        <span class="priceText wide  CH">1.25</span>
        <span class="priceChangeArrow" ></span>
        <input type="hidden" class="betCode" value="0]SK@84899932@323698807@NB*1~4*0*-1*0*0"/>
        <input type="hidden" class="decValue" value="1.25"/>
        <input type="hidden" class="originalBetCode" value="0]SK@84899932@323698807@NB*1~4*0*-1*0*0"/>
     </a>
</div>

<div class="market-item ">
    <div class="outright-label">Empate</div>
    <div class="outright-odds" title="Vencedor do Encontro">
    <div id="s_323698809" class="odds draw">   <div id="isNotOffered" class="hide">    
    <span class="price priceReadonly"></span>
</div>

<div id="isOffered">      
    <a class="price  " href="javascript:;">
        <span class="priceText wide  UK">3/1</span>
        <span class="priceText wide  EU">4.00</span>
        <span class="priceText wide  US">+300</span>
        <span class="priceText wide  CH">4.00</span>
        <span class="priceChangeArrow" ></span>
        <input type="hidden" class="betCode" value="0]SK@84899932@323698809@NB*3~1*0*-1*0*0"/>
        <input type="hidden" class="decValue" value="4.00"/>
        <input type="hidden" class="originalBetCode" value="0]SK@84899932@323698809@NB*3~1*0*-1*0*0"/>
    </a>
 </div></div>
 </div>
 </div>

The fields that need changing are the input of class= "decValue" and class= "betCode" and if possible also the class = "originalBetCode". The field input with the class of decValue is simpler because we just need to decrease in 20% as in the fields span.

But I want to turn my attention to input with the class = "BetCode" and originalBetCode, because I will need to change only the 2 numbers that are between ~, and to do this I will need to follow a esquema of calculations that will be like this:

I will have to capture every value obtained in span priceText EU already with the decrease of 20%, that is, if on the remote site the value is 2.30, the Qmechanic73 script will decrease in 20% as desired, then our value will remain 2.30 - 20% = 1.84, now I’ll have to take this 1.84 and decrease 1 from him, (I explain why in front), after decreasing this 1.84 for 1, I’ll have to catch the result 0.84 and multiply by a value fixed, which can be any number, I will then use the 5, then *0.84 * 5* shall be equal to 4.2, what will we do with this value? simple! send it to replace those two numbers in the field BetCode, only in the following way; if for example our code is value="0]SK@84899932@323698807@NB*1~4*0*-1*0*0" we will replace the 1 who is after the @NB by our multiplied value, which in this case is 4.2, and the 4 who is after the ~ is the divider, so if our multiplier always be 5, our divisor also will be, then we will replace the 1~4 for 4.2~5, why then we will get the result of 0.84, then this script will automatically add +1 in all the results obtained by our division!

If we want the value to be 3.2, we’ll have to narrow it down by 1, and multiply the 2.2 for 5 for example, and the result obtained 11 be sent to BetCode as follows: 11~5, 11 is the total value, divided by 5 who is our multiplier +1 automatic of the original script.

So I want to do this by adapting the @Qmechanic73 script, sorry for the long explanation, but I wanted a little help on how to do that! anyone have any idea? and if possible, a limiter, so that if a value decreased in 20% give only pennies, it returns the value 1.00 for example; the original value is 1.20, if I decrease in 20% he would stay 0.96, what would go wrong, then PHP would analyze the numbers that came under 1.00 and raise him to 1.00.

I know it’s long, it’s boring, but I really need your help. Thanks in advance guys

  • This is just a warning generated by PHP. Current code does not work?

  • It doesn’t work! it only works when you have a single div, since when there are many it generates this warning and does not return me anything.

  • 1

    @Cassianojosé I did something partial here but I have a question: what value do you want to take initially? the value of decValue or the value of priceText wide UK? in the question you mention that you want to decrease by 20% the value of both, which of the two enters the calculation operation?

  • @Qmechanic73, is from the field priceText wide EU, I made a mistake, but I edited it now. priceText wide UK always contains the same value as in betcode, type: if in div has 1/4 in the priceText UK, that means that in the betcode will have 1~4, was even trying to use the value obtained in the UK, replace the bar with ~, and do the search on betcode, but I didn’t get much. has PHP functions that I haven’t studied yet, there makes it difficult :(. but I hope it helps me do rs =D

2 answers

1


Warning: DOMDocument::loadHTML() [domdocument.loadhtml]: ID isOffered already defined in Entity

This warning message is issued when the HTML to be parsed contains two or more equal identifiers, in which case the isOffered, one ID is a unique identifier, as quoted on that page of W3, each time this attribute is used in a document it must have a different value.

To ignore this type of error you can use the function libxml_use_internal_errors, when using it with the parameter true you will disable the errors of libxml and enable error handling, for example:

<?php

libxml_use_internal_errors(true);
$doc = DOMDocument::load('file.xml');

if (!$doc){
    $errors = libxml_get_errors();
    foreach ($errors as $error) {
        // Tratar os erros manualmente aqui
    }
    libxml_clear_errors();
}

The function libxml_clear_errors is used to clean the buffer of errors of libxml. Another likely alternative is to use the error control operator, the sign @, when it precedes an expression, any error message that can be generated by that expression will be ignored.

The partial problem has already been dealt with, now the other part of the problem, to change the value of the elements input of the classes betCode, originalBetCode and Decvalue, first we have to get the values of these classes and then replace with a value we want.

$decValues = $xpath->query('//input[@class="decValue"]/@value');
$betCodes  = $xpath->query('//input[@class="betCode"]/@value');
$originalBetCodes = $xpath->query('//input[@class="originalBetCode"]/@value');

In the variable decValues will be the field values value class decValue, in the variable betCodes the field values will be stored value class betCode and even happens with the variable originalBetCodes.

Case to query return no result your return value will be false, one boolean value and consequently an error message will be sent when trying to travel it with the foreach.

To treat that possible error, use the function is_array before attempting to use a array, as I’m sure the query will return results I will not use it, but it is information here.

From now on just go through these variables and make the necessary calculations, the function query of DomXpath returns an object DOMNodeList which in turn implements the interface Transversable, to convert it into an object array function was used iterator_to_array and subsequently used in a multidimensional array. Just below is an example, based on what I could understand, I commented some passages.

<?php

$html = file_get_contents('GetInPlaySports.html'); //  
$outputFile = "GetInPlaySports2.html"; // Arquivo onde será salvo o HTML modificado
libxml_use_internal_errors(true);

$DOM =  new DOMDocument();
$DOM->loadHTML($html);
$xpath = new DomXpath($DOM);

$decValues = $xpath->query('//input[@class="decValue"]/@value'); // Obtem os campos "value" da classe "decValue"
$betCodes  = $xpath->query('//input[@class="betCode"]/@value');  // Obtem os campos "value" da classe "betCode"
$originalBetCodes = $xpath->query('//input[@class="originalBetCode"]/@value');  // Obtem os campos "value" da classe "originalBetCode"
// Uma array de arrays
$arrValues = array_map(null, iterator_to_array($decValues), 
                             iterator_to_array($betCodes),
                             iterator_to_array($originalBetCodes));

$percent = 20.0 / 100.0; 
$mult = 5;

foreach($arrValues as $value){
    $floatValue = floatval($value[0]->nodeValue); // Pega o valor de "decValue"
    $discountValue = $floatValue - ($percent * $floatValue);
    $expr = (((($discountValue < 1)? round($discountValue): $discountValue) - 1) * $mult);
    $finalValue = "*". $expr. "~". $mult. "*";

    $betValue = $value[1]->nodeValue; // Obtem o valor de "betCode"
    $repl = preg_replace('/\*(\d+)~(\d+)\*/', $finalValue, $betValue);
    $value[1]->nodeValue = $repl; // Atualiza o campo "value" da classe "betCode"
    $value[2]->nodeValue = $repl; // Atualiza o campo "value" da classe "originalBetCode"
}

libxml_clear_errors();
file_put_contents($outputFile, $DOM->saveHTML());
echo "Done!";

This example will receive a page with file_get_contents and save the file with the modifications made with the file_put_contents.

There is also a limiter, taking as an example the value 1.20 when subtracted there is a condition that will check whether the result is less than 1, in case it will be 0.96, through an Arredont condition we give this value to 1.00 with the use of the function round.

Here there is an adapted example of the above code.

  • @Cassianojosé I didn’t know. From what I read here this seems to be a good solution for what you seek!

  • Qmechanic73, but is it a part browser? I couldn’t get it right. .

0

It does not work because this HTML is invalid: "There cannot be two entities with the same id."

Anyway, if your problem is PHP errors, try adding this at the beginning of your code:

libxml_use_internal_errors(true) AND libxml_clear_errors();

Browser other questions tagged

You are not signed in. Login or sign up in order to post.