get_meta_tags

(PHP 4, PHP 5, PHP 7, PHP 8)

get_meta_tags从文件提取所有元标记内容属性并返回数组

说明

get_meta_tags(string $filename, bool $use_include_path = false): array|false

打开 filename 并逐行解析,查找文件中的 <meta> 标记。解析在 </head> 处停止。

参数

filename

HTML 文件的路径,作为字符串。这可以是本地文件或 URL

示例 #1 get_meta_tags() 解析的内容

<meta name="author" content="name">
<meta name="keywords" content="php documentation">
<meta name="DESCRIPTION" content="a php manual">
<meta name="geo.position" content="49.33;-86.59">
</head> <!-- parsing stops here -->

use_include_path

use_include_path 设置为 true 将导致 PHP 尝试沿标准包含路径打开文件,如 include_path 指令所述。这用于本地文件,而不是 URL。

返回值

返回包含所有解析的元标记的数组。

name 属性的值成为键,content 属性的值成为返回数组的值,因此可以轻松使用标准数组函数来遍历它或访问单个值。name 属性值的特殊字符被替换为 '_’,其余部分转换为小写。如果两个元标记具有相同的名称,则只返回最后一个。

如果失败,则返回 false

示例

示例 #2 get_meta_tags() 返回的内容

<?php
// 假设上面的标签在 www.example.com
$tags = get_meta_tags('http://www.example.com/');

// 注意键现在都是小写了,
// 并且 . 在键中被替换为 _。
echo $tags['author']; // name
echo $tags['keywords']; // php documentation
echo $tags['description']; // a php manual
echo $tags['geo_position']; // 49.33;-86.59
?>

注释

注意:

只解析具有 name 属性的元标记。不需要引号。

参见

添加注释

用户贡献的注释 19 个注释

53
bobble bubble
9 年前
此正则表达式通过在先行断言中捕获来获取独立于顺序的元标记。
此外,它使用分支重置功能来处理不同引号样式的值。
可以在此处测试该模式:https://regex101.com/r/oE4oU9/1

<?PHP

