Selenium + 自研小型 Agent:用脚本加简易agent搭建简单数据工作流

Selenium + 自研小型 Agent:用脚本加简易agent搭建简单数据工作流

这篇文章想分享的不是「又一个爬虫」,而是两件事怎么拼在一起:

Selenium(以及公开接口)负责把网页世界变成结构化数据

自研的小型 Agent Harness 负责听懂人话、选工具、把流水线跑完

文末附开源地址,可直接跑。


0. 先看结果长什么样

一句话下令之后,希望得到的是一张固定列的表,而不是一堆临时脚本碎片。

Excel / JSON 里大概是这样(示意,数据会随热榜变化):

rank title author hot_score view_count like_count comment_count sample_comments
1 【MYSQL】...表的内外连接 *** 24050 970 43 41 (抽样评论,可空)
2 【Linux网络】深入 HTTP... *** 21071 1273 61 102 ...
3 一个人也能做AI漫剧... *** 20350 16580 15 4 ...

完整字段还包括:author_idurlperiodfavor_countfetched_at

后面会讲这些数从哪来、为什么收藏经常是 0。


1. 原理:先把两层能力拆开

很多人一上来就「Agent 自己写爬虫」。短期能出活,长期很脆------模型每次临场发挥,接口一变全盘重写,还容易把 Cookie、频率控制写丢。

更稳的做法是分层:

text 复制代码
┌─────────────────────────────────────────┐
│  上层:小型 Agent(听懂 → 规划 → 调工具) │
│  配方命中 → run_script → 验收 → 汇报     │
└──────────────────┬──────────────────────┘
                   │ 调用固定脚本
┌──────────────────▼──────────────────────┐
│  下层:数据流水线(Selenium / HTTP)      │
│  拉榜 → 清洗 → 固定列 → xlsx/json/csv   │
└─────────────────────────────────────────┘

1.1 Selenium 在解决什么问题

浏览器自动化的本质很简单:

  1. 启动真实浏览器(或无头 Chrome)
  2. 打开目标页,等待页面与脚本执行
  3. 再去拿数据(DOM、或页面触发过的接口)

对现代站点,页面上的列表往往不是静态 HTML,而是前端再请求 JSON

所以实战里常见两种姿势:

姿势 做法 特点
A. 直接打 XHR urllib / requests 请求热榜接口 快、稳、无浏览器依赖
B. Selenium 兜底 先用浏览器打开榜单页「暖环境」,再走同一套接口 慢一点,偶发风控时更像真人

我们项目的默认路径是 A;--selenium 走 B。

Selenium 不是主角炫技,而是「当纯 HTTP 不够像浏览器时」的补丁。

1.1.1 Selenium 关键代码(仓库原文)

下面这段就是 scripts/csdn_hot_pipeline.py 里的 fetch_with_selenium:无头 Chrome 打开榜单页,关掉浏览器后,仍然调用同一套 fetch_hot_rank HTTP 分页拉数

python 复制代码
def fetch_with_selenium(top: int) -> list[dict[str, Any]]:
    """
    Selenium 兜底:先打开榜单页(带浏览器环境),再走同一 hot-rank 接口。
    适合接口偶发风控时;日常推荐默认 HTTP 模式。
    """
    try:
        from selenium import webdriver
        from selenium.webdriver.chrome.options import Options
    except ImportError as exc:
        raise SystemExit("缺少 selenium,请 pip install selenium") from exc

    options = Options()
    options.add_argument("--headless=new")      # 无头,不弹窗
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")
    options.add_argument("--window-size=1280,900")
    driver = webdriver.Chrome(options=options)
    try:
        driver.get("https://blog.csdn.net/rank/list")  # 暖一下页面上下文
        time.sleep(2)
    finally:
        driver.quit()

    return fetch_hot_rank(top)  # 真正取数仍走公开 XHR

真正分页拉榜的 HTTP 部分(Selenium 与默认模式共用):

python 复制代码
HOT_RANK_URL = "https://blog.csdn.net/phoenix/web/blog/hot-rank"

def fetch_hot_rank(top: int, page_size: int = 25, sleep_s: float = 0.35) -> list[dict[str, Any]]:
    items: list[dict[str, Any]] = []
    page = 0
    while len(items) < top:
        qs = urllib.parse.urlencode({"page": page, "pageSize": page_size, "type": ""})
        url = f"{HOT_RANK_URL}?{qs}"
        payload = http_get_json(url)  # 带 UA / Referer 的 GET JSON
        if int(payload.get("code") or 0) != 200:
            raise RuntimeError(f"hot-rank 失败 code={payload.get('code')}")
        batch = payload.get("data") or []
        if not batch:
            break
        items.extend(batch)
        page += 1
        if len(batch) < page_size:
            break
        time.sleep(sleep_s)  # 限速,别打爆接口
    return items[:top]

