在爬蟲、內容分析、數據清洗等場景中,常需要從 HTML 頁面中提取鏈接、郵箱、圖片等結構化信息。本文提供一個封裝良好的 Grep 類,支持提取與替換三類核心內容,基於正則表達式實現,靈活易擴展。
<?php
/**
* Grep 類:從 HTML 字符串中提取/替換 URL、Email、Image
* @author fdipzone
* @version 1.0
*/
class Grep {
// 內部正則模式(私有,防止外部誤改)
private $_pattern = array(
'url' => '/<a.*?href="((http(s)?:\/\/).*?)".*?/si',
'email' => '/([\w\-\.]+@[\w\-\.]+(\.\w+)+)/',
'image' => '/<img.*?src="(https?:\/\/.+?\.(jpg|jpeg|gif|bmp|png))"/i'
);
private $_content = ''; // 待處理的 HTML 內容
/**
* 設置源內容
* @param string $content
*/
public function set($content = '') {
$this->_content = $content;
}
/**
* 獲取指定類型的內容
* @param string $type 類型:url, email, image
* @param int $unique 0=全部, 1=去重
* @return array
*/
public function get($type = '', $unique = 0) {
$type = strtolower($type);
if ($this->_content === '' || !isset($this->_pattern[$type])) {
return array();
}
$pattern = $this->_pattern[$type];
preg_match_all($pattern, $this->_content, $matches);
$result = isset($matches[1]) ? $matches[1] : array();
return $unique ? array_unique($result) : $result;
}
/**
* 替換指定類型的內容
* @param string $type
* @param callable $callback 回調函數,接收 $matches 返回替換字符串
* @return string 替換後的 HTML
*/
public function replace($type = '', $callback = '') {
$type = strtolower($type);
if ($this->_content === '' || !isset($this->_pattern[$type]) || !$callback) {
return $this->_content;
}
return preg_replace_callback($this->_pattern[$type], $callback, $this->_content);
}
}
?>
<?php
header('Content-Type: text/html; charset=utf-8');
require('Grep.class.php');
// 獲取遠程頁面內容(實際項目建議用 cURL 並設置超時)
$html = file_get_contents('https://www.example.com/');
$grep = new Grep();
$grep->set($html);
// 1. 提取所有鏈接(不去重)
$urls = $grep->get('url', 0);
print_r($urls);
// 2. 提取郵箱(去重)
$emails = $grep->get('email', 1);
print_r($emails);
// 3. 提取圖片鏈接(去重)
$images = $grep->get('image', 1);
print_r($images);
// 4. 替換鏈接:將 <a href="...">...</a> 替換為 [url]...[/url] 格式
$new_html = $grep->replace('url', 'replace_url_callback');
echo $new_html;
function replace_url_callback($matches) {
return isset($matches[1]) ? '[url]'.$matches[1].'[/url]' : '';
}
?>
| 類型 | 正則 | 說明 | 潛在問題 |
|---|---|---|---|
| URL | /<a.*?href="((http(s)?:\/\/).*?)".*?/si | 匹配 a 標籤 href 屬性,捕獲完整 URL | 不匹配單引號、無協議鏈接、JS 生成鏈接 |
/([\w\-\.]+@[\w\-\.]+(\.\w+)+)/ | 標準郵箱格式匹配 | 可能匹配到文本中的類郵箱字符串 | |
| Image | /<img.*?src="(https?:\/\/.+?\.(jpg|jpeg|gif|bmp|png))"/i | 匹配 img 標籤 src,限定常見圖片後綴 | 不匹配 data URI、WebP、懶加載 data-src、單引號 |
private $_pattern = array(
'url' => '/<a\s[^>]*href\s*=\s*["\']?([^"\'\s>]+)["\']?/si', // 支持單雙引號、無引號
'email' => '/\b[\w\-\.]+@[\w\-\.]+\.\w{2,}\b/', // 詞邊界限定,減少誤匹配
'image' => '/<img\s[^>]*src\s*=\s*["\']?([^"\'\s>]+\.(?:jpg|jpeg|gif|png|webp|bmp))["\']?/i' // 支持 WebP、單雙引號
);
phone、id_card、ip 等提取模式。DOMDocument 解析 HTML,比正則更可靠處理巢狀、屬性順序不固定等情況。該類為輕量級提取需求提供了清晰的 OOP 介面,適合中小型爬蟲、內容審核、編輯器過濾等場景。生產環境建議配合 DOM 解析器使用,提升魯棒性。