「AI Agent 全栈开发 50 讲」——从本地模型部署到多智能体系统,一年省 87 万 第 13 课 | 基础爬虫:requests + BeautifulSoup 爬取 IT之家
第 13 课 | 基础爬虫:requests + BeautifulSoup 爬取 IT之家
竞品监控 Agent 的第一道工序——数据采集。这节课用 requests + BeautifulSoup 搭建第一个爬虫,自动抓取 IT 之家科技新闻,效率提升 10 倍。
一、业务价值:为什么需要爬虫
1.1 一个真实的场景
假设你是某科技公司的市场分析师,每天的工作是:
- 打开 IT 之家、36氪、虎嗅等 5-8 个科技媒体
- 浏览首页,寻找和公司产品相关的新闻
- 复制标题、摘要、发布时间到 Excel
- 分类整理,发给团队
这个过程每天至少花 2-3 小时,而且容易遗漏。如果覆盖 10 个数据源,一个人全天都做不完。
1.2 自动化后的效率对比
| 指标 | 人工方式 | 爬虫自动化 | 提升 |
|---|---|---|---|
| 单站采集时间 | 20-30 分钟 | 10-30 秒 | 100x |
| 10 站采集时间 | 3-5 小时 | 2-5 分钟 | 60x |
| 遗漏率 | 15-30% | 0%(全量) | - |
| 数据格式 | 手动整理,格式不一 | 结构化存储,统一格式 | - |
| 可扩展性 | 加一个站多 30 分钟 | 加一个站多 10 行代码 | - |
核心价值:把人从重复劳动中解放出来,把时间花在分析和决策上。
1.3 爬虫在 Agent 系统中的位置
爬虫是整个 Agent 系统的数据入口。没有高质量的数据,后面的嵌入、检索、分析都是空中楼阁。
二、爬虫基础原理
2.1 HTTP 请求-响应模型
爬虫的本质是模拟浏览器发送 HTTP 请求,解析服务器返回的 HTML。
2.2 HTML 结构速览
HTML 是树形结构,每个 <div>、<a>、<span> 都是一个节点:
<div class="news-list">
<div class="news-item">
<a class="title" href="/article/123">新闻标题</a>
<span class="summary">新闻摘要...</span>
<span class="time">2026-08-15</span>
</div>
</div>
爬虫的工作就是:找到目标节点 → 提取文本或属性。
2.3 三个核心工具
| 工具 | 作用 | 类比 |
|---|---|---|
| requests | 发送 HTTP 请求,获取网页 HTML | 浏览器地址栏输入 URL |
| BeautifulSoup | 解析 HTML,提取指定内容 | 用 CSS 选择器定位元素 |
| SQLite | 轻量数据库,存储结构化数据 | Excel 表格,但支持 SQL 查询 |
三、环境准备
3.1 安装依赖
uv pip install requests beautifulsoup4 lxml
requests:HTTP 请求库beautifulsoup4:HTML 解析库lxml:高性能解析器(BeautifulSoup 的底层引擎)
3.2 目标网站分析
我们选择 IT 之家(ithome.com)作为目标,原因:
- 科技新闻聚合,内容质量高,适合竞品监控
- HTML 结构规整,适合新手练习
- 反爬策略相对宽松(相比知乎、豆瓣)
在开始写代码之前,先在浏览器中打开 IT 之家,按 F12 打开开发者工具,观察新闻列表的 HTML 结构:
- 新闻列表容器:
class="new-list" - 每条新闻:
class="new"的li元素 - 标题:
class="new"下的h2 > a标签 - 摘要:
class="new"下的div.c或有描述文字的元素
四、实战:爬取 IT 之家新闻
4.1 第一步:发送请求
import requests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
url = "https://www.ithome.com/"
response = requests.get(url, headers=headers, timeout=10)
response.encoding = "utf-8"
print(f"状态码: {response.status_code}") # 200 表示成功
关键点:
User-Agent伪装成浏览器,否则服务器可能拒绝请求timeout=10设置超时,防止无限等待encoding="utf-8"指定编码,防止中文乱码
4.2 第二步:解析 HTML
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, "lxml")
news_items = soup.select(".new-list .new") # CSS 选择器
print(f"找到 {len(news_items)} 条新闻")
select() 使用 CSS 选择器语法,比正则表达式更直观、更可靠。
4.3 第三步:提取数据
for item in news_items[:10]: # 只取前 10 条
title_elem = item.select_one("h2 a")
summary_elem = item.select_one(".c")
time_elem = item.select_one("time")
title = title_elem.text.strip() if title_elem else ""
summary = summary_elem.text.strip() if summary_elem else ""
url = title_elem.get("href") if title_elem else ""
pub_time = time_elem.get("datetime", "") if time_elem else ""
print(f"标题: {title}")
print(f"摘要: {summary[:50]}...")
print(f"时间: {pub_time}")
print("---")
4.4 第四步:存储到 SQLite
import sqlite3
conn = sqlite3.connect("news.db")
conn.execute("""
CREATE TABLE IF NOT EXISTS news (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
summary TEXT,
url TEXT UNIQUE,
source TEXT,
pub_time TEXT,
crawled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
for item in news_items[:10]:
# ... 提取数据 ...
conn.execute(
"INSERT OR IGNORE INTO news (title, summary, url, source, pub_time) VALUES (?, ?, ?, ?, ?)",
(title, summary, url, "IT之家", pub_time)
)
conn.commit()
conn.close()
INSERT OR IGNORE 确保 url 唯一,不会重复插入同一条新闻。
五、职业道德:做有素质的爬虫
5.1 遵守 robots.txt
# 检查 robots.txt
# https://www.ithome.com/robots.txt
# 如果 Disallow 包含你要爬的路径,就不要爬
5.2 请求频率控制
import time
import random
# 每次请求之间随机延迟 1-3 秒
delay = random.uniform(1, 3)
time.sleep(delay)
为什么需要延迟?
- 高频请求会被服务器封 IP
- 给服务器造成负担,影响正常用户访问
- 做个有素质的爬虫开发者
5.3 请求头轮换
import random
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Edge/120.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Safari/17.0",
]
headers = {
"User-Agent": random.choice(USER_AGENTS),
"Accept": "text/html,application/xhtml+xml",
"Accept-Language": "zh-CN,zh;q=0.9",
}
六、完整代码运行
code/ithome_crawler.py 是完整的爬虫脚本,包含以上所有功能。
cd code/lesson-13-web-crawler
uv run ithome_crawler.py
运行后生成 data/ithome_news.db,包含爬取的新闻数据:
# 查看数据
sqlite3 data/ithome_news.db "SELECT title, pub_time FROM news LIMIT 5"
运行结果示例
[2026-08-15 14:30:01] 开始爬取 IT之家...
[2026-08-15 14:30:02] 状态码: 200
[2026-08-15 14:30:03] 找到 35 条新闻
[2026-08-15 14:30:03] 已保存: 苹果发布iOS 19开发者预览版
[2026-08-15 14:30:03] 已保存: 华为Mate 80系列曝光
[2026-08-15 14:30:03] 已保存: 特斯拉Optimus机器人量产计划
...
[2026-08-15 14:30:03] 完成!共爬取 35 条新闻,新增 12 条,跳过 23 条(重复)
七、常见问题排查
7.1 状态码不是 200
| 状态码 | 含义 | 解决方案 |
|---|---|---|
| 403 | 禁止访问 | 加强 User-Agent 伪装,降低请求频率 |
| 404 | 页面不存在 | 检查 URL 是否正确 |
| 429 | 请求过多 | 增加延迟时间,等待恢复 |
| 500 | 服务器错误 | 稍后重试 |
7.2 解析不到数据
常见原因:
- HTML 结构变了:网站改版,CSS 选择器失效 → 重新分析页面结构
- 动态加载:内容由 JavaScript 渲染 → 需要 Selenium/Playwright(第 14 课)
- 反爬机制:服务器返回了假数据或验证码 → 需要更高级的伪装策略
7.3 中文乱码
response.encoding = response.apparent_encoding # 自动检测编码
# 或手动指定
response.encoding = "utf-8"
八、总结
这节课我们完成了 Agent 系统的数据入口——爬虫模块:
- 业务价值:自动化采集替代人工浏览,效率提升 60-100 倍
- 核心技术:requests 发送请求 → BeautifulSoup 解析 HTML → SQLite 存储
- 职业道德:遵守 robots.txt、控制请求频率、伪装请求头
下一课,我们将进阶到更复杂的爬虫场景:分析 API 接口直接获取 JSON 数据,以及用 Selenium 处理动态页面。
本课代码:code/lesson-13-web-crawler/ithome_crawler.py
本课数据:code/lesson-13-web-crawler/data/ithome_news.db(运行后生成)
更多推荐
所有评论(0)