写“爬虫python”示例时,最容易误导初学者的是只展示 requests.get(),却不说授权、频率和失败响应。一个能交付的小采集器,至少要把请求、解析、清洗和保存拆开,并且知道什么时候应该停下来。
下面用公开静态页面做演示,目标是提取文章标题并保存为 CSV。示例不绕过登录、不抓取个人信息,也不把站点的反爬策略当成可以规避的障碍。
先画清楚一条数据链路
采集任务不是“发一个请求”这么简单:请求得到响应后,要校验状态码和内容类型,再交给解析器,最后才写入文件。

图:请求、响应、解析、清洗和 CSV 保存是五个独立的可检查节点。
一个最小可复现实现
安装依赖:
python -m pip install requests beautifulsoup4
代码把 URL、选择器和输出路径都放在参数里,方便替换为获得授权的测试页面:
import csv
import requests
from bs4 import BeautifulSoup
def collect(url: str, selector: str = "h2") -> list[str]:
response = requests.get(
url,
headers={"User-Agent": "learning-bot/1.0"},
timeout=10,
)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
return [node.get_text(" ", strip=True) for node in soup.select(selector)]
def save_csv(rows: list[str], path: str) -> None:
with open(path, "w", newline="", encoding="utf-8-sig") as handle:
writer = csv.writer(handle)
writer.writerow(["title"])
writer.writerows([[row] for row in rows if row])
运行前先确认页面允许自动访问,再调用 collect()。当前环境没有针对具体站点运行这段代码,因此不声称固定条数或耗时;读者应把真实 URL、响应状态和输出文件作为自己的验证记录。
解析结果不等于业务数据
网页结构会变,选择器失效时最好让任务失败,而不是静默生成空 CSV。可以加三道检查:
- 响应状态不是 200 时记录状态码并停止。
- 解析结果为空时保存原始响应摘要,方便定位选择器变化。
- 写文件前去重、去除空白,并限制字段长度,避免把整段页面误当标题。

图:授权、频率、响应、字段和保存五个环节都通过后,数据才适合进入下游。
频率和边界怎么定
单页练习可以人工触发;批量任务则需要显式的间隔、最大页数和失败上限。不要把并发数写成“越大越快”,它同时会增加对方压力、触发限制和本地内存占用。
当页面依赖 JavaScript 渲染、需要登录或包含敏感数据时,requests + BeautifulSoup 就不是合适的默认方案。此时应先确认授权和数据处理范围,再选择官方 API 或经过批准的浏览器自动化方案。
适用范围
这套最小链路适合学习 HTTP、HTML 解析和文件落盘,也适合一次性整理公开资料。它不是通用采集平台:生产任务还需要 robots 与条款核验、速率限制、重试退避、日志、断点和数据质量监控。