如何用RegEx抓取带/不带引号的Facebook Meta属性与内容值
优化OG Meta标签正则匹配方案
问题背景
抓取不同站点的Facebook OG Meta值时,部分站点(如usatoday.com)HTML代码不规范,属性存在带/不带转义引号(")或普通引号的情况。现有多分支preg_match写法灵活性差,还无法捕获无引号的URL类content值。
优化后的正则表达式
用单条正则即可兼容所有不规范场景:
preg_match('/<meta\s+(?:[^>]*?\s+)?property=(?:"|")?(og:[a-z:]+)(?:"|")?\s+(?:[^>]*?\s+)?content=(?:"|")?(?(?="|")(.+?)(?:"|")|([^\s>]+))\s*\/?>/i', $raw_html, $matches);
正则逻辑说明
<meta\s+:匹配<meta标签开头及后续空格(?:[^>]*?\s+)?:非贪婪匹配标签内的其他属性(不捕获),兼容属性顺序不固定的情况property=(?:"|")?(og:[a-z:]+)(?:"|")?:匹配property属性,支持带普通引号、转义引号或无引号的情况,捕获og:开头的属性名content=(?:"|")?:匹配content属性开头,兼容带/不带引号的场景(?(?="|")(.+?)(?:"|")|([^\s>]+)):条件匹配逻辑- 如果遇到引号/转义引号,就捕获引号内的完整内容(支持含空格的文本)
- 无引号时,捕获到空格或标签结束前的内容(适配URL类无空格值)
\s*\/?>:匹配标签闭合,允许末尾空格及/>或>两种闭合方式
使用示例
// 测试带转义引号的文本内容(usatoday的og:title) $raw_html1 = '<meta property=og:title content="Lakers trading Russell Westbrook in massive three-team deal with Jazz and Timberwolves"/>'; if (preg_match('/<meta\s+(?:[^>]*?\s+)?property=(?:"|")?(og:[a-z:]+)(?:"|")?\s+(?:[^>]*?\s+)?content=(?:"|")?(?(?="|")(.+?)(?:"|")|([^\s>]+))\s*\/?>/i', $raw_html1, $matches)) { $property = $matches[1]; $content = $matches[2] ?: $matches[3]; echo "Property: {$property}\nContent: {$content}\n"; } // 测试无引号的URL内容(usatoday的og:url) $raw_html2 = '<meta property=og:url content=https://www.usatoday.com/story/sports/nba/2023/02/08/lakers-jazz-timberwolves-trade-russell-westbrook-mike-conley-dangelo-russell/11214855002/ />'; if (preg_match('/<meta\s+(?:[^>]*?\s+)?property=(?:"|")?(og:[a-z:]+)(?:"|")?\s+(?:[^>]*?\s+)?content=(?:"|")?(?(?="|")(.+?)(?:"|")|([^\s>]+))\s*\/?>/i', $raw_html2, $matches)) { $property = $matches[1]; $content = $matches[2] ?: $matches[3]; echo "Property: {$property}\nContent: {$content}\n"; }
优势
- 替代多分支判断,用单条正则覆盖所有属性引号场景
- 同时支持带空格的文本内容和无空格的URL内容捕获
- 兼容标签内属性顺序调换、多余空格等不规范HTML写法
内容的提问来源于stack exchange,提问作者what
相关产品推荐
相关产品推荐