入口里如何切换两条路径:

python 复制代码
if args.selenium:
    raw = fetch_with_selenium(top)
else:
    raw = fetch_hot_rank(top)

读代码时抓住三点即可:

  1. Selenium 只负责「像浏览器一样打开榜单页」,不在这里解析 DOM 抠一百条标题。
  2. 数据仍然来自 hot-rank JSON,和默认模式同一套清洗逻辑。
  3. --sleep / time.sleep 限速是必须的;开源分享时也建议读者别去掉。

依赖:pip install selenium,本机已装 Chrome(Selenium 4 一般会自动管理驱动)。

1.2 小型 Agent 在解决什么问题

自研 harness(我们叫它 mini-agent-harness)体量不大,但闭环是完整的:

text 复制代码
用户自然语言
  → 意图 / 配方(这是不是「CSDN 热榜一条龙」?)
  → 对话态(缺不缺关键槽位?要不要追问?)
  → 任务分解(先跑脚本,再 profile 表格)
  → 工具执行(run_script / read_excel ...)
  → 验收与汇报

和「大而全 Agent 框架」相比,它刻意做小,方便研究:

  • 工具是一等公民:爬虫能力不靠模型临场写,而靠仓库里的脚本
  • 配方(Recipe):一类话术绑定推荐工具链
  • 玻璃盒:过程可追踪,适合学习「Agent 到底在干什么」

关键原则一句话:

Agent 负责编排;Selenium/脚本负责取数。

编排可以换模型,取数逻辑应该版本可控、可单测、可开源。

1.3 两层拼在一起时,最容易踩的坑

若用户说:「清洗后导出 exports/csdn_hot_top100.xlsx」,

通用对话态容易理解成:「你已经有一张表,告诉我路径,我帮你导出」。

于是 Agent 开始追问文件路径------热榜任务还没开始就卡死了

所以原理上还要多一步特判:命中「CSDN 热榜」配方时,这是生成新表 ,不是加工旧表;跳过 file 槽位澄清,直接 run_script


2. 爬虫长什么样

脚本入口:scripts/csdn_hot_pipeline.py(约 300 行,可独立运行)。

2.1 数据从哪来

公开接口(页面 Network 里也能看到同类请求):

text 复制代码
热榜:https://blog.csdn.net/phoenix/web/blog/hot-rank?page=0&pageSize=25&type=
评论:https://blog.csdn.net/phoenix/web/v1/comment/list?articleId=...

流程:

text 复制代码
分页拉热榜 Top N
  → 字段归一化(标题、作者、热度、阅读、点赞...)
  → 可选:每篇抽样 N 条评论内容
  → 写出 xlsx(默认)+ json(默认)+ 可选 csv

2.2 清洗时要注意的「脏细节」

热榜原始 JSON 字段名并不「人类友好」,例如:

  • 接口里的 favorCount,语义上更接近点赞,不是收藏
  • 收藏字段经常缺失 → 导出里 favor_count 常为 0
  • 阅读量可能是 "2.4w" 这种字符串 → 要先解析成整数
  • 评论内容可能带 HTML → 简单剥标签再截断

归一化后的一行,概念上类似:

json 复制代码
{
  "rank": 1,
  "title": "【MYSQL】MYSQL学习的一大重点:表的内外连接",
  "author": "艾莉丝努力练剑",
  "author_id": "2401_89899187",
  "url": "https://blog.csdn.net/.../article/details/163200338",
  "period": "2026-07-30-14",
  "hot_score": 24050,
  "view_count": 970,
  "like_count": 43,
  "favor_count": 0,
  "comment_count": 41,
  "sample_comments": "",
  "fetched_at": "2026-07-30 15:11:07"
}

固定列(给 Agent / Excel 对齐用):

text 复制代码
rank, title, author, author_id, url, period,
hot_score, view_count, like_count, favor_count,
comment_count, sample_comments, fetched_at

2.3 命令行长什么样

不经过 Agent,直接跑流水线:

bash 复制代码
pip install openpyxl

# 默认 HTTP,Top100,每篇抽 2 条评论
python scripts/csdn_hot_pipeline.py \
  --top 100 \
  --enrich-comments 2 \
  --out exports/csdn_hot_top100.xlsx \
  --also-csv

# 接口偶发不稳时,打开 Selenium 兜底(需本机 Chrome)
pip install selenium
python scripts/csdn_hot_pipeline.py --top 100 --selenium --out exports/csdn_hot_top100.xlsx

终端大致会看到:

text 复制代码
[csdn] fetch top=100 selenium=False
[csdn] got 100 raw items, cleaning...
  cleaned 10/100
  ...
[csdn] done rows=100
[csdn] xlsx=.../exports/csdn_hot_top100.xlsx

3. Agent 侧长什么样

对 harness 说人话即可(REPL):

text 复制代码
/forget
抓取 CSDN 今天热榜前 100,带点赞收藏评论和评论内容,清洗后导出 exports/csdn_hot_top100.xlsx

内部推荐链路:

text 复制代码
命中配方 csdn-hot-pipeline
  → run_script scripts/csdn_hot_pipeline.py
       args: --top 100 --enrich-comments 2 --out ... --also-csv
  → profile_dataset / read_excel 确认行列
  → 用自然语言汇报结果路径

也就是说:读者看到的「智能」,一大半是配方 + 固定脚本;模型负责选择与解释,而不是每次重写爬虫。


4. 开源了什么、怎么用

项目已开源(MIT):

仓库: https://gitcode.com/z996262114/agent-harness-tool

你可以重点看这些文件:

路径 内容
scripts/csdn_hot_pipeline.py Selenium / HTTP 抓取 + 清洗 + 导出
src/policy/DataRecipes.ts 配方 csdn-hot-pipeline
src/policy/DialogueState.ts 热榜任务跳过「缺文件」误澄清
src/policy/TaskDecomposer.ts 优先 run_script
docs/本地使用-CSDN热榜工作流.md 本机一步步跑通

快速体验 Agent:

bash 复制代码
git clone https://gitcode.com/z996262114/agent-harness-tool.git
cd agent-harness-tool   # 或你本地的 mini-agent-harness 目录
npm install
# 配置 DeepSeek API Key:key.txt 或环境变量
npm run repl

本地上手文档写得更细,适合照着敲命令。


5. 写给正在研究的人

  1. 先独立跑通脚本,再挂到 Agent 上------出问题先分清是爬虫层还是编排层。
  2. 把输出列定死,Agent 才好验收;列名天天变,上层永远在修提示词。
  3. Selenium 当兜底,日常优先接口;浏览器自动化贵且慢。
  4. 限速、学习用途、尊重内容版权------接口可能变更,代码不保证永久可用。

6. 结语

这篇文章想留下的画面很简单:

  • 原理:Selenium/HTTP 取数,小型 Agent 编排;两层不要揉成一团。
  • 样子:固定列的热榜表 + 可独立运行的 Python 流水线。
  • 开源:MIT 仓库已公开,欢迎直接跑、提 Issue / PR。

如果你也在做「Agent + 真实数据任务」,不妨试试:先把脏活收成脚本,再让 Agent 学会按铃。 往往比指望模型每次现场发明轮子,更接近能长期维护的工程。

相关推荐
半兽先生20 小时前
意图分类模型,使用ber分类和LLM分类有哪些优缺点?
人工智能·分类·bert
Cachel wood20 小时前
hands-on-modern-rl:动手学强化学习 贝尔曼方程
开发语言·网络·python·学习·embedding
HIT_Weston20 小时前
161、【Agent】【OpenCode】TuiThreadCmd(联合类型)
人工智能·agent·opencode
设计总监老谢20 小时前
从长鑫存储上市,看中国科技企业的品牌觉醒
python·科技
深圳市快瞳科技有限公司20 小时前
宠物生物特征识别:鼻纹、面部与多模态融合技术的突破
人工智能·算法·计算机视觉·宠物
昇腾CANN20 小时前
基于 PyPTO 与 Agent,2周完成模型 QAT 算子开发与优化
人工智能·昇腾·cann
怕浪猫21 小时前
给女朋友添加一个分身吧
人工智能·程序员·aigc
xwz小王子21 小时前
触觉机器人,正在补齐从采集到策略的整条链路
人工智能·机器学习·机器人
ITmaster073121 小时前
从前端到AI工程师:一场跨越鸿沟的真实蜕变之旅
前端·人工智能
武子康21 小时前
GitHub Code Quality GA 后,100 名开发者真的只要每月 1000 美元吗?
人工智能·agent·github copilot