欢迎光临
我们一直在努力

硬核入门!Python爬虫实战:爬取豆瓣读书TOP250,书名+评分+简介,一键生成精美Excel书单(2026避坑版)

前言

“想建个私人书单,却要在豆瓣上一页页复制粘贴?” “看到好书想记录,但手动整理书名、作者、评分、简介太耗时?” “听说爬虫很酷,但怕封IP、怕写代码太难、怕法律风险?”

别担心!今天我们将通过一个经典且实用的项目——爬取豆瓣读书TOP250,带你从零开始掌握Python爬虫的核心技能。

为什么选豆瓣TOP250?

  • 结构清晰:HTML结构规范,非常适合新手练习解析。
  • 数据价值高:涵盖书名、作者、评分、评价人数、简介等核心信息,是制作书单的完美素材。
  • 反爬适中:有一定的反爬机制(如User-Agent检查),能学到真实的对抗技巧,但又不会像大厂那样难如登天。

本实战你将学到:

  • 🕷️ 请求伪装:如何构造Headers,让服务器以为你是真人浏览器。
  • 🔍 数据提取:使用 BeautifulSoup 和 CSS选择器 精准定位目标数据。
  • 🛡️ 反爬策略:添加延时、随机User-Agent,优雅地避免被封禁。
  • 📊 数据持久化:使用 pandas 将清洗后的数据一键导出为专业的Excel表格。
  • ⚖️ 合规指南:爬虫的道德与法律边界,做守法的开发者。

哪怕你是编程小白,跟着本文步骤,30分钟内也能拥有自己的自动化书单收集器!


一、环境准备:工欲善其事

在开始之前,我们需要安装几个核心库。请确保你已安装 Python 3.8+。

1. 安装依赖

打开终端(CMD或Terminal),运行以下命令:

pip install requests beautifulsoup4 pandas openpyxl

  • requests: 发送HTTP请求,获取网页内容。
  • beautifulsoup4: 解析HTML,提取数据的神器。
  • pandas: 数据处理与Excel导出。
  • openpyxl: pandas导出Excel所需的引擎。

2. 项目结构

创建一个文件夹 douban_spider,内部结构如下:

douban_spider/
├── main.py # 主程序代码
├── books.xlsx # 生成的结果文件(运行后产生)
└── README.md # 说明文档


二、核心代码实战:四步走战略

第一步:分析网页结构与反爬机制

