
㊗️本期内容已收录至专栏《Python爬虫实战》持续完善知识体系与项目实战建议先订阅收藏后续查阅更方便㊙️本期爬虫难度指数⭐ (入门级)福利一次订阅后专栏内的所有文章可永久免费看持续更新中保底1000(篇)硬核实战内容。全文目录 开篇语0️⃣ 前言Preface1️⃣ 摘要Abstract2️⃣ 背景与需求Why3️⃣ 合规与注意事项必写 ⚖️4️⃣ 技术选型与整体流程What/How5️⃣ 环境准备与依赖安装可复现 ️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数据存储。读完你能获得什么掌握User-Agent伪装的核心技巧解决 403 Forbidden 问题。学会使用XPath这种比正则快、比 BS4 准的解析语法。获得一套可复用于绝大多数静态列表网站的爬虫模板。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️⃣ 合规与注意事项必写 ⚖️✋停一下听我说爬虫是把双刃剑咱们只做技术交流不做网络强盗。Robots 协议豆瓣的 robots.txt 禁止爬取用户个人数据但 Top 250 这种公开榜单通常处于灰度区作为个人学习且不商用的前提下严禁高频请求。频率控制Rate Limiting这是底线代码里必须加time.sleep(2)。如果你一秒钟发 100 个请求IP 被封是小事给人家服务器造成压力就是你的不对了。数据隐私我们只抓公开的电影信息绝对不抓取用户的评论ID、账号信息等隐私数据。4️⃣ 技术选型与整体流程What/How技术栈静态网页抓取。豆瓣 Top 250 是典型的服务端渲染SSR右键“查看网页源代码”能看到数据所以不需要 Selenium/Playwright 这种重型核武器。解析库选择为什么选lxml而不是BeautifulSouplxml基于 C 语言库解析速度比 BS4 快几十倍。XPath语法通用性强学会了它以后写自动化测试都能用。流程图生成分页 URL➔Fetcher (带 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:responserequests.get(url,headersheaders,timeout10)ifresponse.status_code200:returnresponse.textelse:print(f⚠️ 状态码异常:{response.status_code})returnNoneexceptRequestExceptionase:print(f❌ 请求连接失败:{e})returnNone7️⃣ 核心实现解析层Parser 这里我们用XPath。它的逻辑是“路径定位”比如//div[classitem]意思就是“找到文档里所有 class 为 item 的 div”。fromlxmlimportetreedefparse_html(html): 利用 lxml 的 XPath 提取数据快准狠 ifnothtml:return[]treeetree.HTML(html)items[]# 1. 找到所有电影的卡片容器# 豆瓣页面结构ol classgrid_view - li - div classitemmovie_nodestree.xpath(//ol[classgrid_view]/li/div[classitem])fornodeinmovie_nodes:try:# 排名在 em class1/em 中ranknode.xpath(./div[classpic]/em/text())[0]# 标题有多个 span第一个通常是中文名# .//span[classtitle] 返回一个列表titlesnode.xpath(.//div[classinfo]//span[classtitle]/text())main_titletitles[0].strip()iftitleselse未知标题# 链接linknode.xpath(./div[classpic]/a/href)[0]# 评分在 span classrating_numratingnode.xpath(.//span[classrating_num]/text())[0]# 引言Quote有的电影可能没有需要容错# XPath 如果没找到返回空列表quote_tagnode.xpath(.//span[classinq]/text())quotequote_tag[0]ifquote_tagelseitems.append({rank:rank,title:main_title,rating:rating,quote:quote,link_url:link})exceptIndexErrorase:# 只要 HTML 结构微调XPath 就可能报错这里做个软着陆print(f⚠️ 解析某条目时出错:{e})continuereturnitems8️⃣ 数据存储与导出Storage 我们这次用csv模块的标准写法保证通用性。字段映射Rank - 排名Title - 电影名Rating - 评分Quote - 推荐语Link_URL - 链接importcsvimportosdefsave_to_csv(data,filenamedouban_top250.csv): 追加写入模式抓一页存一页防止程序崩了白忙活 is_file_existos.path.exists(filename)withopen(filename,modea,encodingutf-8-sig,newline)asf:writercsv.DictWriter(f,fieldnames[rank,title,rating,quote,link_url])# 如果文件第一次创建写入表头ifnotis_file_exist:writer.writeheader()writer.writerows(data)9️⃣ 运行方式与结果展示必写 组合代码加上翻页逻辑。豆瓣 Top 250 每页 25 条共 10 页。URL 规律是start0,start25,start50…defmain():print( 豆瓣 Top 250 爬虫启动...)base_urlhttps://movie.douban.com/top250?start{}filterforpageinrange(0,10):# 0到9共10页start_numpage*25urlbase_url.format(start_num)print(f 正在采集第{page1}页 (start{start_num})...)htmlget_page_source(url)ifhtml:moviesparse_html(html)save_to_csv(movies)print(f✅ 第{page1}页采集完成存入{len(movies)}条数据。)else:print(f❌ 第{page1}页采集失败。)# ⚠️ 关键随机休眠 2-4 秒模仿人类阅读速度# 这是对服务器最基本的尊重也是避免被封 IP 的最简单手段sleep_timerandom.uniform(2,4)print(f 休息{sleep_time:.2f}秒...)time.sleep(sleep_time)print( 全部任务结束请查看 douban_top250.csv)if__name____main__:main()展示结果示例ranktitleratingquotelink_url1肖申克的救赎9.7希望让人自由。https://movie…/1292052/2霸王别姬9.6风华绝代。https://movie…/1291546/3阿甘正传9.5生活就像一盒巧克力…https://movie…/1292720/ 常见问题与排错老司机经验 返回 418 / 403原因豆瓣发现你是脚本了。排查99% 是 Headers 里的User-Agent没加或者过期了。去浏览器 F12 网络面板里复制一个新的过来。XPath 解析为空原因网页结构变了或者你直接在浏览器“审查元素”里 Copy 的 XPath 包含了 tbodytbody 往往是浏览器自动渲染加的源码里没有。解决必须对着requests.get打印出来的text源码写 XPath或者用//div[classxxx]这种相对路径别用/html/body/div[1]/...这种绝对路径。乱码问题解决Windows 下 Excel 打开 CSV 乱码在open()函数里加encodingutf-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爬虫实战》再按目录大纲顺序学习效率十倍上升✅ 互动征集想让我把【某站点/某反爬/某验证码/某分布式方案】等写成某期实战评论区留言告诉我你的需求我会优先安排实现(更新)哒~⭐️ 若喜欢我就请关注我叭更新不迷路⭐️ 若对你有用就请点赞支持一下叭给我一点点动力⭐️ 若有疑问就请评论留言告诉我叭我会补坑 更新迭代✅ 免责声明本文爬虫思路、相关技术和代码仅用于学习参考对阅读本文后的进行爬虫行为的用户本作者不承担任何法律责任。使用或者参考本项目即表示您已阅读并同意以下条款合法使用 不得将本项目用于任何违法、违规或侵犯他人权益的行为包括但不限于网络攻击、诈骗、绕过身份验证、未经授权的数据抓取等。风险自负 任何因使用本项目而产生的法律责任、技术风险或经济损失由使用者自行承担项目作者不承担任何形式的责任。禁止滥用 不得将本项目用于违法牟利、黑产活动或其他不当商业用途。使用或者参考本项目即视为同意上述条款,即 “谁使用谁负责” 。如不同意请立即停止使用并删除本项目。