
传统定向爬虫依赖人工编写CSS选择器与XPath语法,针对异构站点适配成本高;网页迭代改版后,原有匹配规则极易失效。大语言模型(LLM)具备HTML语义解析能力,可自适应异构页面,无需人工维护选择器,显著降低爬虫开发运维成本。本文构建LLM驱动的智能爬虫架构,实现页面采集—HTML精炼—结构化提取—语义清洗自动化流程,结合亿牛云代理IP规避封禁限制,完成高通用性、高稳定性的数据采集方案。一、传统爬虫与大模型爬虫对比从提取机制、迭代适配、成本开销等维度对比两类爬虫技术,明确差异化适用场景:
维度 | 传统规则爬虫 | 大模型爬虫 |
|---|---|---|
数据提取 | 人工编写选择器语法 | LLM语义解析自动提取 |
页面迭代 | 规则失效,需二次开发 | 自适应页面结构变更 |
数据清洗 | 正则+规则引擎格式清洗 | 语义级智能标准化清洗 |
开发成本 | 单站单独定制规则 | 通用Prompt跨站复用 |
准确率 | 高精度硬匹配 | 中高准确率(依赖模型性能) |
响应速度 | 毫秒级响应 | 1~3秒/次(模型推理耗时) |
运行成本 | 算力成本极低 | 含模型API调用费用 |
1.1 场景适配原则传统爬虫:页面结构固化、对延迟与准确率要求严苛的采集场景。大模型爬虫:站点量大、页面异构性强、规则维护成本高的业务场景。混合架构:LLM生成适配选择器,规则引擎执行高速提取,兼顾通用性与采集效率。二、技术架构与选型2.1 整体流程本文采用线性串联架构,依托代理IP实现反爬防护,流程如下: 网页采集 → HTML冗余剔除 → LLM结构解析 → JSON结构化输出 → 语义清洗 → 本地化存储 辅助模块:动态代理IP,实现请求指纹离散化,规避访问封禁2.2 技术栈选型
组件 | 技术方案 | 选型依据 |
|---|---|---|
HTTP请求 | requests | 轻量稳定,兼容代理隧道配置 |
HTML预处理 | BeautifulSoup | 精简网页结构,降低LLM Token开销 |
大模型 | GPT-4o-mini | 性价比高,结构化JSON输出稳定性优异 |
代理IP | 亿牛云动态转发代理 | 毫秒级IP轮换,适配高频采集反爬场景 |
三、环境依赖执行以下命令安装项目依赖库:
四、核心代码实现4.1 全局参数配置集中管理模型接口、代理隧道、请求头参数,便于工程化维护:
import requests
import json
import random
import time
from bs4 import BeautifulSoup
from openai import OpenAI
# 模型接口配置
OPENAI_API_KEY = "your-api-key"
OPENAI_BASE_URL = "https://api.openai.com/v1"
MODEL_NAME = "gpt-4o-mini"
# 代理隧道配置
PROXY_CONFIG = {
"host": "t.16yun.cn",
"port": "31111",
"user": "username",
"pass": "password"
}
proxy_meta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % PROXY_CONFIG
PROXIES = {"http": proxy_meta, "https": proxy_meta}
# 模拟浏览器请求头
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/125.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
}4.2 页面采集与HTML精炼为控制LLM输入Token量级,需剔除网页冗余标签与无效属性,保留语义骨架;同时集成代理IP实现指纹混淆。
def fetch_page(url, use_proxy=True):
"""网页采集+异常容错+代理轮换"""
req_headers = HEADERS.copy()
if use_proxy:
tunnel = random.randint(1, 10000)
req_headers['Proxy-Tunnel'] = str(tunnel)
try:
resp = requests.get(url, headers=req_headers, proxies=PROXIES if use_proxy else None, timeout=15)
resp.raise_for_status()
return clean_html(resp.text)
except requests.exceptions.HTTPError as e:
status = e.response.status_code if e.response else 0
if status == 429:time.sleep(3)
print(f"HTTP异常码:{status}")
return None
except Exception as e:
print(f"采集异常:{e}")
return None
def clean_html(html):
"""HTML语义精炼:剔除噪音标签,压缩上下文"""
soup = BeautifulSoup(html, 'html.parser')
# 移除非功能性标签
for tag in soup(['script','style','nav','footer','aside','iframe','form']):
tag.decompose()
# 清除无用属性,减少模型干扰
for tag in soup.find_all(True):
tag.attrs = {k:v for k,v in tag.attrs.items() if k in ['href','src','alt','title']}
return str(soup)4.3 LLM结构化数据提取通过规范化系统提示词约束模型输出格式,采用低温度参数保证推理稳定性,实现无选择器通用提取。
client = OpenAI(api_key=OPENAI_API_KEY, base_url=OPENAI_BASE_URL)
def extract_with_llm(html_content, extraction_prompt, max_retries=2):
"""LLM通用结构化提取接口"""
max_chars = 8000
if len(html_content) > max_chars:
html_content = html_content[:max_chars] + "\n...(截断)"
system_prompt = """你是网页提取专家,严格按要求输出JSON;缺省值填null,禁止编造数据。"""
user_prompt = f"{extraction_prompt}\nHTML内容:{html_content}"
for _ in range(max_retries):
try:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role":"system","content":system_prompt},{"role":"user","content":user_prompt}],
temperature=0.1,
response_format={"type":"json_object"}
)
return json.loads(response.choices[0].message.content)
except Exception:
time.sleep(2)
continue
return None4.4 多场景业务适配封装电商商品、新闻资讯两类通用采集函数,适配结构化业务数据提取。
client = OpenAI(api_key=OPENAI_API_KEY, base_url=OPENAI_BASE_URL)
def extract_with_llm(html_content, extraction_prompt, max_retries=2):
"""LLM通用结构化提取接口"""
max_chars = 8000
if len(html_content) > max_chars:
html_content = html_content[:max_chars] + "\n...(截断)"
system_prompt = """你是网页提取专家,严格按要求输出JSON;缺省值填null,禁止编造数据。"""
user_prompt = f"{extraction_prompt}\nHTML内容:{html_content}"
for _ in range(max_retries):
try:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role":"system","content":system_prompt},{"role":"user","content":user_prompt}],
temperature=0.1,
response_format={"type":"json_object"}
)
return json.loads(response.choices[0].message.content)
except Exception:
time.sleep(2)
continue
return None4.5 语义级数据清洗区别于规则清洗,LLM可完成量词换算、语义空值统一、格式标准化等复杂处理。
def clean_data_with_llm(raw_data, cleaning_rules):
"""语义化数据标准化清洗"""
prompt = f"原始数据:{json.dumps(raw_data,ensure_ascii=False)}\n清洗规则:{cleaning_rules}"
return extract_with_llm("数据清洗", prompt)
# 通用清洗规则
cleaning_rules = """1.金额仅保留纯数字;2.时间统一为YYYY-MM-DD HH:MM:SS;3.中文量词万转为阿拉伯数字;4.无效文本统一置为null"""4.6 批量采集与持久化
def batch_crawl(urls, extract_fn, output_file="output.json"):
"""批量采集、容错存储"""
results = []
for idx, url in enumerate(urls):
print(f"[{idx+1}/{len(urls)}] 采集:{url}")
data = extract_fn(url)
if data:results.append(data)
time.sleep(random.uniform(1,3))
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=2)
return results
def main():
product_urls = ["https://example.com/product/1","https://example.com/product/2","https://example.com/product/3"]
results = batch_crawl(product_urls, extract_product_info, "products.json")
if results:
for item in results:
clean_data_with_llm(item, cleaning_rules)
if __name__ == '__main__':
main()五、代理IP反爬策略大模型爬虫延迟较高,但仍存在IP指纹封禁风险。本文采用动态转发隧道代理,单次请求轮换IP,适配requests无状态请求。5.1 代理模式选型动态转发:单次请求更换IP,适用于短链接无状态采集。固定转发:1~3分钟IP固化,适用于浏览器自动化渲染场景。5.2 链路优化与异常处理HTTPS长连接会抑制IP切换,强制关闭长连接保障代理生效:req_headers['Connection'] = 'Close'。常见异常处理:403校验请求头、407核对代理密钥、429降低采集频率。六、Prompt工程优化方案约束输出格式:强制JSON结构化返回,杜绝自然语言冗余输出。固化处理规则:在提示词内定义单位转换、空值判定逻辑,减少后置处理。控制Token开销:HTML预清洗+字符截断,降低推理成本与延迟。七、技术局限性与优化方案7.1 现存局限
局限性 | 成因 | 优化策略 |
|---|---|---|
推理延迟高 | LLM算力推理耗时 | 列表页规则采集,详情页LLM解析 |
调用成本 | 模型API计费 | 选用轻量模型,压缩输入Token |
模型幻觉 | 大模型随机生成特性 | 规则二次校验,多轮推理核验 |
7.2 混合采集架构为平衡性能与成本,采用分层采集策略:列表页依托传统爬虫高速抓取;异构详情页采用LLM语义提取;后置清洗环节统一使用大模型完成语义标准化,形成高效、低维护、强适配的复合型爬虫方案。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。