——当抓取遇上 AI,结构规则不再是唯一的出路
一、传统抓取为什么越来越累?
如果你做过一点网页抓取,你大概经历过这种场面:
好不容易把一个站点的结构理清楚,整理了好几行 XPath 或 CSS Selector,终于把标题、评分、评论都抽出来了。
但没高兴几天,网页改版了。
class 名字换了。
div 的层级挪了。
甚至有些字段直接被塞进奇怪的标签里。
于是你的脚本扑通一声倒地,又得重新“考古” HTML。
这个循环会让人怀疑人生 ——
不是在抓数据,而是在和网页结构谈恋爱,而且是极其不稳定的那种。
也就是所谓的,结构驱动的抓取模式,总是有点“脆”。
二、换个视角:如果不是匹配结构,而是让 AI 直接“读”网页呢?
现在的大模型(GPT、Claude、Llama 那些)在处理文本上的能力,比我们想象得更强。
给它一页 HTML,它不仅能读,还能“理解”:
- 哪段是电影标题?
- 哪些数字像评分?
- 评论区域是什么结构?
- 标签是分类还是描述内容?
它并不是依靠 class 名称,而是靠语义、靠“逻辑感”,甚至靠页面布局的“暗示”。
传统抓取的是标签。
AI 抓的是含义。
这是完全不同的思路。
就好像以前你让一个程序员分析页面结构;现在你把页面扔给一个“读网页经验丰富的人”,让他直接告诉你数据在哪里。
三、跨界混搭的真正爽点:让抓取负责抓页面,让 AI 负责读页面
说实话,这种分工很自然:
- 抓取模块:负责把 Douban 页面下载下来
- AI 模块:负责理解结构、抽取字段
- 代理:负责不被网站骂出局
- 开发者:只负责问一句,“帮我把电影信息抽出来吧?”
如果说传统抓取是“精确制导”,
那 AI 驱动抓取更像是“语义扫射”。
下面我直接给你看一段可运行的代码,里面包含:
- 请求 Douban 页面
- 走代理(亿牛云示例)
- 把 HTML 丢给 AI 解析
- 返回结构化 JSON
依然是完整中文注释。
代码示例
import requests
from bs4 import BeautifulSoup
import json
from openai import OpenAI
# ========== 1. 配置你的大模型 ==========
# 你可以换成任何兼容 OpenAI 的模型
client = OpenAI(api_key="你的API密钥")
# ========== 2. 配置代理(亿牛云的示例 www.16yun.cn) =======
proxy_host = "proxy.16yun.com"
proxy_port = "12345"
proxy_user = "your_username"
proxy_pass = "your_password"
# 拼接成 requests 认识的代理字符串
proxies = {
"http": f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}",
"https": f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}",
}
# ========== 3. 抓取 Douban 页面的 HTML ==========
def get_page(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/123.0 Safari/537.36"
}
resp = requests.get(url, headers=headers, proxies=proxies, timeout=15)
resp.raise_for_status()
return resp.text
# ========== 4. 用 AI 帮我们“读懂”页面,然后抽取字段 ==========
def extract_movie_info_from_html(html):
prompt = f"""
我给你一段来自 Douban 的电影页面 HTML。
请你找出并提取以下字段:
- title:电影名称
- rating:豆瓣评分
- comment:一段评论摘要(如果有)
- tags:电影的标签(类型、风格等)
请把结果严格用 JSON 格式返回,不要多说其他话。
这是 HTML:
{html}
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}]
)
result = response.choices[0].message.content
# 尝试解析 JSON
try:
return json.loads(result)
except:
return {"raw_output": result}
# ========== 5. 主流程:抓 → 交给 AI → 输出 ==========
if __name__ == "__main__":
url = "https://movie.douban.com/subject/1292052/" # 例子:肖申克的救赎
print("开始抓网页……")
html = get_page(url)
print("AI 正在帮你分析结构……")
info = extract_movie_info_from_html(html)
print("\n=== 解析后的电影信息 ===")
print(json.dumps(info, indent=4, ensure_ascii=False))
四、这套玩法到底有什么价值?为什么值得这么做?
如果你已经写过不少抓取,你会立刻意识到这个方案的价值:
1. 网页改版不再是灾难
HTML 换个 class?
AI 不在乎。
它看的是“这像是评分的位置”,“这段文字像是标签”。
2. 跨网站也能复用同一套 Prompt
换一个电影网站、换一个新闻网站,逻辑仍然通用。
这种“通用解析能力”是传统抓取做不到的。
3. 你不需要死盯 HTML 结构
以前你要把标签层级啃到牙口发酸;
现在你只需要说:
“帮我把页面里的电影信息提取一下。”
AI 会乖乖地把字段整理好。
4. 抽出来的字段更接近“人读出来的意思”
AI 会自动填补隐性语义:
- 分数不是纯数字
- 标签不是随机文本
- 评论不是所有
<p>文本混在一起
它理解上下文。
AI 让抓取从“写选择器”升级成“写任务”
以前的抓取逻辑是:
给我标签,我告诉你位置。
现在变成:
给我网页,我告诉你内容。
这就是抓取从“结构解析工具”进化为“语义理解系统”的关键一步。