Skip to content

Repository files navigation

StructAIWeb 爬虫

一个面向 AI SaaS 应用基础信息收集 的 Windows 端通用爬虫,带 Tkinter 桌面应用 + CLI 两种入口

  • 底层:Python + Playwright,通过 CDP(Chrome DevTools Protocol)接管你自己启动的 Chrome,天然复用浏览器里已有的登录态、Cookie、扩展。
  • 探索方式:通用启发式,不针对任何特定站点。从起始 URL 出发,按"价格 > 功能 > 关于 > 文档"等优先级访问站内页面,并尝试点击主 CTA 进入产品功能区(永远不点付费/订阅类按钮)。
  • 登录拦截:检测到登录墙会自动暂停。GUI 模式下会弹出醒目的提示横幅,点"我已完成登录"按钮即可继续;CLI 模式下按回车继续。
  • 结果整合:可选接入大模型(OpenAI / 通义千问 / DeepSeek / 任意 OpenAI 兼容接口),由 LLM 输出结构化字段并打主观评分。没有 LLM 时退回纯启发式抽取,字段会随爬取实时刷新

1. 安装

最简方式:双击 install.bat,它会自动:

  • 在项目目录创建 .venv 虚拟环境(需要系统装有 Python 3.8+)
  • 安装 requirements.txt 里的全部依赖
  • 安装 Playwright 自带的 chromium(备用)

或手动:

cd e:\Source\StructAIWeb_cursor
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python -m playwright install chromium

不需要重新装 Chrome——爬虫接管的是你系统里已经装好的 Google Chrome 或 Edge。

run_gui.batpython -m scraper.gui 都会自动搜索可用的 Python:先 .venv,再 PATH 上的 python,最后扫 Anaconda 的 envs。所以如果你已经在某个 conda env 里装过依赖,可以直接双击 run_gui.bat,不用再创建 .venv


2. 运行爬虫

2.1 桌面 GUI(推荐)

直接双击 run_gui.bat,或:

python -m scraper.gui

