Capture and reduce values of multiple divs and inputs

2

I got it with the help of @ QMechanic73 , make a parser on a remote site, and capture the values between the span tags that are within several div with their given id , and span with their class and values between your tags , I had to capture and lower the original values by -20% , the code looks 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();

Ok, everything worked fine and according to what I wanted, but then I saw that for the site to retrieve this information I need to change more than the values of span , I need to change the 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 to be changed are the input of class= "decValue" and class= "betCode" and if possible also class = "originalBetCode" . The input field with class decValue is simpler, as we only need to decrease by 20% as in the span fields.

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

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

If we want the value to be 3.2 , we will have to decrease this by 1 , and multiply 2.2 by 5 in> for example, and the result obtained 11 be sent to BetCode as follows: 11 ~ 5 , 11 is the total value, divided by 5 which is our automatic script multiplier +1 original.

So I want to do this by adapting the @QMechanic73 script, sorry for the long explanation, but I wanted some help on how to do it! Anyone have an idea? if possible, a limiter so that if a value decremented by 20% gives only cents, it returns the value 1.00 for example; the original value is 1.20 , if I decrease by 20% it would be 0.96 , which would go wrong, then PHP would parse the numbers it would come below 1.00 and raise it to 1.00 .

I know it's extensive, it's annoying, but I really need your help. Thank you in advance!

    
asked by anonymous 24.02.2015 / 19:58

2 answers

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

This warning message is thrown when the HTML being parsed contains two or more identical identifiers, in which case the isOffered , an ID is a unique identifier, as quoted this page of W3 , every time this attribute is used in a document it must have a different value.

To ignore this type of error you can use the libxml_use_internal_errors , using it with the true parameter will disable the 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 libxml_clear_errors function is used to clean the > of the php.net/manual/en/book.libxml.php">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 is ignored.

The partial problem has already been handled, now the other part of the problem, to change the value of the input of the betCode , originalBetCode and DecValue classes, we will first have to get the values of those classes and then replace them with a value that we wish.

$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 values of the value field of the decValue class, in the variable betCodes the values of the% > betCode and even with the originalBetCodes variable.

If value does not return any results your return value will be false , a Boolean value and consequently an error message will be thrown when trying to navigate it with query .

To handle this possible error, use the foreach before trying to use a array , as I'm sure the is_array " will return results I will not use it, but here is some information.

From now on you only have to go through these variables and make the necessary calculations, the function query of query returns an object DomXpath " which in turn implements the DOMNodeList , to convert it to an array function Transversable and later used in a multidimensional array . 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 iterator_to_array and save the file with the changes made with file_get_contents .

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

Here there is an adapted example of the above code.

    
27.02.2015 / 20:49
0

Does not work because this HTML is invalid: "There can not be two entities with the same id."

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

libxml_use_internal_errors(true) AND libxml_clear_errors();

    
26.02.2015 / 00:24