php正则获取网页中的json

php正则获取网页中的json

💡 原文中文,约2700字,阅读约需7分钟。
📝

内容提要

文章介绍如何用PHP正则从网页中提取JSON,适用于爬取JS变量中的JSON值。核心是递归正则:用命名分组(?<json>)声明,通过(?P>json)递归调用自身,配合非捕获分组(?:)和反向引用(?P=name),分别匹配对象{}与数组[],从而提取嵌套JSON。

🔎

延伸解读

递归正则如何匹配嵌套JSON

文章的核心是使用命名分组 (?<json>) 声明一个可递归调用的正则子表达式,并通过 (?P>json) 在内部调用自身。这样,当 value 部分遇到嵌套的对象或数组时,正则能继续深入匹配,而不是在第一个 } 或 ] 处停止。同时,非捕获分组 (?:) 用于避免产生多余的捕获项,反向引用 (?P=name) 则用于匹配与之前捕获内容相同的文本,例如 HTML 标签的闭合。

适用场景与提取方式

该正则主要针对网页中 JavaScript 变量赋值的 JSON 值,例如 var pureViewPageDataRR = {...};。通过 preg_match 直接对整段网页内容执行匹配,可以提取出变量后的 JSON 字符串。文章示例中,匹配结果同时包含完整 JSON 和内部嵌套的 value 捕获,方便后续解析。但需注意,正则本身不解析 JSON 语义,仅做文本提取。

使用时的局限与注意点

文章未讨论该正则对转义字符、Unicode、注释或非标准 JSON 的处理能力,也未说明性能表现。由于依赖递归和大量可选分组,面对超大或深层嵌套的 JSON 时可能效率下降或触发回溯限制。此外,正则只能提取符合其语法结构的文本,若网页中 JSON 格式不规范(如单引号、尾逗号),匹配可能失败。实际使用前建议先确认目标 JSON 的格式。

❓

Q&A

PHP正则如何提取网页中JS变量里的JSON数据?

使用递归正则表达式,核心是命名分组(?<json>)和递归调用(?P>json)。正则模式为:/(?<json>\s*(?:\{\s*(?:\s*"[^"]+"\s*:\s*(?<value>(?:(?P>json)|true|false|null|-?\d+(?:\.\d+)?|"[^"]*")\s*,?)\s*)*\s*\}|\[\s*(?P>value)*\s*\])\s*)/。该正则能匹配嵌套的JSON对象和数组,通过preg_match提取。

正则表达式中(?<json>)和(?P>json)有什么区别?

(?<json>)用于声明一个命名分组,相当于定义变量;(?P>json)用于递归调用该命名分组的正则表达式,即复用其模式。而(?P=json)是匹配该分组已捕获的内容,不是复用模式。

在PHP正则中,非捕获分组(?:)有什么作用?

非捕获分组(?:)用于分组但不捕获匹配内容,避免在preg_match结果中出现无用的分组数据。例如,使用(?:a|b)代替(a|b)可以防止a或b被单独捕获。

如何用正则匹配嵌套的JSON对象和数组?

通过递归正则实现:用(?<json>)定义整体JSON模式,内部用(?P>json)递归调用自身以匹配嵌套结构。对象部分匹配键值对,值可以是递归JSON、布尔、null、数字或字符串;数组部分直接调用value分组匹配元素。

正则中(?P=name)和(?P>name)分别用在什么场景?

(?P=name)用于匹配与命名分组name已捕获内容相同的文本,常用于匹配成对的HTML标签,如<(?<group>[^>]+)>(.+?)<\/(?P=group)>。(?P>name)用于递归调用命名分组name的正则模式,适用于嵌套结构如JSON。

能否给出一个PHP正则提取网页JSON的完整示例?

假设网页内容包含:var pureViewPageDataRR = {"docInfoFromApi":{"doc_id":"dd6213a9e63a580216fc700abb68a98271feacf9"}}; 使用preg_match('/(?<json>\s*(?:\{\s*(?:\s*"[^"]+"\s*:\s*(?<value>(?:(?P>json)|true|false|null|-?\d+(?:\.\d+)?|"[^"]*")\s*,?)\s*)*\s*\}|\[\s*(?P>value)*\s*\])\s*)/', $content, $match); 即可提取JSON字符串,结果在$match['json']中。

🏷️

标签

➡️

继续阅读