function getMetaTags($str)
{
$pattern = '
~<\s*meta\s

# 使用先行断言将类型捕获到 $1
(?=[^>]*?
\b(?:name|property|http-equiv)\s*=\s*
(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|
([^"\'>]*?)(?=\s*/?\s*>|\s\w+\s*=))
)

# 将内容捕获到 $2
[^>]*?\bcontent\s*=\s*
(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|
([^"\'>]*?)(?=\s*/?\s*>|\s\w+\s*=))
[^>]*>

~ix'
;

if(
preg_match_all($pattern, $str, $out))
return
array_combine($out[1], $out[2]);
return array();
}

// 用法
$meta_tags = getMetaTags($str);

?>
3
jp at webgraphe dot com
20 年前
如果 URL 使用标头进行重定向(就像使用 PHP 函数 header("Location: URL"); 所做的那样),则页面通常没有内容。get_meta_tags() 似乎没有捕获这种重定向(就像 cURL 所做的那样),这导致我的脚本超时。

我在一个我编写的蜘蛛中遇到了这个问题,为了填充我网站上所有可用页面的数据库,一个链接链接到一个页面,该页面只有以下代码

<?php
header
("Location: sections.php?section=home");
exit();
?>

这使我的脚本挂起了一段时间,而且 get_meta_tags() 甚至无法返回错误。

JP。
2
Ebpo
11 年前
请注意,该函数在整个页面中查找元标记。如果由于某种原因您的代码中的一条元标记被注释掉了,它仍然会被抓取。
6
richard dot dern at athaliasoft dot fr
10 年前
我个人在尝试获取元标记并未使用 get_meta_tags 函数(为了也获取 http-equiv 元标记)时,使用 DOM 函数比使用正则表达式遇到的问题更少。

<?php

$doc
= new DOMDocument();
$doc->loadHTML($html);

$xpath = new DOMXPath($doc);

$nodes = $xpath->query('//head/meta');

foreach(
$nodes as $node) {
[...]
}

?>
2
匿名
22 年前
已测试 PHP 4.0.6

get_meta_tags() 似乎只查找文件的开头,这意味着例如如果在 HTML 标头之前有大量 PHP 代码,它将不返回任何内容...
已测试在 HTML 标头之前约 9000 个字符的 PHP 代码的本地文件上使用 get_meta_tags()。

解决方法:如果可能,将代码移到标头之后,否则:包含一个文件。
2
richard at pifmagazine dot com
24 年前
关于 META 标记和此函数的一个重要说明:如果您的 META 标记包含换行符 "\n" 字符,get_meta_tags() 将为该 name 属性返回 NULL 值。从源 META 标记中删除换行符可以解决此问题。
1
rehfeld
19 年前
回复
jp at webgraphe dot com

此函数获取元标记,而不是 http 标头

如果您需要标头

<?php

$fp
= fopen('http://example.org/somepage.html', 'r');

// 变量 $http_response_header 会神奇地出现
print_r($http_response_header);

// 或者
$meta_data = stream_get_meta_data($fp);
print_r($meta_data);

?>
5
mariano at cricava dot com
18 年前
基于 Michael Knapp 的代码,并添加了一些正则表达式,这是一个可以获取所有元标签和标题的函数,该函数基于 URL。如果出现错误,它将返回 false。使用 getUrlContents() 函数,该函数也包含在内,它负责处理 META REFRESH 重定向,最多跟踪指定的重定向次数。请注意,包含的正则表达式被拆分为字符串,因为 php.net 对行过长进行了抱怨;)

<?php
function getUrlData($url)
{
$result = false;

$contents = getUrlContents($url);

if (isset(
$contents) && is_string($contents))
{
$title = null;
$metaTags = null;

preg_match('/<title>([^>]*)<\/title>/si', $contents, $match );

if (isset(
$match) && is_array($match) && count($match) > 0)
{
$title = strip_tags($match[1]);
}

preg_match_all('/<[\s]*meta[\s]*name="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si', $contents, $match);

if (isset(
$match) && is_array($match) && count($match) == 3)
{
$originals = $match[0];
$names = $match[1];
$values = $match[2];

if (
count($originals) == count($names) && count($names) == count($values))
{
$metaTags = array();

for (
$i=0, $limiti=count($names); $i < $limiti; $i++)
{
$metaTags[$names[$i]] = array (
'html' => htmlentities($originals[$i]),
'value' => $values[$i]
);
}
}
}

$result = array (
'title' => $title,
'metaTags' => $metaTags
);
}

return
$result;
}

function
getUrlContents($url, $maximumRedirections = null, $currentRedirection = 0)
{
$result = false;

$contents = @file_get_contents($url);

// 检查是否需要跳转到其他地方

if (isset($contents) && is_string($contents))
{
preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $contents, $match);

if (isset(
$match) && is_array($match) && count($match) == 2 && count($match[1]) == 1)
{
if (!isset(
$maximumRedirections) || $currentRedirection < $maximumRedirections)
{
return
getUrlContents($match[1][0], $maximumRedirections, ++$currentRedirection);
}

$result = false;
}
else
{
$result = $contents;
}
}

return
$contents;
}
?>

这是一个使用示例。检查包含的 URL 是否有 META REFRESH 重定向

<?php
$result
= getUrlData('http://www.marianoiglesias.com.ar/');

echo
'<pre>'; print_r($result); echo '</pre>';

?>

对于上面的代码,输出将是

<?php
Array
(
[
title] => Mariano Iglesias: El Eternauta
[metaTags] => Array
(
[
description] => Array
(
[
html] => <meta name="description" content="Java, PHP, and some other technological mumble jumble. Also, some real-life stuff as well." />
[
value] => Java, PHP, and some other technological mumble jumble. Also, some real-life stuff as well.
)

[
DC.title] => Array
(
[
html] => <meta name="DC.title" content="Mariano Iglesias - Weblog" />
[
value] => Mariano Iglesias - Weblog
)

[
ICBM] => Array
(
[
html] => <meta name="ICBM" content="-34.6017, -58.3956" />
[
value] => -34.6017, -58.3956
)

[
geo.position] => Array
(
[
html] => <meta name="geo.position" content="-34.6017;-58.3956" />
[
value] => -34.6017;-58.3956
)

[
geo.region] => Array
(
[
html] => <meta name="geo.region" content="AR-BA">
[
value] => AR-BA
)

[
geo.placename] => Array
(
[
html] => <meta name="geo.placename" content="Buenos Aires">
[
value] => Buenos Aires
)

)

)
?>
7
LWC
9 年前
基于 mariano at cricava dot com 的工作,新版本支持:
1) 支持元属性(如 Facebook 的 og 标签)。
2) 支持 Unicode(UTF-8)编码的元行。
3) 可以选择不转换 htmlentities - 如果您计划实际使用结果,而不仅仅是显示它们。

function getUrlData($url, $raw=false) // $raw - 启用以显示原始结果
{
$result = false;

$contents = getUrlContents($url);

if (isset($contents) && is_string($contents))
{
$title = null;
$metaTags = null;
$metaProperties = null;

preg_match('/<title>([^>]*)<\/title>/si', $contents, $match );

if (isset($match) && is_array($match) && count($match) > 0)
{
$title = strip_tags($match[1]);
}

preg_match_all('/<[\s]*meta[\s]*(name|property)="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si', $contents, $match);

if (isset($match) && is_array($match) && count($match) == 4)
{
$originals = $match[0];
$names = $match[2];
$values = $match[3];

if (count($originals) == count($names) && count($names) == count($values))
{
$metaTags = array();
$metaProperties = $metaTags;
如果 ($raw) {
如果 (version_compare(PHP_VERSION, '5.4.0') == -1)
$flags = ENT_COMPAT;
否则
$flags = ENT_COMPAT | ENT_HTML401;
}

对于 ($i=0, $limiti=count($names); $i < $limiti; $i++)
{
如果 ($match[1][$i] == 'name')
$meta_type = 'metaTags';
否则
$meta_type = 'metaProperties';
如果 ($raw)
${$meta_type}[$names[$i]] = array (
'html' => htmlentities($originals[$i], $flags, 'UTF-8'),
'value' => $values[$i]
);
否则
${$meta_type}[$names[$i]] = array (
'html' => $originals[$i],
'value' => $values[$i]
);
}
}
}

$result = array (
'title' => $title,
'metaTags' => $metaTags,
'metaProperties' => $metaProperties,
);
}

返回 $result;
}

函数 getUrlContents($url, $maximumRedirections = null, $currentRedirection = 0)
{
$result = false;

$contents = @file_get_contents($url);

// 检查是否需要重定向到其他地方

if (isset($contents) && is_string($contents))
{
preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $contents, $match);

如果 (isset($match) && is_array($match) && count($match) == 2 && count($match[1]) == 1)
{
如果 (!isset($maximumRedirections) || $currentRedirection < $maximumRedirections)
{
返回 getUrlContents($match[1][0], $maximumRedirections, ++$currentRedirection);
}

$result = false;
}
否则
{
$result = $contents;
}
}

返回 $contents;
}
?>

