Eu estou usando PHP 7.1.33
e "fabpot/goutte": "^3.2"
. Meu arquivo compositor é semelhante ao seguinte:
{
"name": "ubuntu/workspace",
"require": {
"fabpot/goutte": "^3.2"
},
"authors": [
{
"name": "admin",
"email": "[email protected]"
}
]
}
Estou tentando obter detalhes por um intervalo de tempo em uma página da Web, mas luto para passar os $crawler
valores para minha matriz de resultados finais $res1Array
.
Eu tentei o seguinte:
<?php
require 'vendor/autoload.php';
use Goutte\Client;
use Symfony\Component\DomCrawler\Crawler;
/**
* Crawls Detail Calender
* Does NOT also include wanted Date in the final result set
* @param $wantedDate
* @return array
*/
function updateCalendarDetailsData($wantedDate)
{
try {
$client = new Client();
/*
$x = 1;
$LIMIT = 3;
global $x;
global $LIMIT;
$x++;
*/
$res1Array = array();
$ffUrlArr = ["https://www.forexfactory.com/calendar.php?month=Jan2020"];
foreach ($ffUrlArr as $key => $v) {
try {
$crawler = $client->request('GET', $ffUrlArr[$key]);
} catch (\Exception $ex) {
error_log($ex);
}
$TEMP = array();
// $count = $crawler->filter('.calendar_row')->count();
// $i = 1; // count starts at 1
$nodeDate = date('Y-m-d');
$crawler->filter('.calendar_row')->each(function ($node) use (&$res1Array, $wantedDate, $nodeDate) { // $count, $i,
$EVENT = array();
// check date for month
$dayMonth = str_split(explode(" ", trim($node->getNode(0)->nodeValue))[0], 3);
$day = explode(" ", trim($node->getNode(0)->nodeValue))[1];
if (is_numeric($day)) {
$nodeDate = date("Y-m-d H:i:s", strtotime($dayMonth[0] . " " . $dayMonth[1] . " " . $day));
}
// return if wanted date is reached
if (date("Y-m-d", strtotime($nodeDate)) == date("Y-m-d", strtotime($wantedDate))) {
return $res1Array;
}
$EVENTID = $node->attr('data-eventid');
$API_RESPONSE = file_get_contents('https://www.forexfactory.com/flex.php?do=ajax&contentType=Content&flex=calendar_mainCal&details=' . $EVENTID);
$API_RESPONSE = str_replace("<![CDATA[", "", $API_RESPONSE);
$API_RESPONSE = str_replace("]]>", "", $API_RESPONSE);
$html = <<<HTML
<!DOCTYPE html>
<html>
<body>
$API_RESPONSE
</body>
</html>
HTML;
$subcrawler = new Crawler($html);
$subcrawler->filter('.calendarspecs__spec')->each(function ($LEFT_TD) use (&$res1Array, &$TEMP, &$EVENT) {
$LEFT_TD_INNER_TEXT = trim($LEFT_TD->text());
if ($LEFT_TD_INNER_TEXT == "Source") {
$TEMP = array();
$LEFT_TD->nextAll()->filter('a')->each(function ($LINK) use (&$TEMP) {
array_push($TEMP, $LINK->text(), $LINK->attr('href'));
});
$EVENT['sourceTEXT'] = $TEMP[0];
$EVENT['sourceURL'] = $TEMP[1];
$EVENT['latestURL'] = $TEMP[3];
}
if ($LEFT_TD_INNER_TEXT == "Measures") {
$EVENT['measures'] = $LEFT_TD->nextAll()->text();
}
if ($LEFT_TD_INNER_TEXT == "Usual Effect") {
$EVENT['usual_effect'] = $LEFT_TD->nextAll()->text();
}
if ($LEFT_TD_INNER_TEXT == "Frequency") {
$EVENT['frequency'] = $LEFT_TD->nextAll()->text();
}
if ($LEFT_TD_INNER_TEXT == "Why Traders") {
$EVENT['why_traders_care'] = $LEFT_TD->nextAll()->text();
}
if ($LEFT_TD_INNER_TEXT == "Derived Via") {
$EVENT['derived_via'] = $LEFT_TD->nextAll()->text();
// array_push($res1Array, $EVENT); // <---- HERE I GET THE ERROR!
}
});
/*
$i++;
if ($i > $count) {
echo "<pre>";
var_dump($res1Array);
print_r($res1Array);
echo "</pre>";
exit;
}
*/
});
}
} catch (\Exception $ex) {
error_log($ex);
}
return $res1Array;
}
var_dump(updateCalendarDetailsData(date("2020-01-02")));
Como você pode ver, estou tentando criar $EVENT
e enviar todos os valores desejados como pares de valores-chave para dentro. Quando terminar, quero empurrá-lo para a $resArray
obtenção da seguinte estrutura (os valores array()
são apenas para fins estruturais):
[
sourceTEXT => "test",
sourceURL => "test",
latestURL => "test",
measures => "test",
usual_effect => "test",
derived_via => "test",
why_traders_care => "test",
frequency => "test"
],
[
sourceTEXT => "test1",
sourceURL => "test1",
latestURL => "test1",
measures => "test1",
usual_effect => "test1",
derived_via => "test1",
why_traders_care => "test1",
frequency => "test1"
],
[
sourceTEXT => "test2",
sourceURL => "test2",
latestURL => "test2",
measures => "test2",
usual_effect => "test2",
derived_via => "test2",
why_traders_care => "test2",
frequency => "test2"
],
// ...
Atualmente, não recebo nada de volta no meu $res1Array
.
Eu aprecio muito suas respostas!
ATUALIZAR
Eu executei o script a partir do @tftd com o "fabpot/goutte": "^4.0"
que obtive:
array(94) {
[0] =>
array(10) {
'eventId' =>
string(6) "114340"
'date' =>
string(10) "2020-01-01"
'sourceTEXT' =>
NULL
'sourceURL' =>
NULL
'latestURL' =>
NULL
'measures' =>
NULL
'usual_effect' =>
NULL
'derived_via' =>
NULL
'why_traders_care' =>
NULL
'frequency' =>
NULL
}
[1] =>
array(10) {
'eventId' =>
string(6) "114341"
'date' =>
string(10) "2020-01-01"
'sourceTEXT' =>
NULL
'sourceURL' =>
NULL
'latestURL' =>
NULL
'measures' =>
NULL
'usual_effect' =>
NULL
'derived_via' =>
NULL
'why_traders_care' =>
NULL
'frequency' =>
NULL
}
[2] =>
array(10) {
'eventId' =>
string(6) "114342"
'date' =>
string(10) "2020-01-01"
'sourceTEXT' =>
NULL
'sourceURL' =>
NULL
'latestURL' =>
NULL
'measures' =>
NULL
'usual_effect' =>
NULL
'derived_via' =>
NULL
'why_traders_care' =>
NULL
'frequency' =>
NULL
}
[3] =>
array(10) {
'eventId' =>
string(6) "114343"
'date' =>
string(10) "2020-01-01"
'sourceTEXT' =>
NULL
'sourceURL' =>
NULL
'latestURL' =>
NULL
'measures' =>
NULL
'usual_effect' =>
NULL
'derived_via' =>
NULL
'why_traders_care' =>
NULL
'frequency' =>
NULL
}
[4] =>
array(10) {
'eventId' =>
string(6) "114328"
'date' =>
string(10) "2020-01-01"
'sourceTEXT' =>
NULL
'sourceURL' =>
NULL
'latestURL' =>
NULL
'measures' =>
NULL
'usual_effect' =>
NULL
'derived_via' =>
NULL
'why_traders_care' =>
NULL
'frequency' =>
NULL
}
[5] =>
array(10) {
'eventId' =>
string(6) "113632"
'date' =>
string(10) "2020-01-01"
'sourceTEXT' =>
NULL
'sourceURL' =>
NULL
'latestURL' =>
NULL
'measures' =>
NULL
'usual_effect' =>
NULL
'derived_via' =>
NULL
'why_traders_care' =>
NULL
'frequency' =>
NULL
}
[6] =>
array(10) {
'eventId' =>
string(6) "114308"
'date' =>
string(10) "2020-01-01"
'sourceTEXT' =>
NULL
'sourceURL' =>
NULL
'latestURL' =>
NULL
'measures' =>
NULL
'usual_effect' =>
NULL
'derived_via' =>
NULL
'why_traders_care' =>
NULL
'frequency' =>
NULL
}
// ...
Alguma sugestão de por que recebo todos esses valores nulos?
fonte
2020-01-02
em uma matriz que contém os dados da linha. Isso está correto?now() - 2020/01-18
(que não faz parte do exemplo acima, pois ele começa no início e vai até uma certa data, no entanto, eu poderia pular linhas indesejadas) . Meu grande problema é que recebo de volta uma matriz vazia. Forneça um exemplo completo de trabalho.file_get_contents()
ou$client->request()
. Por exemplo, tente encontrar o ID do evento 113606Respostas:
Tomei a liberdade de reescrever um pouco seu código usando OOP, em vez de deixá-lo funcional, porque é muito mais fácil focar em bits menores do código. Deve ser fácil convertê-lo em codificação funcional, caso você precise.
Essa classe leva um
date
formato formatadoJan2020
para poder obter o calendário.Para obter os eventos para um intervalo de datas nos registros do calendário - é necessário ligar
$parser->getEventsBetweenDates()
com astartDate
e anendDate
. As horas não são levadas em consideração durante a análise, mas você pode adicioná-lo se precisar. Aqui está um exemplo:O resultado do código acima é:
Aqui está o código completo:
fonte
Uncaught Error: Call to undefined method Symfony\Component\DomCrawler\Crawler::closest()
. Quais versões das bibliotecas você está executando? (Compositer.json) Por favor, adicione uma correção e eu vou aceitar a sua resposta!php 7.1
php 7.3
mas isso não deve importar. Eu acho que você pode ter uma versão mais antigafabpot/goutte
- a minha év4.0.0
. EDIT: Acabei de notar na sua pergunta que você apontou que está usando^3.2
. Seria possível atualizar para4.0
?111392
verá todos os campos preenchidos. Onull
valor em outros registros é simplesmente porque não existe um rótulo do qual você possa obter os dados.symfony/dom-crawler
(que é de onde aCrawler
classe vem) com versões^4.4
ou^5.0
. Esta função existe nos dois releases (verifique os links). Eu suspeito que algo pode estar errado do seu lado - eu tentei com as duas versões e funciona. Talvez verifique com ocomposer show -i
que está realmente instalado?Ainda estou trabalhando no código que você forneceu, mas uma das primeiras coisas que percebi é antes de você definir
$API_RESPONSE
, você tem as seguintes linhas de código ...Nesse ponto da função, você ainda não enviou nenhum dado para
$res1Array
que ele retornasse apenas uma matriz vazia. Não é até o$subcrawler
(e a segunda tentativa de retornar$res1Array
) em que você está realmente enviando informações para a matriz.Nota: atualizarei minha resposta assim que eu trabalhar com o restante do código, na esperança de fornecer uma solução mais completa para o seu problema.
fonte
break
oforeach
ciclo. Ele apenas "ignora" a execução do restante do código da função.Eu recomendo que você se atenha ao seu código. É menor, mais simples e mais familiar para você.
Fiz uma revisão do seu código. Você pode encontrar meus comentários marcados com "***".
Além disso, você pode salvar esse código e compará-lo com sua versão original em alguma ferramenta diff.
Na verdade, você tinha apenas 4 pequenos bugs.
fonte