Snoopy 沒有內建「抓取所有圖片」的方法,但結合 fetchlinks() 取得文章連結、fetch() 取得內文、正則比對 <img src=...> 即可完成完整圖片爬取流程。
fetchlinks)/article/123.html)fetch)<img src="https://..."> 的絕對路徑include 'snoopy/Snoopy.class.php';
$sourceURL = 'https://target.site/list.html';
$snoopy = new Snoopy;
$snoopy->fetchlinks($sourceURL);
$articlePattern = '/\d+\.html$/'; // 文章頁面規則
$imgPattern = '/<img[^>]+src=["\'](https?:\/\/[^"\']+\.(?:jpg|png|gif|jpeg))["\']/i';
foreach ($snoopy->results as $link) {
if (!preg_match($articlePattern, $link)) continue;
fetchAndSaveImages($link);
}
function fetchAndSaveImages($url) {
global $imgPattern;
$snoopy = new Snoopy;
$snoopy->fetch($url);
$html = $snoopy->results;
if (preg_match_all($imgPattern, $html, $matches)) {
foreach ($matches[1] as $imgUrl) {
saveImage($imgUrl);
}
}
}
function saveImage($url) {
$ext = pathinfo($url, PATHINFO_EXTENSION);
$id = basename($url, ".{$ext}"); // 假設檔名為 ID
$dir = ($ext === 'gif') ? 'emotion' : 'topic';
$path = "E:/www/images/{$dir}/{$id}.{$ext}";
if (is_file($path)) {
unlink($path);
echo "舊檔刪除:{$path}\n";
}
$data = @file_get_contents($url);
if ($data !== false && file_put_contents($path, $data)) {
echo "儲存成功:{$path}\n";
} else {
echo "下載失敗:{$url}\n";
}
}
src=["\'](https?:\/\/[^"\']+\.(?:jpg|png|gif|jpeg))["\'] 同時支援單雙引號、限定副檔名、排除相對路徑。$snoopy->referer 設為文章頁 URL。curl 串流下載,避免 file_get_contents 佔滿記憶體。mb_convert_encoding($html, 'UTF-8', 'BIG5') 再比對正則。文章末尾提到的「不讀整檔、直接 fseek 覆寫」在行長度變化時會損毀後續資料。正確做法:
file() 讀陣列 → 修改 → file_put_contents()rename() 覆蓋原檔