㊗️本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~
㊙️本期爬虫难度指数:⭐⭐⭐
🉐福利:一次订阅后,专栏内的所有文章可永久免费看,持续更新中,保底1000+(篇)硬核实战内容。
全文目录:
- 🌟 开篇语
- 1️⃣ 摘要
- 2️⃣ 背景与需求(Why)
- 3️⃣ 合规与注意事项(必写)
- 4️⃣ 技术选型与整体流程(What/How)
- 5️⃣ 环境准备与依赖安装(可复现)💻
- 6️⃣ 核心实现:请求层(Fetcher)📡
- 7️⃣ 核心实现:解析层(Parser)🔍
- 8️⃣ 数据存储与导出(Storage)💾
- 9️⃣ 运行方式与结果展示(必写)🚀
- 🔟 常见问题与排错(建议收藏)🆘
- 1️⃣1️⃣ 进阶优化(可选但加分)🚀
- 1️⃣2️⃣ 总结与延伸阅读 📝
- 🌟 文末
- ✅ 专栏持续更新中|建议收藏 + 订阅
- ✅ 互动征集
- ✅ 免责声明
🌟 开篇语
哈喽,各位小伙伴们你们好呀~我是【喵手】。
运营社区: C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO
欢迎大家常来逛逛,一起学习,一起进步~🌟
我长期专注Python 爬虫工程化实战,主理专栏 《Python爬虫实战》:从采集策略到反爬对抗,从数据清洗到分布式调度,持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”,让数据价值真正做到——抓得到、洗得净、用得上。
📌专栏食用指南(建议收藏)
- ✅ 入门基础:环境搭建 / 请求与解析 / 数据落库
- ✅ 进阶提升:登录鉴权 / 动态渲染 / 反爬对抗
- ✅ 工程实战:异步并发 / 分布式调度 / 监控与容错
- ✅ 项目落地:数据治理 / 可视化分析 / 场景化应用
📣专栏推广时间:如果你想系统学爬虫,而不是碎片化东拼西凑,欢迎订阅专栏👉《Python爬虫实战》👈,一次订阅后,专栏内的所有文章可永久免费阅读,持续更新中。
💕订阅后更新会优先推送,按目录学习更高效💯~
1️⃣ 摘要
本文将带你使用 Python 的requests和BeautifulSoup库,构建一个健壮的爬虫脚本,自动抓取 Books to Scrape 网站上所有书籍的名称、价格、评价星级及库存状态,并将其结构化存储为 CSV 文件。
读完你将获得:
- 掌握一套可复用的“生产级”单线程爬虫架构(请求-解析-存储解耦)。
- 学会处理分页抓取与异常容错机制。
- 得到一份开箱即用的 Python 爬虫源码。
2️⃣ 背景与需求(Why)
为什么要爬:
在电商竞品分析或图书市场调研中,我们需要获取大量的书籍元数据。手动复制粘贴?太慢了!我们需要自动化脚本来完成信息聚合,后续可用于价格趋势分析或选品决策。
目标站点:
- URL:
http://books.toscrape.com/
目标字段清单:
| 字段名 (Field) | 说明 |
|---|---|
title | 书籍完整标题 |
price | 价格 (英镑) |
rating | 评分 (Star Rating) |
availability | 库存状态 |
detail_url | 详情页链接 |
3️⃣ 合规与注意事项(必写)
做爬虫,底线比技术更重要!🚫
- Robots.txt:该站点的
/robots.txt通常允许所有 User-agent 访问(Sandbox 性质),但在实战中,必须优先检查site.com/robots.txt。 - 频率控制:虽然是练习站,但我们要养成好习惯。代码中会加入
time.sleep,模拟人类阅读间隔,拒绝 DoS 攻击式的并发。 - 隐私与版权:本次仅采集公开的商品信息,不涉及用户隐私。严禁用于抓取受版权保护的付费内容或绕过登录墙抓取敏感数据。
4️⃣ 技术选型与整体流程(What/How)
技术选型:
这是一个静态网页(HTML服务端渲染),不需要执行 JavaScript。
为什么选
requests+BeautifulSoup?- 相比
Scrapy:对于中小规模(1000本书)的任务,框架太重,脚本化开发更灵活轻便。 - 相比
Selenium/Playwright:浏览器自动化太慢且吃资源,直接 HTTP 请求效率高 10 倍以上!
- 相比
整体流程:
5️⃣ 环境准备与依赖安装(可复现)💻
Python 版本:推荐 Python 3.8+
依赖安装:
我们需要安装 HTTP 请求库、HTML 解析库以及解析器。
pipinstallrequests beautifulsoup4 lxml项目结构:
建议创建一个文件夹book_spider/,结构如下:
book_spider/ ├── main.py # 入口文件 ├── scraper.py # 核心逻辑 ├── output/ # 存放结果 │ └── books.csv └── requirements.txt6️⃣ 核心实现:请求层(Fetcher)📡
这里我们不能直接裸奔!必须伪装成浏览器。
importrequestsfromrequests.adaptersimportHTTPAdapterfromurllib3.util.retryimportRetryimporttimeimportrandomdefget_html(url):""" 发送请求获取 HTML,包含重试机制和随机 User-Agent """# 模拟真实浏览器 Headerheaders={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36","Referer":"http://books.toscrape.com/"}# 配置重试策略:遇到 500/502/503/504 错误时重试 3 次session=requests.Session()retry=Retry(connect=3,backoff_factor=0.5)adapter=HTTPAdapter(max_retries=retry)session.mount('http://',adapter)session.mount('https://',adapter)try:response=session.get(url,headers=headers,timeout=10)response.raise_for_status()# 非 200 抛出异常response.encoding='utf-8'# 显式设定编码,防止乱码returnresponse.textexceptExceptionase:print(f"❌ 请求失败:{url}, Error:{e}")returnNone7️⃣ 核心实现:解析层(Parser)🔍
解析是爬虫的灵魂。我们要用 CSS 选择器精准定位。
frombs4importBeautifulSoupfromurllib.parseimporturljoindefparse_books(html,base_url):""" 解析 HTML,提取书籍信息和下一页链接 """ifnothtml:return[],Nonesoup=BeautifulSoup(html,'lxml')book_items=soup.select('article.product_pod')data_list=[]foriteminbook_items:try:# 1. 提取标题 (Title)title_tag=item.select_one('h3 a')title=title_tag['title']iftitle_tagelse"N/A"# 2. 提取价格 (Price) - 原始文本是 "£51.77"price_text=item.select_one('p.price_color').text price=price_text.replace('£','').strip()# 3. 提取评分 (Rating) - class 包含 "star-rating Three"star_class=item.select_one('p.star-rating')['class']# 获取第二个 class 值,即 'Three', 'Four' 等rating=star_class[1]iflen(star_class)>1else"Unknown"# 4. 提取链接并拼接relative_url=item.select_one('h3 a')['href']full_url=urljoin(base_url,relative_url)data_list.append({'title':title,'price':price,'rating':rating,'availability':'In Stock',# 该站点列表页默认有货,详情页才准,这里简化'link':full_url})exceptAttributeErrorase:print(f"⚠️ 解析单个条目出错:{e}")continue# 提取下一页链接next_btn=soup.select_one('li.next a')next_url=urljoin(base_url,next_btn['href'])ifnext_btnelseNonereturndata_list,next_url8️⃣ 数据存储与导出(Storage)💾
简单直接,我们存CSV。
importcsvimportosdefsave_to_csv(data,filename="books_data.csv"):""" 追加写入 CSV 文件 """file_exists=os.path.isfile(filename)withopen(filename,mode='a',newline='',encoding='utf-8-sig')asf:fieldnames=['title','price','rating','availability','link']writer=csv.DictWriter(f,fieldnames=fieldnames)ifnotfile_exists:writer.writeheader()# 文件不存在时才写表头writer.writerows(data)print(f"💾 已保存{len(data)}条数据到{filename}")9️⃣ 运行方式与结果展示(必写)🚀
将以上代码整合到main.py中,运行流程如下:
启动命令:
python main.py主逻辑代码:
defmain():url="http://books.toscrape.com/catalogue/page-1.html"base_url="http://books.toscrape.com/catalogue/"whileurl:print(f"🔄 正在抓取:{url}")html=get_html(url)books,next_url=parse_books(html,url)ifbooks:save_to_csv(books,filename="books_result.csv")url=next_url# 翻页time.sleep(random.uniform(1,3))# 随机休眠 1-3秒,模拟真人print("🎉 全部抓取完成!")if__name__=="__main__":main()示例结果展示 (
books_result.csv):
| title | price | rating | availability | link |
|---|---|---|---|---|
| A Light in the Attic | 51.77 | Three | In Stock | http://books.toscrape.com/…/a-light-in-the-attic… |
| Tipping the Velvet | 53.74 | One | In Stock | http://books.toscrape.com/…/tipping-the-velvet… |
| Soumission | 50.10 | One | In Stock | http://books.toscrape.com/…/soumission… |
🔟 常见问题与排错(建议收藏)🆘
HTML 抓到空壳?
- 现象:
response.text里只有简短的 JS 代码,没有书名。 - 原因:网站采用了 SPA(单页应用)动态渲染。
- 解决:换
Selenium或Playwright,或者在 Network 面板找XHR/Fetch的 JSON 接口。
- 现象:
403/429 报错?
- 403 Forbidden:通常是 Headers 没加对,检查
Referer和User-Agent。 - 429 Too Many Requests:你爬太快了!增大
time.sleep的间隔,或者使用代理 IP 池。
- 403 Forbidden:通常是 Headers 没加对,检查
编码乱码?
- Windows Excel 打开 CSV 乱码?在
open()时使用encoding='utf-8-sig',BOM 头能救命。
- Windows Excel 打开 CSV 乱码?在
1️⃣1️⃣ 进阶优化(可选但加分)🚀
如果这不仅仅是个练习,而是要抓取100万条数据,该怎么办?
- 并发加速:使用
concurrent.futures.ThreadPoolExecutor开启多线程,或者升级为aiohttp异步爬虫,速度提升 10-50 倍。 - 断点续跑:在数据库或 Redis 中记录
visited_urls。程序崩溃重启后,先检查该 URL 是否已抓过,避免重复劳动。 - 监控:接入
logging模块,将错误日志输出到文件,方便夜间无人值守时排查问题。
1️⃣2️⃣ 总结与延伸阅读 📝
复盘:
今天我们不仅写了一个爬虫,更建立了一套标准化的数据采集思维:从分析请求,到编写健壮的 Fetcher,再到精确的解析和持久化存储。看着终端里一行行数据滚动,是不是很有成就感?😎
下一步:
- 尝试抓取书籍详情页里的“产品描述”文本。
- 去学习Scrapy 框架,它是 Python 爬虫界的瑞士军刀,适合大型项目。
加油!每一个数据科学家都是从第一只小爬虫开始的!
🌟 文末
好啦~以上就是本期的全部内容啦!如果你在实践过程中遇到任何疑问,欢迎在评论区留言交流,我看到都会尽量回复~咱们下期见!
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦~
三连就是对我写作道路上最好的鼓励与支持!❤️🔥
✅ 专栏持续更新中|建议收藏 + 订阅
墙裂推荐订阅专栏 👉 《Python爬虫实战》,本专栏秉承着以“入门 → 进阶 → 工程化 → 项目落地”的路线持续更新,争取让每一期内容都做到:
✅ 讲得清楚(原理)|✅ 跑得起来(代码)|✅ 用得上(场景)|✅ 扛得住(工程化)
📣想系统提升的小伙伴:强烈建议先订阅专栏 《Python爬虫实战》,再按目录大纲顺序学习,效率十倍上升~
✅ 互动征集
想让我把【某站点/某反爬/某验证码/某分布式方案】等写成某期实战?
评论区留言告诉我你的需求,我会优先安排实现(更新)哒~
⭐️ 若喜欢我,就请关注我叭~(更新不迷路)
⭐️ 若对你有用,就请点赞支持一下叭~(给我一点点动力)
⭐️ 若有疑问,就请评论留言告诉我叭~(我会补坑 & 更新迭代)
✅ 免责声明
本文爬虫思路、相关技术和代码仅用于学习参考,对阅读本文后的进行爬虫行为的用户本作者不承担任何法律责任。
使用或者参考本项目即表示您已阅读并同意以下条款:
- 合法使用: 不得将本项目用于任何违法、违规或侵犯他人权益的行为,包括但不限于网络攻击、诈骗、绕过身份验证、未经授权的数据抓取等。
- 风险自负: 任何因使用本项目而产生的法律责任、技术风险或经济损失,由使用者自行承担,项目作者不承担任何形式的责任。
- 禁止滥用: 不得将本项目用于违法牟利、黑产活动或其他不当商业用途。
- 使用或者参考本项目即视为同意上述条款,即 “谁使用,谁负责” 。如不同意,请立即停止使用并删除本项目。!!!