Как читать JSON с URL сайта, используя DOMDocument - PullRequest
0 голосов
/ 13 октября 2018

В приведенном ниже коде я пытаюсь прочитать application/ld+json JSON и получить ratingValue.

Используя текущий URL (https://www.facebook.com/Dermaks), результат $rate должен быть: 5.

Если вы посетите этот URL (выше 4 строк в режиме просмотра исходного кода), вы сможете выбрать JSON, который я хочу прочитать:

<script type="application/ld+json"> {
    "\u0040context":"http:\/\/schema.org",
    "\u0040type":"LocalBusiness",
    "name":"Kosmetyka Profesjonalna Dermaks",
    "address": {
        "\u0040type": "PostalAddress", "streetAddress": "DERMAKS, ul. Hempla 4\/34a", "addressLocality": "Lublin, Poland", "addressRegion": "Lublin Voivodeship", "postalCode": "20-008"
    }
    ,
    "aggregateRating": {
        "\u0040type": "AggregateRating", "ratingValue": 5, "ratingCount": 2
    }
}

</script>

<script type="application/ld+json"> {
    "\u0040context":"http:\/\/schema.org",
    "\u0040type":"Review",
    "name":"",
    "reviewBody":"Profesjonalna  i przy tym bardzo,bardzo mi\u0142a obs\u0142uga. Zabiegi na bardzo wysokim poziomie. POLECAM next dw\u00f3ch zda\u0144!!!!!!!",
    "itemReviewed": {
        "\u0040type": "LocalBusiness", "name": "Kosmetyka Profesjonalna Dermaks", "sameAs": "https:\/\/www.facebook.com\/Dermaks\/"
    }
    ,
    "reviewRating": {
        "\u0040type": "Rating", "ratingValue": 5
    }
    ,
    "author": {
        "\u0040type": "Person", "name": "Malgorzata Mordo\u0144"
    }
}

</script>

Как я могу исправить код ниже?

$url = 'https://www.facebook.com/Dermaks';

function get_data($url, $timeout = 15, $header = array(), $options = array()) {
    if (!function_exists('curl_init')) {
    return file_get_contents($url);
  } elseif (!function_exists('file_get_contents')) {
    return '';
  }
    if (empty($options)) {
        $options = array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
            CURLOPT_TIMEOUT => $timeout
        );
    }
    if (empty($header)) {
        $header = array(
            "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*\/*;q=0.5",
            "Accept-Language: en-us,en;q=0.5",
            "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7",
            "Cache-Control: must-revalidate, max-age=0",
            "Connection: keep-alive",
            "Keep-Alive: 300",
            "Pragma: public"
        );
    }
    if ($header != 'NO_HEADER') {
        $options[CURLOPT_HTTPHEADER] = $header;
    }
    $ch = curl_init();
    curl_setopt_array($ch, $options);
    $data = curl_exec($ch);
    curl_close($ch);
    return $data;
}

$html = get_data($url);
$doc = new DOMDocument();
@$doc->loadHTML($html);
$scripts = $doc->getElementsByTagName('script');
for ($i = 0; $i < $scripts->length; ++$i) {
  $script = $scripts->item($i);
  if ($script->getAttribute('type') == 'application/ld+json') {
    $rate = $script->getAttribute('ratingValue');
  }
}

echo $rate;
// result should be: 5

1 Ответ

0 голосов
/ 13 октября 2018

Вам придется запускать каждую $script через json_decode.

Я предполагаю, что вы просто хотите значение aggregateRating, поскольку есть несколько элементов с ratingValue.

if ($script->getAttribute('type') == 'application/ld+json') {
  // Load as an array
  $entity = json_decode($script->nodeValue, true);
  if (($entity['type'] == '@LocalBusiness') && isset($entity['aggregateRating'])) {
    $rate = $entity['aggregateRating']['ratingValue'];
    break;
  }
}

Кстати, DOMDocument loadHTMLFile метод должен иметь возможность извлекать URL-адрес сам по себе при правильной конфигурации php.ini:

$doc->loadHTMLFile($url);
...