<?php
$result
= getUrlData('http://whatever...', true);

echo
'<pre>'; print_r($result, true); echo '</pre>';

?>

输出示例

<?php
数组
(
[
title] => The requested page's title
[metaTags] => 数组
(
[description] => 数组
(
[html] => <meta name="description" content="Something..." />
[value] => Something...
)
)
[metaProperties] => 数组
(
[og:type] => 数组
(
[html] => <meta property="og:type" content="article"/>/>
[value] => article
)
)
)
?>
4
roganty at gmail dot com
17 年前
这是对 jimmyxx at gmail dot com 函数的轻微修改

我尝试使用他代码中显示的正则表达式,PHP 抛出了一些错误

以下是有效的正确正则表达式
(请注意,我不得不将正则表达式拆分为字符串,因为 php.net 对行过长有抱怨)
<?php
preg_match_all
(
"|<meta[^>]+name=\"([^\"]*)\"[^>]" . "+content=\"([^\"]*)\"[^>]+>|i",
$html, $out,PREG_PATTERN_ORDER);
?>

问题出在引号的转义不正确。
我希望这能帮助任何在使用他的代码时遇到问题的人
1
tim dot bennett at haveaniceplay dot com
19 年前
如果你想获取除 meta 之外的标签内容,可以使用

<?php