GUI 操作流程(主流程已合并为一个按钮):

  1. 顶部填入 目标 URLCDP endpoint(默认 http://127.0.0.1:9222)、最多页数
  2. 可选填 LLM Provider(none / dashscope / openai / deepseek)和 API Key
  3. 「尝试使用主功能(评估效果与易用性,仅消耗一次积分)」 默认已勾选,可在"试用输入"修改提示词;若只看公开文案、不消耗任何积分,取消勾选即可
  4. 「🚀 一键结构化分析」 —— 这一步会自动完成
    • 找不到调试浏览器就自动启动一个(不再弹"是否启动"的询问对话框)
    • 启动爬取流程,左侧 执行日志 实时显示访问的每个页面、CTA 点击、登录拦截、试用过程等
    • 右侧 已抓字段表格 随爬取实时刷新(双击任一行弹窗查看完整值)
    • 跑完后自动把结果落盘到 output/<host>_<时间戳>.json,状态栏直接显示文件路径
  5. 如果触发登录拦截,底部会弹出醒目横幅,回到那个浏览器窗口登录完,再点 GUI 上"我已完成登录" 即可继续
  6. 想另存到其它路径?点 「另存为...」 弹文件对话框选位置(这是辅助按钮,平时不需要)

浏览器不用提前自己起。如果偏好手动控制,双击老的 start_chrome.bat 提前拉一个调试浏览器也行——「一键结构化分析」检测到端口已通就跳过启动这一步。

想专门为某站点提前训练高准确率视觉指纹?点 「训练视觉指纹(高精度)」(详见 2.2.1)。

要批量处理一堆站点?点 「批量操作...」(详见 2.1.1)。

2.1.1 批量操作(一次跑一堆 URL)

GUI 顶部按钮栏的 「批量操作...」 用于"对一份 URL 清单跑同一种任务",支持两种模式:

  • 🚀 一键结构化分析:对每个 URL 走完整爬取流程,结果自动写到 output/<host>_<ts>.json
  • 🎯 视觉指纹训练(高精度):对每个 URL 跑多采样投票训练,结果写到 ~/.structaiweb/vision_cache.json

清单文件默认是项目根目录下的 url_list.txt,格式:

# 注释行以 # 开头,会被忽略;空行也忽略
# 每行两个字段:<flag> <url>
# flag = 0  → 本次会处理它;flag = 1  → 本次跳过(占位,用于暂时排除某些站点)
# 分隔符可用空格 / 制表符 / 逗号 / 竖线
0  https://codewisp.ai/create
0  https://laughchat.cn/home
1  https://www.example.com/skip-this-one

执行逻辑:

  1. 只处理首字段为 0 的行(首字段为 1 或其它值的行整行跳过
  2. 串行处理:当前一个站点跑完才会开始下一个(不并发,避免对同站点频繁请求触发风控)
  3. 每开始一个 URL 之前,先做一次登录检测——如果命中登录墙就停下来弹横幅,等你在浏览器里登录完点「我已完成登录」再继续;想直接放弃这条 URL 可以点「跳过登录」(它会被记成 reason=login_required,跑下一条)。视觉指纹训练尤其依赖这一步——没登录的训练会把指纹训歪
  4. 本工具不会修改 url_list.txt。它是你的输入清单,工具只读不写
  5. 批量结束后写一份独立的运行报告到 output/batch_report_<时间戳>.json,含每个 URL 的成功/失败、保存路径、错误原因、耗时等。结果对话框也会显示这份报告的路径

报告 JSON 结构示意:

{
  "task": "analyze",
  "url_list_file": ".../url_list.txt",
  "started_at": "2026-05-25T22:30:21",
  "finished_at": "2026-05-25T22:30:58",
  "elapsed_seconds": 36.92,
  "summary": {"total": 1, "ok": 1, "failed": 0},
  "items": [
    {
      "index": 1,
      "url": "https://codewisp.ai/create",
      "ok": true,
      "saved_path": ".../output/codewisp.ai_20260525_223058.json",
      "source_line": 2,
      "elapsed_seconds": 36.92
    }
  ]
}

想"跳过某些已经处理过的站点"?直接手动把对应行的首字段从 0 改成 1 即可,工具本身不再帮你改这个文件。

2.2 视觉模型识别"该点哪个按钮"(可选,强烈推荐复杂前端)

部分 SaaS 的"开始生成"按钮纯靠文本/class 匹配选不准(比如 laughchat 是"两段提交":先点 提交,再点弹出面板里的"开始异步全流程生成")。此时启用视觉模型识别

  • GUI:勾选「用视觉模型识别提交按钮」,输入"视觉模型"名(默认 qwen-vl-max-latest,跑在阿里百炼)即可;base_url / api_key 自动复用上面的 LLM 配置(DashScope、OpenAI、智谱等 OpenAI 兼容多模态服务都支持)
  • CLI:加 --vision-locator [--vision-model qwen-vl-max-latest]

工作机制:

  1. 试用前先给页面上所有可点击元素叠加红色编号、所有输入框叠加蓝色编号
  2. 把整页截图 + 元素清单一起发给多模态模型,让它直接回答:"应该输入到 I1,再依次点 12、25 号按钮"
  3. 把它返回的编号转成稳定指纹(tag + text + class 关键 token),存到 ~/.structaiweb/vision_cache.json,按"域名 + 路径首段"作 key
  4. 同一站点下次直接命中缓存,跳过模型调用;缓存指纹在新 DOM 上失效时会自动清除并重新识别
  5. 安全护栏:如果模型把"购买 / 充值 / 订阅"等付费按钮当成提交按钮,整个计划会被本地策略拒绝,回退到 score 启发式(不会误扣费)

启用视觉识别后,整个试用按钮选择路径变成"缓存 → 视觉模型 → score 启发式"三级回退,第一级和第二级失败都会自动 fallback。

支持的视觉模型示例(按推荐顺序排列):

Provider 视觉模型名 备注
阿里百炼 (DashScope OpenAI 兼容模式) qwen-vl-max-latest ⭐默认, qwen-vl-max, qwen-vl-plus-latest, qwen2.5-vl-72b-instruct 中文场景识别率最高,账号最容易拿
OpenAI gpt-4o, gpt-4o-mini, gpt-4-turbo 需要 OpenAI 账号或镜像服务
智谱 glm-4v, glm-4v-plus 国内备选
月之暗面 moonshot-v1-128k-vision-preview

用百炼做视觉的最简配置:LLM Provider 选 dashscope、API Key 填百炼 sk-、勾选「用视觉模型识别提交按钮」、保持视觉模型名为默认 qwen-vl-max-latest。文本和视觉同走百炼一个 Key 搞定。

2.2.1 高精度训练视觉指纹(一次性、准确率优先)

GUI 上有个 「训练视觉指纹(高精度)」 按钮,专门解决"我希望对某个站点的关键页面(比如 https://codewisp.ai/create)一次性把指纹训准,以后每次爬取都直接命中缓存、不再调视觉模型"的需求。

跟普通流程的区别:

维度 普通 --vision-locator 高精度训练
入口 自动在试用流程中懒触发,首次失败才调模型 GUI 上手动点按钮显式触发
采样次数 1 次(截图 → 调一次模型) N 次(默认 3 次:分别滚动到首屏 / 中部 / 底部各采一次)
决策方式 单次结果直接保存 多数投票:按"按钮 dom_idx 序列"作 key,赢家才入库
识别范围 只识别 submit_chain + input_box 还顺便识别 11 类关键元素(详见下表),按角色独立投票
缓存标记 trained=false trained=true, samples=N, confidence=N/M
Token 消耗 省 token 优先 准确率优先,可以多花 token
适用场景 一般站点 重要站点、UI 复杂的站点、要批量重复爬取的站点

训练时一次性收集的"关键元素角色"(写入 vision_cache.jsonkey_elements 字段):

角色 含义 典型识别结果
login 登录入口 登录 / Log in / Sign in
signup 注册入口 注册 / Sign up / Register
pricing 定价 / 收费 / 积分中心入口 Pricing / Plans / 充值 / 积分中心 / Wallet / About credits
faq FAQ / 帮助 / 常见问题 FAQ / Help / 常见问题
docs 文档 / API 参考 Documentation / API / Block Editor
profile 个人中心 / 头像 Profile / My account / 头像菜单
logout 退出登录 Sign out / 退出
settings 设置 / 偏好 Settings / 偏好
history 历史记录 / 我的作品 My works / History / My games
home 主页 / Logo Home / 站点 Logo
contact 联系 / 反馈 / 支持 Contact / Feedback / Support

每个角色独立投票:在 N 次采样中"多数"识别为同一 dom_idx 的角色才被采纳。模型在某次采样里没识别到的角色直接跳过(不会硬塞)。训练完后可以通过 GUI 弹出的结果对话框看到每个角色的 winner_dom_idx / votes / confidence / from_sample_index

pricing 角色允许包含"定价 / Pricing / 充值"字样的链接(视为指向定价页面的入口);其它所有角色严格过滤掉付费按钮(避免误识别"立即支付"这种)。

操作流程:

  1. GUI 上「目标 URL」填主功能页(推荐直接填 https://codewisp.ai/create 这种,不要填入口 https://codewisp.ai/);如果你只能填入口,请在训练对话框里勾选「训练前先尝试点击主 CTA」让程序自己跳进去
  2. 配好 LLM Provider + API Key(训练会复用同一个 Key 调多模态模型)
  3. 点击 「训练视觉指纹(高精度)」
  4. 在弹出的对话框里:
    • 「采样次数」默认 3(每次都会调一次多模态 LLM),可以调到 1~6
    • 「试用文本」会作为给模型的提示语("该用户想干什么"),帮助它挑选语义最匹配的按钮
  5. 点「开始训练」后,日志窗口会实时显示每次采样的结果(按钮链 dom_idx、模型给出的理由);训练结束弹出完整结果窗口
  6. 之后回到主界面正常爬取,视觉路径会直接命中 ~/.structaiweb/vision_cache.json 里的训练成果——日志里会出现 视觉缓存命中: 按钮链 N 步,且不会再出现 调用视觉模型识别提交按钮

训练只预热缓存,不会抓取字段、不会调 LLM 整合、不会跑试用——它是个独立的"准备"步骤。

2.3 命令行 CLI(适合脚本 / CI)

先双击 start_chrome.bat 启动调试浏览器后:

# 最简单:用内置默认配置 + 启发式抽取(不调用 LLM)
python -m scraper.main https://laughchat.cn/home

# 限制最多访问 8 个页面
python -m scraper.main https://laughchat.cn/home --max-pages 8

# 启用通义千问做结构化整合 + 评分(需要 DashScope API Key)
python -m scraper.main https://laughchat.cn/home `
    --llm-provider dashscope `
    --llm-api-key sk-xxxxxxxx

# CLI 也默认会自动试用主功能;如不想消耗积分可关掉
python -m scraper.main https://laughchat.cn/home --no-try-features

# 自定义试用提示词
python -m scraper.main https://laughchat.cn/home `
    --demo-text "请帮我写一段产品 slogan。"

# 启用视觉模型识别提交按钮(结果按站点缓存,下次免费)
# 推荐:用阿里百炼一套 Key 同时跑文本 LLM 和视觉 LLM
python -m scraper.main https://laughchat.cn/home `
    --llm-provider dashscope --llm-api-key sk-xxx `
    --vision-locator   # 不带 --vision-model 默认就是 qwen-vl-max-latest

# 如果偏好 OpenAI
python -m scraper.main https://laughchat.cn/home `
    --llm-provider openai --llm-api-key sk-xxx `
    --vision-locator --vision-model gpt-4o

结果会写到 ./output/<host>_<timestamp>.json,控制台也会打印一份。

默认开启的"试用主功能"逻辑:找最大的 textarea / contenteditable,输入设定文本, 点"生成 / 提交 / 发送"类按钮(会主动避开"购买 / 充值 / 订阅"按钮),最长等 30 秒并采用 "出现 + 稳定 4 秒"两阶段判定抓取新增输出,然后把输入和输出一起喂给 LLM 作为 effect_score 的依据。 整轮探索只触发一次试用,最多消耗一次积分;如要彻底关闭加 --no-try-features 即可。

Windows PowerShell 默认编码可能导致中文日志乱码。用 cmd 跑 + 先 chcp 65001 即可正常显示;或直接用 GUI 模式不会有这个问题。

配置文件(可选)

复制 config.example.yamlconfig.yaml,按需修改。常用项:

字段 说明
browser.cdp_endpoint Chrome 调试端口。默认 http://127.0.0.1:9222,要和 start_chrome.bat 里的 DEBUG_PORT 一致。
crawl.max_pages 单次最多探索多少个页面(默认 12)
crawl.same_site_only 是否只在同根域名下探索(默认 true)
llm.provider none / openai / dashscope / deepseek / custom
llm.api_key LLM API Key。也可以用 --llm-api-key 或环境变量 LLM_API_KEY 传入。

3. 输出字段说明

output/*.jsondata 子对象包含:

字段 说明
name 工具的展示名称(保留品牌大小写)
logo_url 工具 logo 图片地址
tagline 一句话简介 / Slogan
description 工具详细介绍(纯文本)
developer 开发商 / 组织名称
is_free 是否存在免费可用部分(true/false/null)。积分制 / 必须充值 / Free trial 都算 false
pricing_info 定价说明文字。若识别到"剩余 N 积分"/"充值"/"会员"等线索,会自动追加"积分制/付费墙线索"段
sub_capbility_list 子功能列表 [{"capbility": "...", "descript": "..."}]
usability_score / usability_describe 易用性评分 1~10 及理由
effect_score / effect_describe 效果评分 1~10 及理由(启用 --try-features 时,会基于真实试用输出打分)
price_score / price_describe 性价比评分 1~10 及理由

顶层另外几个字段:

字段 说明
visited_pages 本次实际抓到快照的 URL 列表(含 anchor section)
login_encounters 命中登录拦截的全部记录(页面 URL + 触发原因)
demo_runs 启用 --try-features 时记录的试用结果 [{input, output, url, submit_button}, ...]

评分字段只有在启用了 LLM 时才会被填充;否则保持为 null 并在 describe 中说明原因。


4. 用户配置自动保存

GUI 会把上次填的 目标 URL / CDP / 最多页数 / LLM Provider / API Key / 试用开关 / 试用提示词 / 视觉模型开关 / 视觉模型名 保存到:

%USERPROFILE%\.structaiweb\settings.json

视觉模型识别出的"该点哪些按钮"会按 host + path 缓存到另一个独立文件:

%USERPROFILE%\.structaiweb\vision_cache.json

想强制让某个站点重新识别?直接删掉 vision_cache.json(或编辑掉对应条目)即可;下次访问会重新调一次视觉模型并把新指纹存回。

下次启动 GUI 直接回填,不用每次重新填一遍 API Key。

特点:

  • 按 Provider 分桶保存 API Key:切到 OpenAI 输入了一个 key 再切回 DashScope,DashScope 的旧 key 还在。Provider 下拉一变,输入框立刻显示对应的 key。
  • 何时落盘:点 「🚀 一键结构化分析」「训练视觉指纹(高精度)」 时保存一次;退出 GUI 时再保存一次;切换 Provider 时也会把当前输入框的 key 写回 Provider 的桶。
  • 文件权限:保存后会尝试 chmod 0o600(仅当前用户可读写,Windows 下尽力而为)。
  • 配置不会进 git:放在用户主目录,跟项目目录隔离。
  • 需要重置 / 想清空保存的 API Key? 在 GUI 顶部按钮区点 「重置配置...」,确认后即删除 settings.json 并回到默认值;或者直接手动删除上面那个文件。
  • CLI 默认 不读 这个文件(保持脚本可重复性);CLI 用户依旧通过 --llm-api-key / config.yaml / LLM_API_KEY 环境变量传 key。

5. 排错与日志

GUI 每次启动都会把详细日志写到 logs/gui.log(追加模式,单文件自动滚动到最大 2 MB × 5 份)。

  • 记录的内容包括:
    • 每次启动的 === START === 横幅 + 进程 PID
    • 用户每次点击「🚀 一键结构化分析」/「训练视觉指纹(高精度)」时的完整参数
    • 后台线程开始 / 结束 / 异常
    • 探索过程中每个关键节点(连接 Chrome、访问页面、点击 CTA、登录拦截、调用 LLM…)
    • 主线程 / 子线程 / asyncio / tkinter callback 的全部未处理异常(带完整 traceback)
  • 如果 GUI 突然闪退、看不到任何弹窗,打开 logs/gui.log 看最后几条就能定位卡在哪一步、是否抛了异常。
  • GUI 顶部有 「打开日志文件」 按钮,点它会用资源管理器高亮 gui.log

6. 项目结构

StructAIWeb_cursor/
├── README.md                  # 本文件
├── requirements.txt           # Python 依赖
├── config.example.yaml        # 配置文件模板
├── install.bat                # 一键创建 .venv + 安装依赖
├── run_gui.bat                # 启动 Tkinter 桌面应用(自动找有依赖的 Python)
├── start_chrome.bat           # (可选)老的手动启动调试 Chrome 脚本
├── output/                    # 爬取结果 JSON(自动创建)
├── logs/                      # GUI 运行日志(自动创建)
└── scraper/
    ├── __init__.py
    ├── main.py                # CLI 入口
    ├── gui.py                 # Tkinter 桌面应用入口
    ├── runner.py              # 核心流程封装(CLI & GUI 共用)
    ├── settings.py            # GUI 用户偏好持久化(~/.structaiweb/settings.json)
    ├── logger.py              # 统一日志 + 全局异常拦截
    ├── browser.py             # CDP 接管 Chrome / 自动启动浏览器
    ├── explorer.py            # 站内页面发现与调度 + 主 CTA 点击 + 主功能试用
    ├── extractor.py           # 单页 HTML -> 结构化快照
    ├── login_guard.py         # 登录拦截检测 / 暂停等待
    └── llm_analyzer.py        # LLM 整合 + 评分(可选)

7. 工作流程一图流

┌──────────────────────┐
│ 你: 双击 start_chrome│
│  并在 Chrome 里登录   │
└────────┬─────────────┘
         │ CDP :9222
         ▼
┌──────────────────────┐
│  Playwright 接管 Tab │
│  → 访问起始 URL       │
│  → 提取 meta/og/正文 │
│  → 发现并排序子链接  │
│  → 遇到登录墙: 暂停  │
└────────┬─────────────┘
         │
         ▼
┌──────────────────────┐
│  把所有页面快照交给  │
│  LLM 输出 JSON+评分  │
│  (没配 LLM 走启发式) │
└────────┬─────────────┘
         │
         ▼
   output/*.json

8. 常见问题

Q: 程序提示"无法连接到 Chrome 调试端口"? A: 没先双击 start_chrome.bat,或者已经有别的进程占用了 9222 端口。改 DEBUG_PORT 后记得同步改 config.yaml

Q: 我的 Chrome 安装在非常规位置,bat 找不到? A: 用记事本打开 start_chrome.bat,手动改 CHROME_EXE 一行。

Q: 想爬的 SaaS 强制登录才能用,怎么办? A: 程序检测到登录墙后会暂停,你在浏览器里登录完回到终端按回车即可继续。下次再跑同一个站时(只要 StructAIWeb_chrome_profile 没删),登录态自动复用。

Q: 爬到的字段不全? A: 这类站点没有把信息暴露在公开页面上是常见现象。脚本会原样返回 "" / null / [],符合需求里"找不到就说找不到"的要求。

About

使用AI智能体自动对网站进行测试,得到网站的客观的结构化信息,包括:功能、易用性、收费情况等,方便用户找到适合自己的应用

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages