Пожалуйста, кто-нибудь может мне помочь? Я искал везде и не могу найти или предоставить правильное решение. Мне нужна помощь в извлечении данных рецепта с внешней страницы. Если вы посмотрите на изображение, вы заметите, что на одной странице реализовано несколько тегов ld+json, но мне нужно извлечь только данные рецепта и создать их в формате JSON, и оттуда я знаю, как загрузить его в таблицу в базе данных.
Я пробовал этот скрипт, но не знаю, как получить со страницы только данные рецепта.
$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTMLFile('https://www.thecookingcat.com/recipes/fluffy-pancake.php');
libxml_clear_errors();
$recipe = array();
$xpath = new DOMXPath($dom);
$contentDiv = $dom->getElementById('content');
$recipe['title'] = $xpath->evaluate('string(div/h2/a)', $contentDiv);
foreach ($xpath->query('div/div/ul/li', $contentDiv) as $listNode) {
$recipe['ingredients'][] = $listNode->nodeValue;
}
print_r($recipe);
Ваш код, кажется, анализирует сложный HTML
страницы вместо использования указанного вами ld+json
, который предоставил бы все необходимые данные более простым и доступным способом.
Итак, первое предложение, вместо использования DOMXPath
, просто зациклите все скрипты со страницы следующим образом:
foreach ($dom->getElementsByTagName('script') as $script) {
Затем, чтобы не пытаться анализировать настоящий код javascript и рассматривать только содержимое ld+json
, проверьте атрибут type
следующим образом:
if ($script->getAttribute('type') == "application/ld+json") {
Теперь вы можете получить доступ к тексту внутри тега с помощью $script->textContent
Обычно вы можете напрямую разобрать json
в объект, но возвращаемый текст имеет 2 проблемы, которые могут привести к сбою json_decode
:
$json_txt = preg_replace('@/\*.*?\*/@', '', $script->textContent);
$json_txt = preg_replace("/\r|\n/", " ", trim($json_txt));
Теперь, когда у вас есть правильно отформатированный json
, вы можете декодировать его в объект.
$json = json_decode($json_txt);
Затем вы можете легко получить доступ ко всем свойствам. Например, чтобы получить название рецепта, вы можете использовать
$json->name
а для ингредиентов у вас уже есть массив, поэтому вам даже не нужно зацикливаться.
$json->recipeIngredient;
Вы, конечно, можете назначить это своему собственному массиву, если хотите:
$recipe['title'] = $json->name;
$recipe['ingredients'] = $json->recipeIngredient;
Вот общий код
$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTMLFile('https://www.thecookingcat.com/recipes/fluffy-pancake.php');
$recipe = array();
foreach ($dom->getElementsByTagName('script') as $script) {
if ($script->getAttribute('type') == "application/ld+json") {
$json_txt = preg_replace('@/\*.*?\*/@', '', $script->textContent);
$json_txt = preg_replace("/\r|\n/", " ", trim($json_txt));
$json = json_decode($json_txt);
if ($json->{'@type'} == "Recipe") {
$recipe['title'] = $json->name;
$recipe['ingredients'] = $json->recipeIngredient;
}
}
}