PHP 从外部菜谱页面获取 application/ld+json 数据

Iwa*_*oss 1 php json metadata recipe

请问有人可以帮助我吗?我一直在到处搜索,但无法找到或产生正确的解决方案。我需要帮助从外部页面提取食谱数据。如果你看一下图像,你会注意到在同一页面上实现了一些 ld+json 标签,但我只需要提取配方数据并以 JSON 格式生成它,从那里,我知道如何将其加载到数据库中的表中。

在此输入图像描述

  1. 是页面的 URL。
  2. ld-json 标签的位置,尽管在其他页面上有所不同。
  3. 我需要提取并以 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);
Run Code Online (Sandbox Code Playgroud)

And*_*ato 5

您的代码似乎解析HTML页面的复杂性,而不是使用ld+json您指定的,这将以更简单、更易于访问的方式提供所有必要的数据。

因此,第一个建议是,不要使用DOMXPath,而是简单地循环页面中的所有脚本,如下所示:

foreach ($dom->getElementsByTagName('script') as $script) {
Run Code Online (Sandbox Code Playgroud)

然后,为了避免尝试解析真实的 javascript 代码并只考虑ld+json内容,请type像这样检查属性:

if ($script->getAttribute('type') == "application/ld+json") {
Run Code Online (Sandbox Code Playgroud)

您现在可以使用以下命令访问标签内的文本$script->textContent

通常,您可以直接将其解析json为对象,但返回的文本有两个问题会导致json_decode失败:

  1. 它在第一行包含注释,我们可以使用正则表达式将其删除
$json_txt = preg_replace('@/\*.*?\*/@', '', $script->textContent);
Run Code Online (Sandbox Code Playgroud)
  1. 它在段落中包含换行符,我们可以使用另一个正则表达式将其删除
$json_txt = preg_replace("/\r|\n/", " ", trim($json_txt));
Run Code Online (Sandbox Code Playgroud)

现在您已经有了正确格式化的json,您可以将其解码为对象。

$json = json_decode($json_txt);
Run Code Online (Sandbox Code Playgroud)

然后您可以轻松访问所有属性。例如,要获取您可以使用的食谱的名称

$json->name
Run Code Online (Sandbox Code Playgroud)

对于成分,你已经有一个数组,所以你甚至不需要循环。

$json->recipeIngredient;
Run Code Online (Sandbox Code Playgroud)

如果您愿意,当然可以将其分配给您自己的数组:

$recipe['title'] = $json->name;
$recipe['ingredients'] = $json->recipeIngredient;
Run Code Online (Sandbox Code Playgroud)

这是整体代码

$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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)