QueryList 是一個基於 phpQuery (jQuery 選擇器 PHP 移植版) 的通用採集類,支援 HTTPS、列表採集、區塊範圍限定、多欄位提取,適合快速開發各類爬蟲任務。
.title a, img[src]) 定位元素<?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);
}
}
<?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 )
...
)
*/
<?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"},...]
*/
<?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"] |
iconv 轉碼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 相似度高。