
本文介绍在解析电商比价页面时,如何通过字符串预处理结合正则匹配,跳过顶部广告区块、准确提取所有真实商家信息(每个以 `
` 开始、以 `
` 或 `
` 结束的区块)。
在实际网页抓取(如解析 ZAP.co.il 商品比价页)过程中,常遇到结构相似但语义不同的 HTML 区块:顶部是推广广告商家(同样使用 zuojiankuohaophpcndiv class="StoreLine">),而下方才是真实比价结果。若直接对全文用 preg_match_all() 匹配 StoreLine 到 BuyButtons 的闭合区块,会错误包含广告内容。
核心思路不是“在正则中跳过前 N 个”——而是先定位语义分界点,截断无关前导 HTML,再进行精确匹配。
该页面中,广告区与真实比价区之间存在一个稳定的结构锚点:<div class="SortBy">(即“按价格/评分排序”标题栏)。它标志着广告结束、真实商家列表开始。因此,应优先使用 strstr() 提取从该标记起的后续全部 HTML:
// 截取从第一个 <div class="SortBy"> 开始的子串(含该标签)
$str = strstr($str, '<div class="SortBy">');
if ($str === false) {
throw new RuntimeException('未找到 SortBy 分隔标识,可能页面结构已变更');
}完成预处理后,再执行安全、非贪婪的正则匹配:
$pattern = '/<div\s+class="StoreLine">(.*?)<(?:div\s+class="SmartBuyButtons"|div\s+class="BuyButtons")>/is';
preg_match_all($pattern, $str, $matches, PREG_SET_ORDER);
// $matches 现在只包含真实商家区块(含完整 HTML 片段)
$stores = [];
foreach ($matches as $match) {
$stores[] = $match[0]; // 完整匹配字符串(含 StoreLine 至 BuyButtons)
}✅ 关键优化说明:
- 使用 i(忽略大小写)和 s(. 匹配换行符)修饰符提升鲁棒性;
- .*? 采用非贪婪模式,避免跨区块误匹配;
- 替换原正则中易出错的 *.*? 冗余写法,明确限定起始标签为 <div\s+class="StoreLine">(\s+ 更容错空格/换行);
- 使用 PREG_SET_ORDER 返回结构化数组,便于后续 DOM 解析或字段提取。
⚠️ 注意事项:
立即学习“PHP免费学习笔记(深入)”;
- 此方案依赖页面稳定的语义分隔符(如 SortBy)。若目标站点改版,需同步更新锚点选择器;
- 强烈建议后续用 DOMDocument 或 simple_html_dom 解析 $stores 中的 HTML 片段,而非二次正则提取价格/店名——更健壮、可维护;
- 生产环境务必添加异常处理与超时控制,避免因网络或 HTML 异常导致脚本中断。
总结:正则表达式擅长“局部模式匹配”,但面对复杂 HTML 层级结构时,“先宏观截断、再微观提取”往往比强行设计超长正则更简洁、高效且易于调试。











