news 2026/8/7 7:55:53

Python爬虫实战:只用 100 行代码把豆瓣 Top 250 电影装进硬盘!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python爬虫实战:只用 100 行代码把豆瓣 Top 250 电影装进硬盘!

㊗️本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~
㊙️本期爬虫难度指数:⭐ (入门级)
🉐福利:一次订阅后,专栏内的所有文章可永久免费看,持续更新中,保底1000+(篇)硬核实战内容。

全文目录:

      • 🌟 开篇语
      • 0️⃣ 前言(Preface)
      • 1️⃣ 摘要(Abstract)
      • 2️⃣ 背景与需求(Why)
      • 3️⃣ 合规与注意事项(必写) ⚖️
      • 4️⃣ 技术选型与整体流程(What/How)
      • 5️⃣ 环境准备与依赖安装(可复现) 🛠️
      • 6️⃣ 核心实现:请求层(Fetcher) 📡
      • 7️⃣ 核心实现:解析层(Parser) 🔍
      • 8️⃣ 数据存储与导出(Storage) 💾
      • 9️⃣ 运行方式与结果展示(必写) 🚀
      • 🔟 常见问题与排错(老司机经验) 🔧
      • 1️⃣1️⃣ 进阶优化(可选但加分) ⚡
      • 1️⃣2️⃣ 总结与延伸阅读 📝
      • 🌟 文末
        • ✅ 专栏持续更新中|建议收藏 + 订阅
        • ✅ 互动征集
        • ✅ 免责声明

🌟 开篇语

哈喽,各位小伙伴们你们好呀~我是【喵手】。
运营社区: C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO
欢迎大家常来逛逛,一起学习,一起进步~🌟

我长期专注Python 爬虫工程化实战,主理专栏 《Python爬虫实战》:从采集策略反爬对抗,从数据清洗分布式调度,持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”,让数据价值真正做到——抓得到、洗得净、用得上

📌专栏食用指南(建议收藏)

  • ✅ 入门基础:环境搭建 / 请求与解析 / 数据落库
  • ✅ 进阶提升:登录鉴权 / 动态渲染 / 反爬对抗
  • ✅ 工程实战:异步并发 / 分布式调度 / 监控与容错
  • ✅ 项目落地:数据治理 / 可视化分析 / 场景化应用

📣专栏推广时间:如果你想系统学爬虫,而不是碎片化东拼西凑,欢迎订阅专栏👉《Python爬虫实战》👈,一次订阅后,专栏内的所有文章可永久免费阅读,持续更新中。

💕订阅后更新会优先推送,按目录学习更高效💯~

0️⃣ 前言(Preface)

  • 我们要干什么:利用 Python 定向抓取豆瓣电影 Top 250 榜单,提取电影名、评分、引言(Quote)和详情链接,最终存为 Excel/CSV。

  • 工具箱requests(发请求) +lxml(高效解析) +pandas(数据存储)。

  • 读完你能获得什么?

    1. 掌握User-Agent伪装的核心技巧,解决 403 Forbidden 问题。
    2. 学会使用XPath这种比正则快、比 BS4 准的解析语法。
    3. 获得一套可复用于绝大多数静态列表网站的爬虫模板。

1️⃣ 摘要(Abstract)

本文将构建一个生产级的小型爬虫,针对movie.douban.com/top250进行分页抓取。区别于简单的 Demo,我们将重点讲解如何通过自定义 Headers 绕过基础反爬,利用lxml.etree进行高效率 DOM 解析,并处理数据中的空白与异常,最终产出结构化的 CSV 数据文件。

2️⃣ 背景与需求(Why)

  • 为什么要爬

    • 数据沉淀:建立自己的高分电影数据库,不用每次都去网页翻。
    • 分析练习:后续可以做“哪个年代好电影最多”、“哪个导演霸榜”的数据分析。
  • 目标站点https://movie.douban.com/top250

  • 目标字段清单

    • Rank(排名)
    • Title(电影中文名)
    • Rating(评分)
    • Quote(经典台词/一句话评价)
    • Link(详情页链接)

3️⃣ 合规与注意事项(必写) ⚖️

停一下,听我说:爬虫是把双刃剑,咱们只做技术交流,不做网络强盗。

  1. Robots 协议:豆瓣的 robots.txt 禁止爬取用户个人数据,但 Top 250 这种公开榜单通常处于灰度区,作为个人学习且不商用的前提下,严禁高频请求
  2. 频率控制(Rate Limiting):这是底线!代码里必须加time.sleep(2)。如果你一秒钟发 100 个请求,IP 被封是小事,给人家服务器造成压力就是你的不对了。
  3. 数据隐私:我们只抓公开的电影信息,绝对不抓取用户的评论ID、账号信息等隐私数据。

4️⃣ 技术选型与整体流程(What/How)

  • 技术栈静态网页抓取

    • 豆瓣 Top 250 是典型的服务端渲染(SSR),右键“查看网页源代码”能看到数据,所以不需要 Selenium/Playwright 这种重型核武器。
  • 解析库选择:为什么选lxml而不是BeautifulSoup

    • lxml基于 C 语言库,解析速度比 BS4 快几十倍。
    • XPath语法通用性强,学会了它,以后写自动化测试都能用。
  • 流程图
    生成分页 URLFetcher (带 Headers 请求)Parser (XPath 提取)Cleaner (去除空格/换行)Storage (CSV 追加写入)

5️⃣ 环境准备与依赖安装(可复现) 🛠️

  • Python 版本:Python 3.8+

  • 项目结构

    douban_spider/ ├── spider.py # 主程序 ├── requirements.txt # 依赖 └── results/ # 结果存这就行 └── douban_top250.csv
  • 依赖安装

    pipinstallrequests lxml pandas

    (注:这里引入 pandas 是为了存 CSV 更方便,不想用的同学用内置 csv 模块也行)

6️⃣ 核心实现:请求层(Fetcher) 📡

豆瓣是有反爬的!如果你直接requests.get(url),大概率会收到418 I’m a teapot或者403 Forbidden。必须带上User-Agent

importrequestsimportrandomimporttimefromrequests.exceptionsimportRequestExceptiondefget_page_source(url):""" 伪装成浏览器发起请求,获取网页源码 """# 这里的 User-Agent 是爬虫的“身份证”,必须伪装成浏览器headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36','Referer':'https://movie.douban.com/','Host':'movie.douban.com'}try:response=requests.get(url,headers=headers,timeout=10)ifresponse.status_code==200:returnresponse.textelse:print(f"⚠️ 状态码异常:{response.status_code}")returnNoneexceptRequestExceptionase:print(f"❌ 请求连接失败:{e}")returnNone

7️⃣ 核心实现:解析层(Parser) 🔍

这里我们用XPath。它的逻辑是“路径定位”,比如//div[@class='item']意思就是“找到文档里所有 class 为 item 的 div”。

fromlxmlimportetreedefparse_html(html):""" 利用 lxml 的 XPath 提取数据,快准狠 """ifnothtml:return[]tree=etree.HTML(html)items=[]# 1. 找到所有电影的卡片容器# 豆瓣页面结构:<ol class="grid_view"> -> <li> -> <div class="item">movie_nodes=tree.xpath('//ol[@class="grid_view"]/li/div[@class="item"]')fornodeinmovie_nodes:try:# 排名:在 <em class="">1</em> 中rank=node.xpath('./div[@class="pic"]/em/text()')[0]# 标题:有多个 span,第一个通常是中文名# .//span[@class="title"] 返回一个列表titles=node.xpath('.//div[@class="info"]//span[@class="title"]/text()')main_title=titles[0].strip()iftitleselse"未知标题"# 链接link=node.xpath('./div[@class="pic"]/a/@href')[0]# 评分:在 <span class="rating_num">rating=node.xpath('.//span[@class="rating_num"]/text()')[0]# 引言(Quote):有的电影可能没有,需要容错!# XPath 如果没找到,返回空列表quote_tag=node.xpath('.//span[@class="inq"]/text()')quote=quote_tag[0]ifquote_tagelse""items.append({'rank':rank,'title':main_title,'rating':rating,'quote':quote,'link_url':link})exceptIndexErrorase:# 只要 HTML 结构微调,XPath 就可能报错,这里做个软着陆print(f"⚠️ 解析某条目时出错:{e}")continuereturnitems

8️⃣ 数据存储与导出(Storage) 💾

我们这次用csv模块的标准写法,保证通用性。

  • 字段映射

    • Rank -> 排名
    • Title -> 电影名
    • Rating -> 评分
    • Quote -> 推荐语
    • Link_URL -> 链接
importcsvimportosdefsave_to_csv(data,filename="douban_top250.csv"):""" 追加写入模式,抓一页存一页,防止程序崩了白忙活 """is_file_exist=os.path.exists(filename)withopen(filename,mode='a',encoding='utf-8-sig',newline='')asf:writer=csv.DictWriter(f,fieldnames=['rank','title','rating','quote','link_url'])# 如果文件第一次创建,写入表头ifnotis_file_exist:writer.writeheader()writer.writerows(data)

9️⃣ 运行方式与结果展示(必写) 🚀

组合代码,加上翻页逻辑。豆瓣 Top 250 每页 25 条,共 10 页。URL 规律是start=0,start=25,start=50

defmain():print("🎬 豆瓣 Top 250 爬虫启动...")base_url="https://movie.douban.com/top250?start={}&filter="forpageinrange(0,10):# 0到9,共10页start_num=page*25url=base_url.format(start_num)print(f"📡 正在采集第{page+1}页 (start={start_num})...")html=get_page_source(url)ifhtml:movies=parse_html(html)save_to_csv(movies)print(f"✅ 第{page+1}页采集完成,存入{len(movies)}条数据。")else:print(f"❌ 第{page+1}页采集失败。")# ⚠️ 关键:随机休眠 2-4 秒,模仿人类阅读速度# 这是对服务器最基本的尊重,也是避免被封 IP 的最简单手段sleep_time=random.uniform(2,4)print(f"💤 休息{sleep_time:.2f}秒...")time.sleep(sleep_time)print("🎉 全部任务结束!请查看 douban_top250.csv")if__name__=="__main__":main()

展示结果示例

ranktitleratingquotelink_url
1肖申克的救赎9.7希望让人自由。https://movie…/1292052/
2霸王别姬9.6风华绝代。https://movie…/1291546/
3阿甘正传9.5生活就像一盒巧克力…https://movie…/1292720/

🔟 常见问题与排错(老司机经验) 🔧

  1. 返回 418 / 403

    • 原因:豆瓣发现你是脚本了。
    • 排查:99% 是 Headers 里的User-Agent没加或者过期了。去浏览器 F12 网络面板里复制一个新的过来。
  2. XPath 解析为空

    • 原因:网页结构变了,或者你直接在浏览器“审查元素”里 Copy 的 XPath 包含了 tbody(tbody 往往是浏览器自动渲染加的,源码里没有)。
    • 解决:必须对着requests.get打印出来的text源码写 XPath,或者用//div[@class='xxx']这种相对路径,别用/html/body/div[1]/...这种绝对路径。
  3. 乱码问题

    • 解决:Windows 下 Excel 打开 CSV 乱码?在open()函数里加encoding='utf-8-sig'(带 BOM 的 UTF-8)。

1️⃣1️⃣ 进阶优化(可选但加分) ⚡

想让你的爬虫更像个“正规军”?可以尝试:

  • IP 代理池:虽然抓 Top 250 不需要,但如果你要抓几十万条影评,单 IP 必死。你需要接入付费代理。
  • 断点续跑:程序崩了不想重头跑?在 loop 里加个判断,如果rank已经在 CSV 里了就continue
  • 随机 User-Agent:使用fake_useragent库,每次请求换个身份,让服务器以为是不同的人在访问。

1️⃣2️⃣ 总结与延伸阅读 📝

今天我们用不到 100 行代码,完成了一个从采集到存储的完整数据链路。

  • 复盘:Headers 伪装是敲门砖,XPath 是手术刀,CSV 是保鲜盒。
  • 下一步:试试抓取每部电影详情页里的“上映日期”和“剧情简介”?这需要你从列表页拿到 Link,再发起二次请求(嵌套抓取),难度升级,但更有趣!

保持好奇心,代码敲起来!

🌟 文末

好啦~以上就是本期的全部内容啦!如果你在实践过程中遇到任何疑问,欢迎在评论区留言交流,我看到都会尽量回复~咱们下期见!

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦~
三连就是对我写作道路上最好的鼓励与支持!❤️🔥

