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

基於 phpQuery 的 PHP 通用採集類 QueryList 完整實作與使用指南

     編輯:PHP 相關知識

QueryList 是一個基於 phpQuery (jQuery 選擇器 PHP 移植版) 的通用採集類,支援 HTTPS、列表採集、區塊範圍限定、多欄位提取,適合快速開發各類爬蟲任務。

核心特色

  • 語法直觀:使用 CSS 選擇器 (如 .title a, img[src]) 定位元素
  • 支援 HTTPS:內建 cURL 取得內容,自動處理 SSL 驗證
  • 區塊採集:先定位列表容器,再在區塊內提取欄位,結構清晰
  • 多輸出格式:陣列、JSON 靈活切換
  • 可複用:同一頁面可多次設定不同規則採集

QueryList 類完整原始碼

<?php
/**
 * 通用列表採集類 QueryList v1.3
 * 依賴: phpQuery (需自行下載放置於 ../phpQuery/phpQuery/phpQuery.php)
 */

require_once '../phpQuery/phpQuery/phpQuery.php';

class QueryList {
    private $pageURL;
    private $regArr = [];
    public $jsonArr = [];
    private $regRange;
    private $html;

    /**
     * 建構子:可直接執行採集
     * @param string $pageURL 目標網址
     * @param array $regArr 選擇器規則陣列 ['欄位名' => ['選擇器', '類型']]
     * @param string $regRange 區塊選擇器 (列表容器)
     */
    public function __construct($pageURL, $regArr = [], $regRange = '') {
        $this->pageURL = $pageURL;
        
        // 使用 cURL 取得網頁內容 (支援 HTTPS)
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->pageURL,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; QueryList Bot)'
        ]);
        $this->html = curl_exec($ch);
        curl_close($ch);
        
        if (!empty($regArr)) {
            $this->regArr = $regArr;
            $this->regRange = $regRange;
            $this->getList();
        }
    }

    /**
     * 重新設定規則並執行採集 (同一頁面多次採集)
     */
    public function setQuery($regArr, $regRange = '') {
        $this->jsonArr = [];
        $this->regArr = $regArr;
        $this->regRange = $regRange;
        $this->getList();
    }

    /**
     * 核心採集邏輯
     */
    private function getList() {
        $hobj = phpQuery::newDocumentHTML($this->html);
        
        if (!empty($this->regRange)) {
            // === 區塊採集模式 ===
            $robj = pq($hobj)->find($this->regRange);
            $i = 0;
            
            foreach ($robj as $item) {
                foreach ($this->regArr as $key => $reg_value) {
                    $iobj = pq($item)->find($reg_value[0]);
                    
                    switch ($reg_value[1]) {
                        case 'text':
                            $this->jsonArr[$i][$key] = trim(pq($iobj)->text());
                            break;
                        case 'html':
                            $this->jsonArr[$i][$key] = trim(pq($iobj)->html());
                            break;
                        default:  // 屬性值 (href, src, alt, title...)
                            $this->jsonArr[$i][$key] = pq($iobj)->attr($reg_value[1]);
                            break;
                    }
                }
                $i++;
            }
        } else {
            // === 全域採集模式 ===
            foreach ($this->regArr as $key => $reg_value) {
                $lobj = pq($hobj)->find($reg_value[0]);
                $i = 0;
                
                foreach ($lobj as $item) {
                    switch ($reg_value[1]) {
                        case 'text':
                            $this->jsonArr[$i++][$key] = trim(pq($item)->text());
                            break;
                        case 'html':
                            $this->jsonArr[$i++][$key] = trim(pq($item)->html());
                            break;
                        default:
                            $this->jsonArr[$i++][$key] = pq($item)->attr($reg_value[1]);
                            break;
                    }
                }
            }
        }
    }

    /**
     * 獲取 JSON 格式結果
     */
    public function getJSON() {
        return json_encode($this->jsonArr, JSON_UNESCAPED_UNICODE);
    }
}

使用範例集錦

範例 1:採集 OSChina 代碼分享列表

<?php
require 'Query/QueryList.class.php';

// 目標頁面
$url = "https://www.oschina.net/code/list";

// 採集規則:標題、連結、作者
$reg = [
    "title" => [".code_title a:eq(0)", "text"],
    "url"   => [".code_title a:eq(0)", "href"],
    "author"=> ["img", "title"]
];

// 列表容器選擇器
$range = ".code_list li";

$hj = new QueryList($url, $reg, $range);
$arr = $hj->jsonArr;
print_r($arr);

/* 輸出範例:
Array
(
    [0] => Array ( [title] => 精美的登入介面 [url] => /code/snippet_123 [author] => user001 )
    [1] => Array ( [title] => 圖片延遲載入 [url] => /code/snippet_456 [author] => user002 )
    ...
)
*/

範例 2:同頁面二次採集 (右側 TOP 貢獻者頭像)

<?php
// 同一個 QueryList 實例,重新設定規則
$reg = [
    "portrait" => [".hot_top img", "src"]
];
$hj->setQuery($reg);  // 無區塊限定,全域查找
$json = $hj->getJSON();
echo $json . "<hr/>";

/* 輸出:
[{"portrait":"https://static.oschina.net/uploads/user/100/200.jpg"},...]
*/

範例 3:採集內容頁詳細資訊

<?php
$url = "https://www.oschina.net/code/snippet_186288_23816";

$reg = [
    "title" => [".QTitle h1", "text"],
    "con"   => [".Content", "html"]
];

$hj = new QueryList($url, $reg);  // 無區塊模式
$arr = $hj->jsonArr;
print_r($arr);

選擇器類型完整對照

類型值說明範例
"text"元素純文字內容[".title", "text"]
"html"元素內部 HTML[".content", "html"]
"href"連結地址["a", "href"]
"src"圖片/iframe 來源["img", "src"]
"attr名稱"任意屬性值["input", "value"], ["div", "data-id"]

進階技巧與注意事項

  • 編碼處理:phpQuery 預設 UTF-8,抓取 Big5/GBK 頁面需先 iconv 轉碼
  • 動態內容:JS 渲染內容無法直接採集,需搭配 Selenium/PhantomJS 或分析 API
  • 反爬蟲:加入 CURLOPT_COOKIEJAR 維持 Session、隨機 User-Agent、請求間隔 sleep()
  • 記憶體管理:大量採集時定期 phpQuery::$documents = [] 釋放 DOM 物件
  • 錯誤處理:檢查 curl_errno()、HTTP 狀態碼、選擇器匹配結果是否為空

擴展建議

<?php
// 擴展:支援 POST 請求、Header 自訂、代理 IP
class QueryListPro extends QueryList {
    public function __construct($url, $regArr = [], $regRange = '', $options = []) {
        // $options: ['method'=>'POST', 'post_data'=>[], 'headers'=>[], 'proxy'=>'ip:port']
        // 覆寫 cURL 設定邏輯...
    }
    
    // 擴展:分頁採集
    public function crawlPages($page_url_pattern, $start, $end, $regArr, $regRange) {
        for ($p = $start; $p <= $end; $p++) {
            $url = sprintf($page_url_pattern, $p);
            $this->setQuery($regArr, $regRange);
            // 處理 $this->jsonArr...
            sleep(1);  // 禮貌延遲
        }
    }
}

phpQuery 專案已停止維護,新專案建議考慮 PHP HTML Parser 或 Symfony DomCrawler 作為替代,API 相似度高。

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