《Python爬虫 + 飞书自动化上传》全流程详细讲解
项目目标:从豆瓣电影 Top250 抓取前 100 条热门电影数据(含名称、评分、链接、详情),
然后一键上传到 飞书多维表格(Bitable)。
🧩 项目结构
douban_host_to_feishu/
│
├── config.yaml # 飞书配置文件(App ID、Token等)
├── feishu_uploader.py # 飞书上传模块
└── douban_spider.py # 爬虫主逻辑
📄 一、飞书上传模块(feishu_uploader.py)
💡 功能说明:
负责读取配置、获取 Feishu Access Token,并将 DataFrame 批量上传。
✨ 知识点 1:读取配置文件
import yamlwith open("config.yaml", "r", encoding="utf-8") as f:CONFIG = yaml.safe_load(f)
📘 解析:
with open():上下文语法,自动关闭文件。yaml.safe_load():比load()更安全,只会解析基础类型。- 加
encoding="utf-8"避免中文乱码。
✅ 举例:
feishu:app_id: "cli_123456"app_secret: "abcdef"app_token: "bascnxxxx"table_id: "tbl12345"
解析结果就是一个 Python 字典:
CONFIG["feishu"]["app_id"] # => "cli_123456"
✨ 知识点 2:发起 POST 请求获取 Token
import requestsdef get_token():url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"data = {"app_id": APP_ID, "app_secret": APP_SECRET}res = requests.post(url, json=data)return res.json().get("tenant_access_token")
📘 解析:
requests.post():发送 POST 请求,自动转 JSON。.json():将返回的 JSON 转为 Python 字典。.get():安全取值,不会抛 KeyError。
✅ 示例输出:
{"code": 0,"tenant_access_token": "t-g104anmeJCS...","expire": 7200
}
返回值为 "t-g104anme...",即 Token。
✨ 知识点 3:遍历 Pandas DataFrame
for _, row in df.iterrows():print(row["电影名称"], row["评分"])
📘 解析:
iterrows():逐行遍历 DataFrame。_代表索引,我们不需要时用_占位。
✅ 输出举例:
肖申克的救赎 9.7
霸王别姬 9.6
✨ 知识点 4:批量上传(分批处理)
for i in range(0, len(records), 10):batch = records[i:i + 10]res = requests.post(url, headers=headers, json={"records": batch})
📘 解析:
range(start, stop, step):步长循环,这里每次上传 10 条。records[i:i + 10]:切片取 10 个元素。
✅ 代码逻辑举例:
records = [1,2,3,4,5,6,7,8,9,10,11,12]
# 第1批: [1..10]
# 第2批: [11..12]
✨ 知识点 5:条件判断与字符串格式化
if res.status_code == 200:print(f"✅ 上传成功:第 {i // 10 + 1} 批")
else:print(f"⚠️ 上传失败:HTTP {res.status_code}")
📘 解析:
f"..."是 f-string(Python3.6+),性能更高,可直接嵌变量。//是整除,%是取余。
✅ 输出举例:
✅ 上传成功:第 3 批
📄 二、豆瓣爬虫模块(douban_spider.py)
💡 功能说明:
从豆瓣电影 Top250 抓取前 100 条电影,提取字段保存为 CSV,并上传。
✨ 知识点 1:requests 请求网页
res = requests.get(url, headers=headers, timeout=10)
res.encoding = "utf-8"
📘 解析:
headers模拟浏览器,避免被反爬。timeout=10限制最长等待时间。.encoding强制使用 UTF-8,防止中文乱码。
✅ 调试技巧:
print(res.status_code) # 200 正常
print(res.text[:500]) # 打印前 500 字符
✨ 知识点 2:BeautifulSoup 解析网页
from bs4 import BeautifulSoupsoup = BeautifulSoup(res.text, "html.parser")
📘 解析:
- BeautifulSoup 是 Python 最常用的 HTML 解析库。
"html.parser"是 Python 内置解析器。
✅ 示例:
html = "<div><p>Hello</p></div>"
soup = BeautifulSoup(html, "html.parser")
print(soup.p.text) # 输出 Hello
✨ 知识点 3:CSS 选择器抓取标签
for item in soup.select("div.item"):title = item.select_one("span.title").get_text(strip=True)
📘 解析:
.select()类似 JavaScript 的document.querySelectorAll()。.select_one()返回第一个匹配。.get_text(strip=True)去除空格换行。
✅ 豆瓣实际结构示例:
<div class="item"><a href="https://movie.douban.com/subject/1292052/"><span class="title">肖申克的救赎</span></a><span class="rating_num">9.7</span>
</div>
✨ 知识点 4:循环分页 + 防爬保护
for start in range(0, 100, 25):url = f"https://movie.douban.com/top250?start={start}"time.sleep(1)
📘 解析:
- 豆瓣每页 25 条,用分页参数
start=25,50,75...。 time.sleep(1)每页暂停 1 秒防止被封。
✅ 循环结果:
start = 0, 25, 50, 75
共抓取 100 条
✨ 知识点 5:Pandas 数据保存
df = pd.DataFrame(movies)
df.to_csv("douban_top100.csv", index=False, encoding="utf-8-sig")
📘 解析:
pd.DataFrame():将列表字典转为表格。index=False:不保存行号。encoding="utf-8-sig":兼容 Excel 中文显示。
✅ 保存结果:
| 电影名称 | 评分 | 链接 | 详情 |
|---|---|---|---|
| 肖申克的救赎 | 9.7 | https://… | 美国剧情片 |
✨ 知识点 6:主入口控制
if __name__ == "__main__":df = get_douban_top100()token = get_token()upload_to_feishu(df, token)
📘 解析:
__name__是 Python 内置变量。- 当文件直接运行时,
__name__ == "__main__"为真。 - 当被其他文件 import 时,则不会执行这段。
✅ 优点:
方便模块复用,比如:
from douban_spider import get_douban_top100
不会执行上传逻辑,只爬取数据。
🧱 项目核心 Python 技能总表
| 分类 | 技能点 | 说明 | 代码位置 |
|---|---|---|---|
| 文件读写 | open() with | 自动关闭文件 | feishu_uploader |
| 网络请求 | requests.get / post | 爬取网页、调用 API | 两个文件都有 |
| 数据结构 | list / dict 嵌套 | 存储电影信息 | douban_spider |
| 数据解析 | BeautifulSoup | 提取 HTML 标签 | douban_spider |
| 循环控制 | for range(start, stop, step) | 分页处理 | douban_spider |
| 异常预防 | if not token: | 保证运行稳定 | feishu_uploader |
| 模块导入 | from feishu_uploader import ... | 结构化项目 | douban_spider |
| 函数封装 | def upload_to_feishu(df, token): | 高复用性设计 | feishu_uploader |
| Pandas 操作 | DataFrame + to_csv | 数据清洗与存储 | douban_spider |
| 条件判断 | if "error" not in res.text | 过滤 API 错误 | feishu_uploader |
💎 小结:项目背后的“编程思想”
| 编程思想 | 表现方式 |
|---|---|
| 模块化设计 | 爬虫逻辑与上传逻辑分离,易维护 |
| 数据驱动 | 一切逻辑都围绕 DataFrame 操作 |
| 防御式编程 | 判断错误、限速、类型转换 |
| 可扩展性 | 可替换数据源、可接企业微信、Notion 等 |
| API 优先 | 上传部分严格遵循 Feishu API 文档 |
🚀 实际运行结果
🎬 正在爬取豆瓣 Top100...
📄 已抓取 25 条...
📄 已抓取 50 条...
📄 已抓取 75 条...
📄 已抓取 100 条...
✅ 共抓取到 100 条电影数据
✅ 已保存到 douban_top100.csv
🔐 正在连接飞书...
✅ 上传成功:第 1 批
✅ 上传成功:第 2 批
✅ 上传成功:第 3 批
✅ 上传成功:第 4 批
✅ 上传成功:第 5 批
✅ 上传成功:第 6 批
✅ 上传成功:第 7 批
✅ 上传成功:第 8 批
✅ 上传成功:第 9 批
✅ 上传成功:第 10 批
🚀 全部上传完毕!