打开浏览器(推荐Chrome),访问 豆瓣读书TOP250。

  • 按F12打开开发者工具,切换到 Network (网络) 标签。
  • 刷新页面,找到第一个 top250 请求。
  • 观察Request Headers:
    • 豆瓣会检查 User-Agent。如果缺失或是Python默认的 python-requests,直接返回418错误(“I’m a teapot”)。
    • 对策:我们需要伪造一个浏览器的User-Agent。
  • 观察HTML结构(Elements标签):
    • 每本书在一个 <tr class="item"> 标签中。
    • 书名:<div class="pl2"> 下的 <a> 标签。
    • 作者/出版社/价格:<p class="pl"> 标签。
    • 评分:<span class="rating_nums">。
    • 简介:<span class="inq">(注意:部分书可能没有简介)。
    • 图片链接:<img> 的 src 属性。
  • 第二步:编写爬虫核心逻辑 (main.py)

    import requests
    from bs4 import BeautifulSoup
    import pandas as pd
    import time
    import random

    # 1. 配置请求头 (伪装成浏览器)
    HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
    "Referer": "https://book.douban.com/"
    }

    def get_book_data(url):
    """发送请求并获取单页数据"""
    try:
    response = requests.get(url, headers=HEADERS, timeout=10)
    response.raise_for_status()
    # 豆瓣网页编码通常是utf-8,但有时需要手动指定
    response.encoding = 'utf-8'
    return response.text
    except requests.RequestException as e:
    print(f"请求失败: {e}")
    return None

    def parse_html(html):
    """解析HTML,提取书籍信息"""
    soup = BeautifulSoup(html, 'html.parser')
    books = []

    # 定位所有书籍条目
    items = soup.find_all('tr', class_='item')

    for item in items:
    try:
    # — 提取书名 (处理换行符) —
    title_div = item.find('div', class_='pl2')
    full_title = title_div.find('a')['title'] if title_div.find('a').get('title') else title_div.find('a').get_text(strip=True)
    # 有些书名包含副标题,用换行符分隔,这里简单处理
    title = full_title.replace('\\n', '').replace('/', ' ').strip()

    # — 提取作者/出版社/年份/价格 —
    info_p = item.find('p', class_='pl')
    info_text = info_p.get_text(strip=True) if info_p else ""
    # 简单分割,实际可根据 '/' 进一步结构化
    author_pub = info_text

    # — 提取评分 —
    rating_span = item.find('span', class_='rating_nums')
    rating = rating_span.get_text(strip=True) if rating_span else "无评分"

    # — 提取评价人数 —
    votes_span = item.find('span', text=lambda t: t and '人评价' in t)
    votes = votes_span.get_text(strip=True).replace('人评价', '') if votes_span else "0"

    # — 提取简介 —
    quote_span = item.find('span', class_='inq')
    summary = quote_span.get_text(strip=True) if quote_span else "无简介"

    # — 提取封面图链接 —
    img_tag = item.find('img')
    cover_url = img_tag['src'] if img_tag else ""

    books.append({
    "书名": title,
    "作者/出版信息": author_pub,
    "评分": rating,
    "评价人数": votes,
    "简介": summary,
    "封面链接": cover_url
    })
    except Exception as e:
    print(f"解析单条数据出错: {e}")
    continue

    return books

    def main():
    all_books = []
    base_url = "https://book.douban.com/top250?start={}"

    print("🚀 开始爬取豆瓣读书TOP250…")

    # TOP250每页25本,共10页 (0, 25, 50 … 225)
    for page in range(10):
    start_num = page * 25
    url = base_url.format(start_num)
    print(f"正在爬取第 {page + 1} 页: {url}")

    html = get_book_data(url)
    if html:
    data = parse_html(html)
    all_books.extend(data)
    print(f"✅ 第 {page + 1} 页抓取成功,共 {len(data)} 本书")
    else:
    print(f"❌ 第 {page + 1} 页抓取失败,跳过")

    # 🛡️ 关键反爬策略:随机延时
    # 模拟人类阅读速度,避免请求过快触发风控
    sleep_time = random.uniform(1.5, 3.5)
    time.sleep(sleep_time)

    # 3. 保存数据到Excel
    if all_books:
    df = pd.DataFrame(all_books)
    file_name = "豆瓣读书TOP250书单.xlsx"

    # 调整列顺序
    df = df[["书名", "作者/出版信息", "评分", "评价人数", "简介", "封面链接"]]

    # 导出Excel
    df.to_excel(file_name, index=False)
    print(f"🎉 成功!数据已保存至 {file_name},共 {len(df)} 条记录。")
    else:
    print("💥 未获取到任何数据,请检查网络或代码。")

    if __name__ == "__main__":
    main()


    三、关键点深度解析

    1. 为什么需要 User-Agent?

    服务器通过 User-Agent 判断客户端身份。如果是Python默认的 python-requests/x.x.x,豆瓣会直接拒绝服务(返回418状态码)。

    • 解决:复制浏览器的UA字符串放入 HEADERS 字典。
    • 进阶:可以建立一个UA池,每次请求随机选择一个,进一步降低风险。

    2. 数据清洗的细节

    • 书名处理:豆瓣的书名有时包含换行符 \\n 或副标题分隔符 /,代码中使用了 .replace() 进行清理,保证Excel整洁。
    • 缺失值处理:不是所有书都有“简介”或“评分”,代码中做了 if … else "无简介" 的判断,防止程序报错崩溃。

    3. 反爬核心:时间延时 (time.sleep)

    这是新手最容易忽略的一点。

    • 错误做法:不加延时,瞬间发送10个请求。结果:IP被暂时封禁。
    • 正确做法:time.sleep(random.uniform(1.5, 3.5))。
      • 模拟人类翻页的不确定性。
      • 给服务器喘息时间,体现“礼貌爬虫”原则。

    4. 为什么用 Pandas 而不是 csv?

    • csv 处理中文编码容易乱码(GBk vs UTF-8)。
    • pandas 的 to_excel 直接生成 .xlsx 格式,自动处理编码,且支持格式化(虽然本例未展示,但扩展性强)。

    四、运行结果展示

    运行脚本后,你将得到一个名为 豆瓣读书TOP250书单.xlsx 的文件。

    书名作者/出版信息评分评价人数简介封面链接
    百年孤独 [哥伦比亚] 加西亚·马尔克斯 / 2011-6-1 / 39.50元 9.3 582109 魔幻现实主义文学巅峰之作… https://img1.doubanio.com/…
    活着 余华 / 2012-8-1 / 20.00元 9.4 903211 讲述一个人一生的故事,关于苦难与生存… https://img2.doubanio.com/…

    你可以直接用Excel筛选“评分>9.0”的书籍,或者根据“作者”排序,轻松制作你的年度阅读计划!


    五、常见问题与避坑指南 (FAQ)

    ❌ 问题1:运行报错 418 Client Error: I'm a teapot

    • 原因:User-Agent 缺失或被识别为爬虫。
    • 解决:检查 HEADERS 是否正确赋值。尝试更换一个最新的浏览器UA字符串。

    ❌ 问题2:中文乱码

    • 原因:Excel打开CSV时的编码问题,或爬取时解码错误。
    • 解决:本代码直接使用 pandas.to_excel,避免了CSV乱码问题。如果必须存CSV,请指定 encoding='utf-8-sig'。

    ❌ 问题3:数据提取为空

    • 原因:豆瓣网页结构微调,导致CSS选择器失效。
    • 解决:重新F12检查元素类名(class name)是否变化(如 pl2 变成了 pl3),更新 find 或 select 的参数。

    ❌ 问题4:IP被封禁

    • 现象:连续请求后,所有请求都返回错误。
    • 解决:
    • 增加 sleep 时间(如 5-10秒)。
    • 暂停程序,换个网络环境(如切换手机热点)再试。
    • 进阶:使用代理IP池(本项目不需要,仅针对大规模爬取)。

    六、⚠️ 重要:爬虫的道德与法律边界

    技术无罪,但使用需有度。 在编写和运行爬虫时,请务必遵守以下原则:

  • 遵守 Robots 协议:
    • 访问 https://www.douban.com/robots.txt。
    • 豆瓣允许部分爬取,但禁止高频访问和商业化利用。本教程仅限个人学习研究。
  • 控制频率:
    • 不要对服务器造成压力。本代码中的 sleep 是必须的,不要删除。
  • 数据用途:
    • ✅ 允许:个人书单管理、数据分析练习、学术研究。
    • ❌ 禁止:将数据用于商业售卖、搭建镜像网站、公开传播大量数据。
  • 隐私保护:
    • 只爬取公开数据,严禁尝试获取用户隐私信息。
  • 声明:本教程代码仅供学习交流使用。请勿用于任何非法用途。如因滥用代码导致的法律纠纷,作者不承担任何责任。


    七、进阶挑战:你能做得更好!

    如果你已经跑通了代码,不妨尝试以下挑战,提升技能树:

  • 下载封面图:
    • 利用 cover_url,使用 requests 下载图片保存到本地文件夹,建立可视化书库。
  • 深入详情页:
    • 目前只爬了列表页。尝试进入每本书的详情页,爬取更详细的“目录”、“书评摘要”、“标签”。
  • 数据可视化:
    • 使用 matplotlib 或 pyecharts,绘制“高分书籍出版社分布图”或“评分与评价人数散点图”。
  • 自动化推送:
    • 结合 smtplib,每周自动抓取新书榜,发送邮件推荐给你自己。

  • 总结

    通过这个实战,你不仅获得了一份珍贵的豆瓣TOP250书单,更重要的是掌握了:

    • HTTP请求与响应的本质。
    • HTML解析的核心技巧。
    • 反爬虫的基本应对策略。
    • 数据清洗与存储的完整流程。

    爬虫是通往数据世界的一把钥匙。现在,钥匙在你手中,去探索更多有趣的数据吧!

    赞(0)
    未经允许不得转载:171主机测评 » 硬核入门!Python爬虫实战:爬取豆瓣读书TOP250,书名+评分+简介,一键生成精美Excel书单(2026避坑版)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址