PHP中strtotime()解析网页时间戳易失败,因它仅支持标准英文格式(如"2024-03-15 14:23:00"),而网页常含中文、符号、相对表述或乱码;须先正则清洗、替换中文为标准分隔符,并显式设置时区。

PHP中用strtotime()解析网页时间戳容易失败的原因
直接对爬取的网页文本调用strtotime()往往返回false,不是函数坏了,而是它只接受标准格式(如"2024-03-15 14:23:00"或"1710512580"),而网页里的时间混着中文、空格、符号、相对表述(“3小时前”“昨天”)甚至乱码。
常见错误现象:strtotime("发布时间:2024年03月15日 14:23") 返回 false;strtotime("2024/03/15 14:23") 在某些 PHP 版本下也失败(尤其 Windows + 旧版 ICU)。
- 先用正则提取干净的时间字符串,再喂给
strtotime(),别跳步 - 中文年月日必须替换为英文符号或数字分隔符,例如把
"2024年03月15日"转成"2024-03-15" - 遇到“刚刚”“半小时前”这类相对时间,需结合当前服务器时间推算,不能只靠
strtotime() - 注意时区:网页时间可能是 UTC 或东八区,但
strtotime()默认按date_default_timezone_get()解析,建议显式设为"Asia/Shanghai"
匹配网页发布时间的正则表达式怎么写才不漏不滥
没有万能正则,得按目标站点结构定制。核心原则是:先宽后窄,用preg_match()捕获组精准定位,避免.*跨行贪婪匹配导致错位。
典型场景与推荐写法:
立即学习“PHP免费学习笔记(深入)”;
- 含中文格式:
/发布时间[::\s]*?(\d{4})[年\s](\d{1,2})[月\s](\d{1,2})[日\s]*(\d{1,2})[:点时\s]*(\d{1,2})[:分\s]*(\d{1,2})秒?/u→ 捕获6个组,拼成"$1-$2-$3 $4:$5:$6" - ISO 类格式:
/[^\d](\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})[^\d]/→ 加前后非数字边界,防匹配到 ID 或 URL 中的数字串 - Unix 时间戳(10位纯数字):
/[^0-9](\d{10})[^0-9]/→ 避免误抓 13 位毫秒级时间戳或手机号 - 带“ago”的英文相对时间:
→ 配合<code>time() - $n * $unit_sec换算
调试技巧:用preg_match_all()先把所有疑似时间都捞出来,人工看一遍再收紧规则,比闭眼写正则靠谱得多。
DateTime类比strtotime()更适合清洗后的日期吗
是的,尤其当清洗后的时间字符串仍有格式波动(比如有时有秒有时没有、有时用.分隔毫秒)时,DateTime::createFromFormat()比strtotime()更可控、报错更明确。
示例对比:
/* 安全解析 "2024-03-15 14:23" 或 "2024-03-15 14:23:05" */
$date = DateTime::createFromFormat('Y-m-d H:i:s', $cleaned);
if (!$date || $date->format('Y-m-d H:i:s') === '1970-01-01 00:00:00') {
// 解析失败,尝试去掉秒再试
$date = DateTime::createFromFormat('Y-m-d H:i', $cleaned);
}-
createFromFormat()允许指定精确模板,不匹配就返回false,不会静默容错 - 支持
!重置时间为 00:00:00(如'!Y-m-d'),避免残留时间干扰 - 解析失败时,
DateTime::getLastErrors()能拿到具体哪部分不匹配,比strtotime()的false有用得多 - 注意:模板中
H是24小时制,h是12小时制,混淆会导致下午时间变凌晨
爬虫时间提取中最容易被忽略的三个细节
多数人卡在正则和转换上,但真正上线后出问题的,常是这些隐性环节:
- 网页 HTML 编码不一致:
mb_convert_encoding($html, 'UTF-8', 'GBK')没做,导致中文“年月日”变成乱码,正则完全失效 - JavaScript 渲染时间:有些站点发布时间由 JS 动态插入(如
document.write(new Date().toLocaleString())),curl 抓到的是占位符或空节点,得换 Puppeteer 或分析 AJAX 接口 - 多个时间字段并存:网页可能同时存在“发布时间”“更新时间”“爬取时间”,仅靠关键词匹配会取错,需结合 DOM 路径(如
//div[@class="post-meta"]/span[1])或上下文位置锚定
清洗不是一次性动作,每次新增目标站点,都要重新检查原始 HTML 片段、编码、JS 行为和 DOM 结构——时间字段永远是最爱伪装的那一个。



















