Python实现全站链接爬取工具:助力打造AI 知识库
标签:#Python #Playwright #爬虫 #AI知识库
日期:2026-05-01
摘要:本文介绍一个自己开发的基于 Playwright 的全站站内链接爬取工具,通过递归爬取 + BeautifulSoup 解析实现自动收集网站所有内部链接,支持导出为 Markdown 格式,方便批量导入 AI 知识库进行"提问式学习"。
前言
最近在学习 NiceGUI 时,发现官方文档内容非常丰富,组件数量有一百多个。按照传统方式逐页阅读,效率很低。
有了 AI 之后,更高效的学习方式是:把官方文档变成你的私人 AI 知识库,用提问代替搜索。
具体分三步走:
- 收集:抓取技术网站的所有站内链接
- 导入:将链接批量导入 AI 知识库工具(我用的是腾讯 IMA)
- 对话:像和老师一对一交流一样,用自然语言提问学习
本文重点介绍:如何高效抓取全站链接。
一、实现原理
🎯 核心思路
用户输入URL
↓
递归爬取每个页面的内部链接
↓
BeautifulSoup 解析 HTML,提取 <a> 标签
↓
过滤:同域名、非锚点、HTTP/HTTPS
↓
去重后保存为 Markdown 文件
🔑 关键技术点
| 技术 | 作用 |
|---|---|
| Playwright | 渲染 JavaScript,获取动态加载后的完整 HTML |
| BeautifulSoup | 解析 HTML,快速定位所有链接 |
| urljoin | 将相对路径转换为绝对路径 |
| 递归爬取 | 从首页开始,自动发现并访问所有子页面 |
二、完整源码
'''
全站站内链接爬取脚本
功能:递归爬取指定网站的所有内部链接,自动过滤锚点链接
'''
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
from my_playwright import MyPlaywright
def get_internal_links(base_url: str) -> set[str]:
"""
递归爬取全站内部链接
Args:
base_url: 目标网站根 URL
Returns:
visited: 所有发现的内部链接集合
"""
visited: set[str] = set() # 已访问的 URL 集合
page = MyPlaywright(headless=True).page # 获取 Playwright Page 对象
target_netloc = urlparse(base_url).netloc # 提取目标网站的域名
def _crawl_links(url: str) -> None:
'''爬取指定 URL 的所有内部链接'''
print(f"总数:{len(visited)} [+] 正在抓取: {url}...")
visited.add(url)
try:
page.goto(url, wait_until='networkidle', timeout=30000)
page.wait_for_timeout(500) # 等待确保页面加载完成
html = page.content()
soup = BeautifulSoup(html, 'html.parser')
for a in soup.find_all('a', href=True):
href = a['href']
full_url = urljoin(url, href)
parsed = urlparse(full_url)
# 过滤非内部链接
if not parsed.netloc == target_netloc:
continue # 跳过其他域名的链接
if '#' in full_url:
continue # 跳过锚点链接
if parsed.scheme not in ('http', 'https'):
continue # 跳过非 HTTP/HTTPS 链接
if full_url in visited:
continue # 跳过已访问的链接
_crawl_links(full_url) # 递归爬取子链接
except Exception as e:
print(f"[!] 请求失败: {url} - {e}")
_crawl_links(base_url)
print(f"[✓] 已完成 {len(visited)} 条链接的爬取")
return visited
def save_to_markdown(links, output_path='internal_links.md'):
"""将链接列表保存为 Markdown 文件,每 10 条为一组"""
sorted_links = sorted(links)
chunk_size = 10
chunks = [sorted_links[i:i + chunk_size] for i in range(0, len(sorted_links), chunk_size)]
markdown_content = []
markdown_content.append("# 全站内部链接列表\n")
markdown_content.append(f"共发现 **{len(links)}** 条链接\n\n")
markdown_content.append("---\n\n")
for idx, chunk in enumerate(chunks, 1):
start_num = (idx - 1) * chunk_size + 1
markdown_content.append(f"### 第 {start_num}-{start_num + len(chunk) - 1} 条链接\n\n")
for link in chunk:
markdown_content.append(f"{link}\n")
markdown_content.append("\n")
with open(output_path, 'w', encoding='utf-8') as f:
f.writelines(markdown_content)
print(f"[✓] 已保存到: {output_path}")
if __name__ == '__main__':
base_url = 'https://nicegui.io/'
links = get_internal_links(base_url)
save_to_markdown(links)
三、源码解析
🔍 MyPlaywright 封装
这里的 MyPlaywright 是我对 Playwright 的封装,核心特点:
| 特性 | 说明 |
|---|---|
| 永久上下文 | 浏览器状态持久化,只需创建一次 |
| 自动资源释放 | 程序退出时自动关闭浏览器 |
| 跨平台 | Windows 显示浏览器,Linux 自动无头 |
| 自动下载 | 监听下载事件,自动保存文件 |
使用方式极其简单:
page = MyPlaywright(headless=True).page
page.goto("https://example.com")
🔍 链接过滤逻辑
# 1. 只爬取同域名的链接
if not parsed.netloc == target_netloc:
continue
# 2. 跳过锚点链接(如 #section)
if '#' in full_url:
continue
# 3. 只处理 HTTP/HTTPS 链接
if parsed.scheme not in ('http', 'https'):
continue
# 4. 已访问过的跳过
if full_url in visited:
continue
🔍 递归爬取流程
nicegui.io (起始页)
├── /documentation
│ ├── /documentation/button
│ │ └── (发现更多子链接...)
│ ├── /documentation/input
│ └── ...
├── /examples
│ └── ...
└── ...
四、使用效果
以 NiceGUI 官网为例,运行脚本后:
总数:0 [+] 正在抓取: https://nicegui.io/...
总数:1 [+] 正在抓取: https://nicegui.io/documentation...
总数:2 [+] 正在抓取: https://nicegui.io/documentation/button...
...
[✓] 已完成 139 条链接的爬取
[✓] 已保存到: internal_links.md
生成的 Markdown 文件示例:
# 全站内部链接列表
共发现 **139** 条链接
---
### 第 1-10 条链接
https://nicegui.io
https://nicegui.io/documentation
https://nicegui.io/documentation/button
https://nicegui.io/documentation/switch
...
每 10 条链接为一组,方便批量导入到 IMA 等 AI 知识库工具。
五、后续计划
这个工具将被整合到类似于龙虾的Agent中,作为一个自动化子任务:
AI Agent
├── 任务:学习 NiceGUI
│ ├── 子任务:爬取全站链接 → 调用 crawl_internal_links.py
│ ├── 子任务:整理分组格式
│ └── 子任务:导入 AI 知识库
└── ...
目标是实现:一句话,让 AI 自动完成整个学习准备工作。
六、总结
📌 要点回顾
- Playwright 解决了 JavaScript 动态渲染页面的抓取问题
- 递归爬取 确保覆盖全站所有页面
- BeautifulSoup 高效解析 HTML 中的链接
- Markdown 分组导出 方便批量导入 AI 知识库
- 配合 AI 知识库 实现"提问式学习",效率倍增
💡 适用场景
- 学习新技术框架的官方文档
- 构建个人技术知识库
- 批量收集某网站的所有页面
⚠️ 注意事项
- 如果使用腾讯IMA知识库的话,很多网上资源可能已经有人已经整理过了,只要点击IMA的“发现”按钮,就可以搜索并寻找自己感兴趣的知识库,订阅即可。
七、相关资源
本文为本人原创,首发于掘金。
如果你有任何问题或想法,欢迎在评论区交流!