首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP Snoopy 爬取圖片實戰:抓取文章列表、比對規則、下載儲存

     編輯:PHP 綜合知識

Snoopy 沒有內建「抓取所有圖片」的方法,但結合 fetchlinks() 取得文章連結、fetch() 取得內文、正則比對 <img src=...> 即可完成完整圖片爬取流程。

完整實作流程

  1. 抓取列表頁所有連結(fetchlinks)
  2. 篩選符合文章頁面規則的 URL(如 /article/123.html)
  3. 逐一抓取文章頁 HTML(fetch)
  4. 正則擷取 <img src="https://..."> 的絕對路徑
  5. 依副檔名與 ID 分類儲存,避免重複檔案

核心程式碼

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))["\'] 同時支援單雙引號、限定副檔名、排除相對路徑。
  • 防盜鏈:若目標站有 Referer 檢查,請在 $snoopy->referer 設為文章頁 URL。
  • 大檔案/記憶體:大量圖片建議改用 curl 串流下載,避免 file_get_contents 佔滿記憶體。
  • 編碼問題:抓取 Big5/GB2312 頁面需先 mb_convert_encoding($html, 'UTF-8', 'BIG5') 再比對正則。

延伸話題:就地修改大型文字檔

文章末尾提到的「不讀整檔、直接 fseek 覆寫」在行長度變化時會損毀後續資料。正確做法:

  • 小檔:file() 讀陣列 → 修改 → file_put_contents()
  • 大檔:建立暫存檔,逐行讀取、處理、寫入暫存檔 → rename() 覆蓋原檔
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved