首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

PHP 正則表達式提取 DIV 內 A 標籤的 HREF 與內容實戰

     編輯:關於C++

許多開發者在久違地重拾正則表達式時,都會有種「似曾相識」的熟悉感:明明是個小案例,卻總覺得得徹底搞懂不可,於是翻閱手冊、寫測試、終於豁然開朗,但下次遇到又得從頭來過。今天就把實務上常用的「兩階段匹配法」記錄下來,供日後快速參考。

核心思路:分而治之

直接對整張 HTML 寫一個超級複雜的正則既難維護又易出錯,不如拆成兩步走:

  1. 先鎖定目標區塊:用 pattern1 把包含目標連結的 <div> 區塊完整擷取出來。
  2. 再精準抓取連結:在已縮小的字串裡用 pattern2 專門匹配 <a href="...">文字</a>,捕獲組 1 取 href,捕獲組 2 取顯示文字。

最小可行性 Demo (PHP)

$str = '<div><a href="shoes/running.html">跑步鞋</a><a href="shoes/basketball.html">籃球鞋</a></div>tryagin';

// 階段 1:取出第一個 div 區塊
preg_match_all('/<div>(.*?)<\/div>/is', $str, $matches);
$target_content = $matches[0][0] ?? '';

// 階段 2:抓取所有 a 標籤的 href 與文字
preg_match_all('/<a\s+href="([^"]+)">(.*?)<\/a>/is', $target_content, $matches_detail);
$href_content   = $matches_detail[1] ?? []; // 連結陣列
$detail_content = $matches_detail[2] ?? []; // 文字陣列

print_r($href_content);   // Array ( [0] => shoes/running.html [1] => shoes/basketball.html )
print_r($detail_content); // Array ( [0] => 跑步鞋 [1] => 籃球鞋 )

實戰封裝:CodeIgniter Model 範例

在實際專案中,常需從 CMS 後台撈取版面內容並解析。下方示範一個可復用的私有方法 get_topic_data(),搭配 clearData() 清理換行/製表符,並支援多主題館(運動、女鞋、男鞋、戶外、童鞋)不同正則規則:

private function get_topic_data($topic, $pattern1, $pattern2) {
    $data = [];
    if (empty($topic) || empty($pattern1) || empty($pattern2)) return $data;

    // 1. 依部門名找頁面 ID
    $modpage_id = 0;
    foreach ($this->Modpage_Model->getAllPages() as $page) {
        if ($page['department'] === $topic) { $modpage_id = $page['id']; break; }
    }

    // 2. 取得目前版本內容
    $version = $this->Modpage_Model->getCurrentPageVersion($modpage_id);
    $raw_data = $this->Modpage_Model->getVersionData($modpage_id, $version['version']);

    // 3. 依模組類型挑選解析字串
    $parse_str = '';
    foreach ($raw_data as $v) {
        if ($topic === 'children') {
            if ($v['module_id'] == 1 && $v['desc'] === '快速找寶貝') { $parse_str = $v['content']; break; }
        } else {
            if ($v['module_id'] == 4) { $parse_str = $v['content']; break; }
        }
    }

    // 4. 兩階段正則 + 清洗 + 域名替換
    $parse_str = $this->clearData($parse_str);
    preg_match_all($pattern1, $parse_str, $m);
    $target = $m[0][0] ?? '';
    $target = str_replace($this->website, TOUCH_URL, $target);
    $target = $this->clearData($target);
    preg_match_all($pattern2, $target, $md);
    $data['href_content']   = $md[1] ?? [];
    $data['detail_content'] = $md[2] ?? [];
    return $data;
}

private function clearData($str) {
    if (empty($str)) return '';
    return trim(str_replace(["\r", "\n", "\t"], '', $str));
}

控制器呼叫範例

public function index() {
    $topic_map = [
        'sports'     => ['sport',     '/<div class="sport">(.*?)<\/div>/is', '/<a href="([^"]+)">(.*?)<\/a>/is'],
        'womenshoes' => ['women',     '/<div class="women">(.*?)<\/div>/is', '/<a href="([^"]+)">(.*?)<\/a>/is'],
        'menshoes'   => ['man',       '/<div class="man">(.*?)<\/div>/is',   '/<a href="([^"]+)">(.*?)<\/a>/is'],
        'outdoor'    => ['outdoor',   '/<div class="outdoor">(.*?)<\/div>/is', '/<a href="([^"]+)">(.*?)<\/a>/is'],
        'children'   => ['children',  '/<div class="children">(.*?)<\/div>/is', '/<a href="([^"]+)">(.*?)<\/a>/is'],
    ];

    $data['data'] = [];
    foreach ($topic_map as $type => $patterns) {
        $res = $this->get_topic_data($type, $patterns[1], $patterns[2]);
        $data['data'][$patterns[0]] = $res;
    }
    // 載入視圖...
}

關鍵提醒

  • 正則加 s (DOTALL) 讓 . 能匹配換行,避免多行 HTML 斷裂。
  • 捕獲組 () 只取需要的部分,$matches[1]、$matches[2] 直接對應 href 與文字。
  • 資料來源若不可控,建議改用 DOMDocument 或 QueryList 等解析器,更穩健。

把這套「先切塊、再細抓」的模式記住,下次遇到同類需求就能開工即寫,不再重複踩坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved