一、時間軸:一次“抓不到重點”的二手車數據爬蟲事故
- 2025/03/18 09:00
產品經理希望抓取懂車帝平臺上“北京地區二手車報價”作為競品監測數據源。我們初步使用傳統XPath
方案,試圖提取車型、年限、里程、價格等數據。 - 2025/03/18 10:00
初版腳本運行失敗,返回的數據全是空值,XPath
定位的路徑在頁面中根本不存在。 - 2025/03/18 11:00
檢查HTML源代碼發現,頁面由**前端異步渲染(JavaScript動態生成)**構建,傳統靜態DOM無法解析真實內容。 - 2025/03/18 14:00
改用Playwright模擬瀏覽器渲染,成功獲取完整DOM。但新的問題是:頁面結構復雜、不穩定,多個汽車列表卡片并非結構統一,手動XPath依舊容易出錯。 - 2025/03/19 10:00
啟動深度學習方案:利用預訓練模型BERT對HTML做塊級語義識別,自動提取“車卡片”結構與核心字段。
二、方案分析:XPath失效 vs 語義塊提取
1. 初始方案失敗原因
- 頁面為前端渲染(SPA架構),傳統的
requests + XPath
方案根本無法加載數據; - 即使用Playwright動態渲染后獲取HTML,汽車信息DOM結構依舊不穩定,嵌套層級深,XPath脆弱;
- 頁面存在部分反爬機制(navigator.webdriver特征、IP頻控、UA檢測),需解決隱藏身份問題。
2. 深度學習方案構思
- 將完整HTML節點轉為token序列(含標簽結構+文本);
- 使用BERT或LayoutLM模型對DOM節點進行語義分類,標注“車卡片”、“車型名”、“報價”等字段;
- 利用位置+標簽結構配合抽取規則,提高抗變動能力;
- 構建領域微調訓練樣本,通過正則與標注相結合構建少量訓練集。
三、架構改進方案:深度語義解析 + 隱身身份訪問
以下是優化后的爬蟲架構,融合了:
- Playwright動態渲染頁面;
- 代理IP隱藏身份(爬蟲代理);
- 設置cookie與user-agent;
- 調用深度學習模塊提取語義塊。
? 示例代碼如下:
import asyncio
from playwright.async_api import async_playwright
import base64
import json
import torch
from transformers import BertTokenizer, BertForTokenClassification
from typing import List# === 億牛云代理配置 www.16yun.cn ===
PROXY_SERVER = "http://proxy.16yun.cn:3100"
PROXY_USERNAME = "16YUN"
PROXY_PASSWORD = "16IP"# Base64編碼代理身份
def get_proxy_auth():credentials = f"{PROXY_USERNAME}:{PROXY_PASSWORD}"return "Basic " + base64.b64encode(credentials.encode()).decode()# === 深度學習模型加載(模擬)===
tokenizer = BertTokenizer.from_pretrained("bert-base-chinese")
model = BertForTokenClassification.from_pretrained("bert-base-chinese")def predict_blocks(text_list: List[str]) -> List[str]:"""使用BERT模擬DOM區塊分類輸入:文本列表(如標簽+內容組成)輸出:每個文本的分類結果,如[車型] [年限] [報價]"""inputs = tokenizer(text_list, return_tensors="pt", padding=True, truncation=True)with torch.no_grad():outputs = model(**inputs).logitspredictions = torch.argmax(outputs, dim=-1)labels = [model.config.id2label[idx.item()] for idx in predictions[0]]return labels# === Playwright爬蟲主流程 ===
async def main():async with async_playwright() as p:browser = await p.chromium.launch(headless=True)# 啟動代理 + 設置UA和Cookiecontext = await browser.new_context(proxy={"server": PROXY_SERVER},user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/122.0.0.0 Safari/537.36",extra_http_headers={"Proxy-Authorization": get_proxy_auth(),"Cookie": "your_cookie_here" # 真實抓包填入cookie})page = await context.new_page()# 搜索“北京二手車”await page.goto("https://www.dongchedi.com/usedcar/search?city_name=%E5%8C%97%E4%BA%AC")await page.wait_for_timeout(5000) # 等待JS加載完# 提取頁面HTMLhtml = await page.content()# 簡化提取所有車卡片文本(真實項目中解析DOM結構)elements = await page.query_selector_all("div.CarCard_card__...") # 選擇器根據真實頁面調整for el in elements:text = await el.inner_text()label = predict_blocks([text])[0]print(f"[{label}] {text}")await browser.close()asyncio.run(main())
四、總結與優化建議
📌 深度學習DOM解析優點:
- 抗結構變化能力強,不再依賴脆弱的XPath;
- 適合復雜網頁(如懂車帝、汽車之家等)中提取卡片、列表、評論等區域;
- 可結合小樣本微調適應特定領域,如二手車、新聞等。
?? 技術架構演進圖
[靜態爬蟲Requests+XPath] ──> [動態爬蟲Playwright+XPath] ──> [Playwright+DOM語義BERT]?失效 ??結構脆弱 ?語義提取,穩定高效
附加建議
- 如需更高精度,可構建100~300條有標注數據微調BERT;
- 可加入圖神經網絡(如DOM-GCN)提升DOM上下文理解;
- 建議結合VisualDOM信息(元素位置+截圖)形成多模態提取模型。