Estoy usando PHP 7.1.33
y "fabpot/goutte": "^3.2"
. Mi archivo de compositor tiene el siguiente aspecto:
{
"name": "ubuntu/workspace",
"require": {
"fabpot/goutte": "^3.2"
},
"authors": [
{
"name": "admin",
"email": "[email protected]"
}
]
}
Estoy tratando de obtener detalles por un intervalo de tiempo desde una página web, pero me cuesta cómo pasar los $crawler
valores a mi matriz de resultados finales $res1Array
.
Intenté lo siguiente:
<?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 puede ver, estoy tratando de crear $EVENT
y empujar todos los valores deseados como pares de valores clave dentro. Cuando termine, quiero llevarlo a la $resArray
siguiente estructura (los valores en este array()
son solo para fines estructurales):
[
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"
],
// ...
Actualmente no recibo nada en mi $res1Array
.
Agradezco mucho sus respuestas!
ACTUALIZAR
Ejecuté el script desde @tftd con el "fabpot/goutte": "^4.0"
que obtuve esto:
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
}
// ...
¿Alguna sugerencia de por qué obtengo todos estos valores nulos?
fuente
2020-01-02
en una matriz que contiene los datos de la fila. ¿Es eso correcto?now() - 2020/01-18
(que no es parte del ejemplo anterior, ya que comienza al principio y continúa hasta una fecha determinada, sin embargo, podría omitir filas no deseadas) . Mi gran problema es que recupero una matriz de vacío. Proporcione un ejemplo de trabajo completo.file_get_contents()
o$client->request()
. Por ejemplo, trate de encontrar la identificación del evento 113606Respuestas:
Me tomé la libertad de reescribir su código un poco usando OOP en lugar de dejarlo funcional porque es mucho más fácil enfocarse en bits más pequeños del código. Debería ser fácil convertirlo a codificación funcional, si lo necesita.
Esta clase toma una
date
que está formateadaJan2020
para poder obtener el calendario.Para obtener los eventos para un rango de fechas dentro de los registros del calendario, debe llamar
$parser->getEventsBetweenDates()
con unstartDate
y unendDate
. Las horas no se tienen en cuenta durante el análisis, pero puede agregarlo si lo necesita. Aquí hay un ejemplo:El resultado del código anterior es:
Aquí está el código completo:
fuente
Uncaught Error: Call to undefined method Symfony\Component\DomCrawler\Crawler::closest()
. ¿Qué versiones de las librerías está ejecutando? (Composer.json) ¡Agregue una solución y estoy dispuesto a aceptar su respuesta!php 7.1
php 7.3
pero eso no debería importar. Creo que podría tener una versión anterior defabpot/goutte
- la mía esv4.0.0
. EDITAR: Acabo de notar en su pregunta que ha señalado que está usando^3.2
. ¿Sería posible actualizar a4.0
?111392
, verá que todos los campos están llenos. Elnull
valor en otros registros es simplemente porque no hay una etiqueta de la que pueda obtener los datos.symfony/dom-crawler
(de dondeCrawler
proviene la clase) con versiones, ya sea^4.4
o^5.0
. Esta función existe en ambas versiones (verifique los enlaces). Sospecho que algo podría estar mal de tu parte: lo he intentado con ambas versiones y funciona. ¿Quizás verifique concomposer show -i
lo que está realmente instalado?Todavía estoy trabajando con el código que proporcionó, pero una de las primeras cosas que noto es justo antes de configurar
$API_RESPONSE
, tiene las siguientes líneas de código ...En ese punto de la función, aún no ha insertado ningún dato
$res1Array
, por lo que devolverá solo una matriz vacía. No es hasta el$subcrawler
(y el segundo intento de regresar$res1Array
) en el que realmente está insertando información en la matriz.Nota: Actualizaré mi respuesta una vez que trabaje con el resto del código, con la esperanza de brindarle una solución más completa a su problema.
fuente
break
elforeach
ciclo. Solo "saltará" la ejecución del resto del código de función.Te recomiendo que te quedes con tu código. Es más pequeño, más simple y más familiar para usted.
Hice una revisión de tu código. Puedes encontrar mis comentarios marcados con "***".
También puede guardar este código y compararlo con su versión original en alguna herramienta diff.
En realidad, solo tenías 4 errores pequeños.
fuente