产品经理希望抓取懂车帝平台上“北京地区二手车报价”作为竞品监测数据源。我们初步使用传统XPath
方案,试图提取车型、年限、里程、价格等数据。
初版脚本运行失败,返回的数据全是空值,XPath
定位的路径在页面中根本不存在。
检查HTML源代码发现,页面由前端异步渲染(JavaScript动态生成)构建,传统静态DOM无法解析真实内容。
改用Playwright模拟浏览器渲染,成功获取完整DOM。但新的问题是:页面结构复杂、不稳定,多个汽车列表卡片并非结构统一,手动XPath依旧容易出错。
启动深度学习方案:利用预训练模型BERT对HTML做块级语义识别,自动提取“车卡片”结构与核心字段。
requests + XPath
方案根本无法加载数据;以下是优化后的爬虫架构,融合了:
import asyncio
from playwright.async_api import async_playwright
import base64
import json
import torch
from transformers import BertTokenizer, BertForTokenClassification
from typing import List
# === 亿牛云代理配置 ===
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).logits
predictions = 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和Cookie
context = 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加载完
# 提取页面HTML
html = 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())
[静态爬虫Requests+XPath] ──> [动态爬虫Playwright+XPath] ──> [Playwright+DOM语义BERT]
❌失效 ⚠️结构脆弱 ✅语义提取,稳定高效
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。