$page
= "http://www.mysite.com/apage.php";

// 标签
$start = '<atag>';
$end = '<\/atag>';

// 打开文件
$fp = fopen( $page, 'r' );

$cont = "";

// 读取内容
while( !feof( $fp ) ) {
$buf = trim( fgets( $fp, 4096 ) );
$cont .= $buf;
}

// 获取标签内容
preg_match( "/$start(.*)$end/s", $cont, $match );

// 标签内容
$contents = $match[ 1 ];

?>
0
Michael Knapp
19 年前
Tim 的代码很好(感谢 Tim),但如果标签是长字符串的一部分,它不会很好地工作。

例如,尝试从 Google 地图 (http://www.google.com/maps) 获取标题。

更好的解决方案是

<?php
$title
= "";

如果 (
$fp = @fopen( $_POST['url'], 'r' )) {

$cont = "";

// 读取内容
while( !feof( $fp ) ) {
$buf = trim(fgets( $fp, 4096 )) ;
$cont .= $buf;
}

// 获取标签内容
@preg_match( "/<title>([a-z 0-9]*)<\/title>/si", $cont, $match );

// 标签内容
$title = strip_tags(@$match[ 1 ]);
}

?>

注意 strip_tags。另一件要注意的事情是检查 ", < 和 >。如果要将输出发布到表单,则需要将它们删除。

此外,最好使用 /i 修饰符,因为有些人可能会编写 <TITLE> 等...
0
richard at pifmagazine dot com
24 年前
上面没有提到的一点应该是:在远程 PHP 页面上使用 get_meta_tags 时,页面会在返回元标签之前解析 - 因此您可以捕获远程生成的元标签(通过 PHP??)。

在本地文件系统上获取元标签时,这不起作用。本地文件在返回 get_meta_tags() 之前不会通过 Web 服务器解析。如果元标签是硬编码到页面中的,那么你会没事 - 但如果它是动态生成的,你将无法捕获它,除非你在调用你的本地文件时使用完整的 URL。
-2
doob_ at gmx dot de
15 年前
<?php

/*
** 提取并格式化元标签内容
*/

函数 get_meta_data($url, $searchkey='') {
$data = get_meta_tags($url); // 将元数据获取到数组中
foreach($data as $key => $value) {
if(
mb_detect_encoding($value, 'UTF-8, ISO-8859-1', true) != 'ISO-8859-1') { // 检查内容是 UTF-8 还是 ISO-8859-1
$value = utf8_decode($value); // 如果是 UTF-8,则对其进行解码
}
$value = strtr($value, get_html_translation_table(HTML_ENTITIES)); // 掩盖内容
if($searchkey != '') { // 如果只需求一个元标签,例如 'description'
if($key == $searchkey) {
$str = $value; // 只返回 value
}
} 否则 {
// 所有元标签
$pattern = '/ |,/i'; // ' ' 或 ','
$array = preg_split($pattern, $value, -1, PREG_SPLIT_NO_EMPTY); // 将其拆分为数组,这样我们就可以得到单词数量
$str .= '<p><span style="display:block;color:#000000;font-weight:bold;">' . $key . ' <span style="font-weight:normal;">(' . count($array) . ' 个词 | ' . strlen($value) . ' 个字符)</span></span>' . $value . '</p>'; // 使用单词和字符数量格式化数据
}
}
返回
$str;
}

$content .= get_meta_data("http://www.example.com/");
/*
输出看起来像这样:

description (23 个词 | 167 个字符)
SELFHTML 8.1.2 - Die bekannte Dokumentation zu HTML, JavaScript und CGI/Perl - Tutorial und Referenz, mit etlichen Zusatztips zu Design, Grafik, Projektverwaltung usw.

keywords (13 个词 | 119 个字符)
SELFHTML, HTML, Dynamic HTML, JavaScript, CGI, Perl, Grafik, WWW-Seiten, Web-Seiten, Hilfe, Dokumentation, Beschreibung

等等。

*/

$content .= get_meta_data("http://www.example.com/", "description");
/*
输出看起来像这样:

SELFHTML 8.1.2 - Die bekannte Dokumentation zu HTML, JavaScript und CGI/Perl - Tutorial und Referenz, mit etlichen Zusatztips zu Design, Grafik, Projektverwaltung usw.
*/

?>
-1
jstel at 126 dot com
15 年前
此函数可以获取 HTML 内容的每个元数据,并去除所有 js 和 css。

<?php
function get_meta_data($content)
{
$content = strtolower($content);
$content = preg_replace("'<style[^>]*>.*</style>'siU",'',$content); // 去除 js
$content = preg_replace("'<script[^>]*>.*</script>'siU",'',$content); // 去除 css
$split = explode("\n",$content);
foreach (
$split as $k => $v)
{
if (
strpos(' '.$v,'<meta')) {
preg_match_all(
"/<meta[^>]+(http\-equiv|name)=\"([^\"]*)\"[^>]" . "+content=\"([^\"]*)\"[^>]*>/i",
$v, $split_content[],PREG_PATTERN_ORDER);;
}
}
return
$split_content;
}
?>
-1
Ben dot Davis at furman dot edu
23 年前
我发现对于大型搜索,get_meta_tags 非常慢。我为一个无法使用数据库的网站创建了一个大型搜索引擎,我首先尝试提取元标签。
我发现使用 eregi 提取元标签实际上快得多。以下代码提取描述

if (eregi ("<meta name=\"description\" content=[^>]*", $contents, $descresult))
{
$description = explode("<meta name=\"description\" content=", $descresult[0]);
echo "<font face=\"Arial\" size=2>$description[1]</font>";

}
-2
Antonio - Malaga
15 年前
如果元语法没有尾部斜杠,则不起作用。
-3
diel at caroes dot be
16 年前
快速元数据抓取器
[代码]
if(get_meta_tags('http://'.$_POST['pagina'])){
print '<font class="midden">Meta data from http://'.$_POST['pagina'].'</font>';
$metadata = get_meta_tags('http://'.$_POST['pagina']);
echo '<table width="100%">';
print '<tr><td>Meta</td><td>Waarde</td></tr>';
foreach($metadata as $naam => $waarde){
echo '<tr><td valign="top">'.$naam.'</td><td>'.$waarde.'</td></tr>';
}
print '</table>';
}else{
print '
<div class="red_h">Incorrect</div>
';
}
[/代码]
-3
jimmyxx at gmail dot com
18 年前
我将它用在我的小型基于 PHP 搜索的搜索引擎中 - 它确实减慢了整个过程。我编写了这个函数来读取 HTML(只需获取文件或使用类似 snoopy 的东西)并通过简单的正则表达式提取元数据,效果很好,使我的爬虫速度更快

<?php

function get_meta_data($html) {

preg_match_all(
"|<meta[^>]+name=\\"([^\\"]*)\\"[^>]+content=\\"([^\\"]*)\\""[^>]+>|i", $html, $out,PREG_PATTERN_ORDER);

for (
$i=0;$i < count($out[1]);$i++) {
// 循环元数据 - 如果需要,在这里添加您自己的标签
if (strtolower($out[1][$i]) == "keywords") $meta['keywords'] = $out[2][$i];
if (
strtolower($out[1][$i]) == "description") $meta['description'] = $out[2][$i];
}

return
$meta;
}

?>
To Top