淘寶開放平台提供官方 API(需應用備案、簽名驗證),適合正規商業項目。若僅需公開頁面數據(圖片、標題、價格),file_get_contents + 正則提取是零成本快速方案。本文基於淘寶 PC 端頁面結構(GBK 編碼)實測可用。
file_get_contents($url) 獲取頁面完整 HTML(字符串)<?php
$url = "https://item.taobao.com/item.htm?id=2380347279";
$html = file_get_contents($url);
// 正則匹配 id="J_ImgBooth" 的 img 標簽
preg_match('/<img[^>]*id="J_ImgBooth"[^>]*src=["\']([^"\']+)["\']/i', $html, $m);
$img500 = $m[1] ?? ''; // 圖片 URL(通常為 //g.alicdn.com/... 或 https://img.alicdn.com/...)
?>
關鍵點:淘寶主圖 ID 固定為 J_ImgBooth,正則只需鎖定此 ID 提取 src 屬性。
<?php
preg_match('/<title>([^<>]+)<\/title>/i', $html, $m);
$title = $m[1] ?? '';
// 淘寶頁面 GBK 編碼,UTF-8 項目需轉碼
$title = iconv('GBK', 'UTF-8//IGNORE', $title);
?>
注意:title 含「- 淘寶網」後綴,實際使用時可 str_replace('- 淘寶網', '', $title) 去除。
<?php
// id="J_StrPrice" 通常在 <strong> 或 <em> 標簽中
preg_match('/<[a-z]+[^>]*id="J_StrPrice"[^>]*>([^<]+)<\/[a-z]+>/is', $html, $m);
$price = floatval($m[1] ?? 0); // 轉浮點數入庫
?>
屬性區塊結構:<div class="attributes">...</div> 後緊跟 <div id="description"> 或 <div class="box J_TBox">。利用這一固定順序「切片」提取:
<?php
// 1. 從 attributes 開始截取到頁面末尾
preg_match('/<div[^>]*class="attributes"[^>]*>.*<\/div>/is', $html, $m);
$block = $m[0] ?? '';
// 2. 刪除 description 及其後內容
$block = preg_replace('/<\/div>[^<]*<div[^>]*id="description"[^>]*>.*<\/div>/is', '', $block);
// 3. 刪除 J_TBox 及其後內容(若存在)
$block = preg_replace('/<\/div>[^<]*<div[^>]*class="box J_TBox"[^>]*>.*<\/div>/is', '', $block);
$attributesHtml = $block; // 含完整屬性 HTML,可直接嵌入頁面或進一步解析
?>
原理:正則無法遞歸匹配任意深度巢狀標簽,但利用淘寶頁面「區塊順序固定」特性,通過多次 preg_replace 刪除後續區塊,反向保留目標區塊。
描述內容不在初始 HTML 中,由 JS 從淘寶 CDN 異步加載。解決方案:注入原頁面所有 JS + 必需 DOM 容器,讓瀏覽器自動執行加載邏輯。
<?php
// 1. 提取頁面所有 <script> 標簽
preg_match_all('/<script[^>]*>.*?<\/script>/is', $html, $m);
$scripts = $m[0];
// 2. 構建描述加載必需 DOM 結構
$descContainer = '<div id="detail"></div>
<div id="description">
<div id="J_DivItemDesc">描述加載中</div>
</div>';
// 3. 合併 JS + 容器(轉碼至 UTF-8)
$description = $descContainer;
foreach ($scripts as $js) {
$description .= iconv('GBK', 'UTF-8//IGNORE', $js);
}
// 4. 前端頁面直接輸出 $description,瀏覽器自動執行 JS 渲染描述
// 注意:同頁多商品描述會衝突(ID 重複),需 iframe 隔離或單商品頁使用
?>
<?php
function fetchTaobaoItem($itemId) {
$url = "https://item.taobao.com/item.htm?id=$itemId";
$html = @file_get_contents($url);
if (!$html) return ['error' => 'HTTP 請求失敗'];
$data = ['item_id' => $itemId];
// 主圖
preg_match('/<img[^>]*id="J_ImgBooth"[^>]*src=["\']([^"\']+)["\']/i', $html, $m);
$data['image'] = $m[1] ?? '';
// 標題
preg_match('/<title>([^<>]+)<\/title>/i', $html, $m);
$data['title'] = iconv('GBK', 'UTF-8//IGNORE', $m[1] ?? '');
// 價格
preg_match('/<[a-z]+[^>]*id="J_StrPrice"[^>]*>([^<]+)<\/[a-z]+>/is', $html, $m);
$data['price'] = floatval($m[1] ?? 0);
// 屬性(HTML 片段)
preg_match('/<div[^>]*class="attributes"[^>]*>.*<\/div>/is', $html, $m);
$attr = $m[0] ?? '';
$attr = preg_replace('/<\/div>[^<]*<div[^>]*id="description"[^>]*>.*<\/div>/is', '', $attr);
$attr = preg_replace('/<\/div>[^<]*<div[^>]*class="box J_TBox"[^>]*>.*<\/div>/is', '', $attr);
$data['attributes_html'] = iconv('GBK', 'UTF-8//IGNORE', $attr);
// 描述加載器
preg_match_all('/<script[^>]*>.*?<\/script>/is', $html, $m);
$desc = '<div id="detail"></div><div id="description"><div id="J_DivItemDesc">加載中...</div></div>';
foreach ($m[0] as $js) $desc .= iconv('GBK', 'UTF-8//IGNORE', $js);
$data['description_loader'] = $desc;
return $data;
}
?>
| 風險 | 應對 |
|---|---|
| IP 限流/封禁 | 代理池輪換、請求間隔隨機化(2-5秒)、模擬真實 UA/Referer/Cookie |
| 頁面結構變更 | 建立選擇器配置文件,異常時告警人工修正;優先用官方 API |
| 登錄態要求 | 維護 Cookie 池(掃碼登錄獲取),定期檢測有效性 |
| 法律合規 | 遵守 robots.txt、淘寶開放平台協議、數據安全法;純公開信息采集風險較低,但商業化建議走官方渠道 |
正則采集淘寶公開頁面可行性高、成本低,關鍵技巧在於:利用固定 ID 定位、GBK 轉 UTF-8、JS 注入解決異步描述、區塊順序切片提取巢狀結構。生產環境請務必加入代理、限流、告警、合規審查模塊。