☰
Python爬虫实战:图书比价系统开发指南
2026/10/15 11:04:05 网站建设 项目流程
## 1. 项目背景与核心价值 最近在帮朋友搭建一个图书比价系统时,发现很多开发者对电商数据采集存在实际需求但缺乏完整案例。Books to Scrape这个专门为爬虫练习设计的网站,恰好包含了完整的图书分类、详情页、价格等结构化数据。通过这个实战项目,我们不仅可以掌握基础爬虫技能,更能学习如何将零散数据转化为可分析的商业情报。 这个项目的独特价值在于: - 真实模拟电商网站的反爬机制(如请求频率限制) - 完整覆盖从列表页到详情页的多级采集场景 - 数据可直接用于价格监控、竞品分析等商业场景 - 最终生成的CSV文件兼容Excel/Power BI等分析工具 ## 2. 技术方案设计 ### 2.1 工具选型解析 选择Requests+BeautifulSoup这套经典组合主要基于三点考量: 1. **学习曲线平缓**:相比Scrapy框架更适合新手理解HTTP请求和DOM解析的基本原理 2. **灵活性强**:可以自由控制请求间隔、异常处理等细节 3. **资源消耗低**:在采集中小规模数据时效率更高 > 注意:虽然Selenium能处理JS渲染页面,但目标网站是纯静态页面,用无头浏览器反而会降低效率 ### 2.2 爬虫架构设计 采用分层采集策略确保数据完整性:
  1. 分类页采集 → 获取所有图书URL ↓
  2. 详情页采集 → 提取标题/价格/库存等字段 ↓
  3. 数据清洗 → 处理特殊字符/单位统一 ↓
  4. CSV导出 → 按ISBN去重存储
## 3. 核心代码实现 ### 3.1 请求控制模块 ```python import requests from time import sleep from random import uniform def safe_get(url, retry=3): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)' } try: # 随机延迟1-3秒避免被封 sleep(uniform(1, 3)) response = requests.get(url, headers=headers) response.raise_for_status() return response.text except Exception as e: if retry > 0: return safe_get(url, retry-1) raise Exception(f"请求失败: {str(e)}")

关键点说明:

  • uniform(1,3)比固定延迟更模拟人工操作
  • raise_for_status()自动检测4xx/5xx错误
  • 递归重试机制增强鲁棒性

3.2 数据解析模块

from bs4 import BeautifulSoup def parse_book_page(html): soup = BeautifulSoup(html, 'lxml') # 使用CSS选择器精准定位 return { 'title': soup.select_one('h1').text.strip(), 'price': float(soup.select_one('.price_color').text[1:]), 'stock': int(soup.select_one('.instock').text.split()[2]), 'rating': soup.select_one('p.star-rating')['class'][1], 'upc': soup.select('tr')[0].td.text # 第一行tr下的td }

避坑指南:网站存在两种价格格式(£12.34 / €12.34),建议统一转换为浮点数存储

4. 完整爬取流程

4.1 分类页遍历技巧

通过分析网站结构发现分类URL规律:

http://books.toscrape.com/catalogue/category/books/{category}_index.html

使用集合存储已采集URL避免重复:

visited_urls = set() def get_category_books(main_url): html = safe_get(main_url) soup = BeautifulSoup(html, 'lxml') book_links = [ f"http://books.toscrape.com/catalogue{link['href'][8:]}" for link in soup.select('h3 a') if link['href'] not in visited_urls ] visited_urls.update(book_links) return book_links

4.2 分页处理策略

当遇到分页时,通过检查"next"按钮状态决定是否继续:

next_button = soup.select_one('li.next a') if next_button: next_url = urljoin(main_url, next_button['href']) book_links.extend(get_category_books(next_url))

5. 数据存储优化

5.1 CSV导出增强版

使用csv.DictWriter实现带标题行的规范存储:

import csv def save_to_csv(data, filename): fieldnames = ['title', 'price', 'stock', 'rating', 'upc'] with open(filename, 'w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerows(data) print(f"成功保存{len(data)}条数据到{filename}")

5.2 数据去重方案

利用ISBN(UPC)作为唯一标识符:

unique_books = {book['upc']: book for book in all_books}.values()

6. 反爬对抗实战

6.1 请求头伪装技巧

除了User-Agent,建议添加更多合法头部:

headers = { 'Accept': 'text/html,application/xhtml+xml', 'Accept-Language': 'en-US,en', 'Referer': 'http://books.toscrape.com/' }

6.2 代理IP接入方案

当出现403错误时,可引入代理池:

proxies = { 'http': 'http://user:pass@proxy_ip:port', 'https': 'https://user:pass@proxy_ip:port' } response = requests.get(url, headers=headers, proxies=proxies)

7. 数据分析应用示例

7.1 价格分布分析

使用pandas快速统计:

import pandas as pd df = pd.read_csv('books.csv') print(df['price'].describe()) # 输出结果示例 """ count 1000.00 mean 25.41 std 15.23 min 10.11 25% 15.67 50% 20.50 75% 30.99 max 99.99 """

7.2 库存预警功能

标记库存不足10本的图书:

df['low_stock'] = df['stock'].apply(lambda x: '是' if x <10 else '否')

8. 项目扩展方向

  1. 自动化监控:用APScheduler定时执行爬虫
  2. 价格异常检测:设置阈值触发邮件报警
  3. 可视化看板:用Matplotlib生成价格趋势图
  4. 多平台对比:整合其他电商网站数据

经验之谈:首次运行建议限制采集数量(如100本),待调试通过后再全量采集。我在实际项目中遇到过因编码问题导致CSV文件损坏的情况,现在会额外添加encoding='utf-8-sig'参数确保Excel兼容性。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询