PHP 从外部配方页面获取 application/ld+json 数据
PHP Get application/ld+json data from external recipe page
有人可以帮助我吗?我一直在到处搜索,但无法找到或生成正确的解决方案。我需要帮助从外部页面提取食谱数据。如果你看一下图像,你会注意到在同一页面上实现了几个 ld+json 标签,但我只需要提取配方数据并以 JSON 格式生成它,并且从那里,我知道如何将它加载到数据库中的 table。
- 是页面的URL。
- 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;
}
}
}
有人可以帮助我吗?我一直在到处搜索,但无法找到或生成正确的解决方案。我需要帮助从外部页面提取食谱数据。如果你看一下图像,你会注意到在同一页面上实现了几个 ld+json 标签,但我只需要提取配方数据并以 JSON 格式生成它,并且从那里,我知道如何将它加载到数据库中的 table。
- 是页面的URL。
- 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;
}
}
}