✅ 专栏持续更新中|建议收藏 + 订阅

墙裂推荐订阅专栏 👉 《Python爬虫实战》,本专栏秉承着以“入门 → 进阶 → 工程化 → 项目落地”的路线持续更新,争取让每一期内容都做到:

✅ 讲得清楚(原理)|✅ 跑得起来(代码)|✅ 用得上(场景)|✅ 扛得住(工程化)

📣想系统提升的小伙伴:强烈建议先订阅专栏 《Python爬虫实战》,再按目录大纲顺序学习,效率十倍上升~

✅ 互动征集

想让我把【某站点/某反爬/某验证码/某分布式方案】等写成某期实战?

评论区留言告诉我你的需求,我会优先安排实现(更新)哒~


⭐️ 若喜欢我,就请关注我叭~(更新不迷路)
⭐️ 若对你有用,就请点赞支持一下叭~(给我一点点动力)
⭐️ 若有疑问,就请评论留言告诉我叭~(我会补坑 & 更新迭代)


✅ 免责声明

本文爬虫思路、相关技术和代码仅用于学习参考,对阅读本文后的进行爬虫行为的用户本作者不承担任何法律责任。

使用或者参考本项目即表示您已阅读并同意以下条款:

  • 合法使用: 不得将本项目用于任何违法、违规或侵犯他人权益的行为,包括但不限于网络攻击、诈骗、绕过身份验证、未经授权的数据抓取等。
  • 风险自负: 任何因使用本项目而产生的法律责任、技术风险或经济损失,由使用者自行承担,项目作者不承担任何形式的责任。
  • 禁止滥用: 不得将本项目用于违法牟利、黑产活动或其他不当商业用途。
  • 使用或者参考本项目即视为同意上述条款,即 “谁使用,谁负责” 。如不同意,请立即停止使用并删除本项目。!!!
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/6 6:26:14

C语言程序设计第四版(何钦铭、颜晖)第八章指针之报数

4. 报数:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(m<n)的人退出圈子,下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。输入整数n和m,并按退出顺序输出退出圈子的人的编号。试编写相应程序。#include<stdio.h> #define MA…

作者头像 李华
网站建设 2026/8/7 7:55:53

学Simulink——基于Simulink的数字控制延时补偿DC-DC系统

目录 手把手教你学Simulink——基于Simulink的数字控制延时补偿DC-DC系统​ 摘要​ 一、背景与挑战​ 1.1 数字控制延时的危害与来源​ 1.2 延时补偿的核心目标与技术路线​ 1.2.1 补偿目标​ 1.2.2 技术路线​ 二、系统架构与核心算法​ 2.1 数字延时补偿DC-DC系统框架…

作者头像 李华
网站建设 2026/8/6 7:13:42

手把手教你学Simulink——基于Simulink的事件触发控制降低开关损耗

目录 手把手教你学Simulink——基于Simulink的事件触发控制降低开关损耗​ 摘要​ 一、背景与挑战​ 1.1 开关损耗的危害与传统控制局限​ 1.2 事件触发控制&#xff08;ETC&#xff09;的降损核心逻辑​ 1.2.1 ETC降损原理​ 1.2.2 设计目标​ 二、系统架构与核心算法​…

作者头像 李华
网站建设 2026/8/6 7:15:41

算法Python题解——DFS和BFS

目录 DFS LEGB原则 760数的计算 BFS DFS 把原问题分解成子问题的结构&#xff0c;天然适合用DFS实现 DFS的核心特点就是深度优先遍历所有&#xff0c;确保遍历每一种方式&#xff0c;枚举所有可能的生成路径 做DFS需要明确一下几个问题&#xff1a; 递归出口是&#xf…

作者头像 李华
网站建设 2026/8/6 7:15:32

[拆解LangChain执行引擎]Agent状态是如何被写入通道的?

根据“梳理Agent的执行流程”中针对Pregel执行流程的介绍&#xff0c;我们知道在每个Superstep的最后阶段&#xff0c;引擎会根据节点针对通道的订阅以及“__pregel_tasks”这个通道存储的Send对象&#xff0c;确定下一步应该执行的节点&#xff0c;并为它们创建代表执行任务的…

作者头像 李华