Python爬虫实战:把“菜鸟教程”的知识树连根拔起(递归/遍历实战)(附 CSV 导出)!

㊙️本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~持续更新中!

㊗️爬虫难度指数:⭐

🚫声明:本数据&代码仅供学习交流,严禁用于商业用途、倒卖数据或违反目标站点的服务条款等,一切后果皆由使用者本人承担。公开榜单数据一般允许访问,但请务必遵守"君子协议",技术无罪,责任在人。

全文目录:

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

🌟 开篇语

哈喽,各位小伙伴们你们好呀~我是【喵手】。

运营社区: C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO

欢迎大家常来逛逛,一起学习,一起进步~🌟

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

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

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

📣 专栏推广时间 :如果你想系统学爬虫,而不是碎片化东拼西凑,欢迎订阅/关注专栏《Python爬虫实战》

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

1️⃣ 标题 && 摘要(Abstract)

项目名称:RunoobDocsCrawler_v1.0

核心工具:Python 3 + Requests + BeautifulSoup4

产出目标:针对菜鸟教程 Python 3 板块,抓取左侧导航栏的所有章节标题、链接,并进一步深入详情页抓取该章节的"简介"(第一段话),生成一份包含层级结构的 CSV/JSON 知识图谱。

读完这篇文章,你将获得:

  1. 🌲 处理层级结构 :如何把网页上的扁平 <a> 标签列表还原成有顺序的知识目录。
  2. 🖇 详情页联动:学会"列表页找链接 -> 详情页抓内容"的经典二步走策略。
  3. 🛡 容错处理:有些章节可能没有简介,如何防止代码报错崩溃。

2️⃣ 背景与需求(Why)

为什么要爬?

  • 离线阅读:将网页教程转为 Markdown 或 PDF,方便在飞机/地铁上学习。
  • 知识图谱构建:把目录导入 Notion 或思维导图软件,建立自己的技能树。
  • 内容聚合:统计一下一个教程到底有多少个知识点,预估学习时长。

🎯 目标站点https://www.runoob.com/python3/python3-tutorial.html

📋 目标字段清单

  • ID (序号):章节顺序
  • Chapter Name (章节名):例如 "Python3 基础语法"
  • URL (链接):该章节的网址
  • Intro (简介):详情页里的第一段描述性文字(摘要)

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

  • Robots 协议 :菜鸟教程是一个免费分享知识的站点,非常良心。请大家务必手下留情
  • 频率控制 :这次我们需要爬取详情页(N次请求)。严禁高并发! 如果你一秒钟发 50 个请求,对方服务器可能会把你判定为攻击。我们将严格执行 time.sleep(1)
  • 版权声明 :爬取的内容仅供个人学习使用,严禁打包成电子书进行售卖!这是对创作者最起码的尊重。🚫

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

技术栈

  • Requests:稳定可靠的 HTTP 库。
  • BeautifulSoup4 :适合处理文档型 HTML,提取 <div><a> 标签。

🌊 整体流程
访问首页提取左侧导航栏 URL 列表循环访问每个 URL提取 <p> 简介组装数据存入 CSV

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

Python 版本:3.8+

依赖安装

bash 复制代码
pip install requests beautifulsoup4 pandas

📂 项目结构

text 复制代码
runoob_crawler/
├── data/
│   └── python3_outline.csv
├── spider.py
└── requirements.txt

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

我们需要一个通用的下载器,因为既要下载首页,又要下载详情页。

python 复制代码
import requests
import time
import random
from fake_useragent import UserAgent

def fetch_url(url):
    ua = UserAgent()
    headers = {
        'User-Agent': ua.random, # 随机 UA,防止被认出是脚本
        'Referer': 'https://www.runoob.com/'
    }
    
    try:
        # 随机延时 1~2 秒,模仿人类点击速度
        time.sleep(random.uniform(1, 2))
        
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        
        # 菜鸟教程主要使用 UTF-8,但防止万一,自动检测一下
        response.encoding = 'utf-8'
        
        return response.text
    except Exception as e:
        print(f"💥 抓取失败 {url}: {e}")
        return None

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

这里分为两步:

  1. 解析目录(Parse Index):在首页找左边栏。
  2. 解析详情(Parse Detail):进入每个链接找简介。
python 复制代码
from bs4 import BeautifulSoup

def parse_sidebar(html):
    """提取左侧导航栏的章节列表"""
    soup = BeautifulSoup(html, 'html.parser')
    chapters = []
    
    # 菜鸟教程的左侧导航栏通常在 id="leftcolumn"
    # 里面的链接通常是 <a href="..." target="_top" ...>
    sidebar = soup.find('div', id='leftcolumn')
    
    if not sidebar:
        print("⚠️ 没找到左侧导航栏,可能页面结构变了")
        return []
    
    links = sidebar.find_all('a')
    
    for idx, link in enumerate(links, 1):
        title = link.text.strip()
        href = link['href']
        
        # 处理相对路径:有些 href 可能是 "/python3/xxx.html" 或完整链接
        if not href.startswith('http'):
            full_url = f"https://www.runoob.com{href}"
        else:
            full_url = href
            
        chapters.append({
            'id': idx,
            'title': title,
            'url': full_url
        })
        
    return chapters

def parse_content_intro(html):
    """提取详情页的第一段简介"""
    if not html: return "Network Error"
    
    soup = BeautifulSoup(html, 'html.parser')
    
    # 正文通常在 class="article-intro"
    content = soup.find('div', class_='article-intro')
    if not content:
        return "No Content Found"
    
    # 提取第一个 <p> 标签作为简介
    # 有时候第一个 p 是空的或者广告,我们找第一个有实义文本的 p
    p_tags = content.find_all('p')
    for p in p_tags:
        text = p.get_text(strip=True)
        if len(text) > 10: # 假设简介至少有10个字
            return text
            
    return "No Description"

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

python 复制代码
import pandas as pd
import os

def save_toc(data_list):
    df = pd.DataFrame(data_list)
    
    if not os.path.exists('data'):
        os.makedirs('data')
        
    filename = 'data/python3_outline.csv'
    df.to_csv(filename, index=False, encoding='utf-8-sig')
    print(f"💾 目录树已保存: {filename} (共 {len(df)} 章)")

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

这里我们将两个解析步骤串联起来。为了防止演示时间过长,你可以设置 MAX_CHAPTERS 来限制抓取的数量。

python 复制代码
def main():
    root_url = "https://www.runoob.com/python3/python3-tutorial.html"
    print("🚀 正在连接菜鸟教程首页,获取目录...")
    
    index_html = fetch_url(root_url)
    if not index_html:
        return
        
    # 1. 获取目录列表
    chapter_list = parse_sidebar(index_html)
    print(f"✅ 成功获取 {len(chapter_list)} 个章节,准备开始深入抓取简介...")
    
    # ⚠️ 演示模式:只抓前 5 章,避免给服务器造成压力
    # 如果你想抓全量,把切片去掉: chapter_list[:]
    targets = chapter_list[:5] 
    
    results = []
    
    for chapter in targets:
        print(f"📄 [{chapter['id']}] 正在抓取: {chapter['title']}")
        
        detail_html = fetch_url(chapter['url'])
        intro = parse_content_intro(detail_html)
        
        # 组装最终数据
        results.append({
            'ID': chapter['id'],
            'Chapter': chapter['title'],
            'URL': chapter['url'],
            'Intro': intro[:50] + "..." # 截断一下方便显示
        })
        
        # 这里的延时已经在 fetch_url 里做了,这里不用重复
    
    save_toc(results)

if __name__ == "__main__":
    main()

📊 运行结果预览:

text 复制代码
🚀 正在连接菜鸟教程首页,获取目录...
✅ 成功获取 98 个章节,准备开始深入抓取简介...
📄 [1] 正在抓取: Python 3 教程
📄 [2] 正在抓取: Python 3 环境搭建
📄 [3] 正在抓取: Python 3 基础语法
...
💾 目录树已保存: data/python3_outline.csv (共 5 章)

CSV 文件预览:

ID Chapter URL Intro
1 Python 3 教程 https://runoob... Python 的 3.0 版本,常被称为 Python 3000...
2 Python 3 环境搭建 https://runoob... 本章节我们将向大家介绍如何在本地搭建 Python3...
3 Python 3 基础语法 https://runoob... Python 语言与 Perl,C 和 Java 等语言有许多相似之处...

🔟 常见问题与排错(💡 经验之谈)

  1. 左侧栏抓取为空?

    • 原因 :有些教程页面(如 Java 教程)的 ID 可能叫 #leftcolumn,但有些新页面可能变了。
    • 排错 :右键"检查元素",确认导航栏的父级 div 的 ID 或 Class 是否变化。
  2. 简介抓到广告?

    • 原因 :有些网站会在正文开头放一个 <p> 标签的广告。
    • 解决 :在代码里加个判断,如果 p 标签内包含 "广告"、"推广" 字样,就 continue 跳过,找下一个 p
  3. HTTPS SSL 报错?

    • 老旧的 Python 环境可能证书过期。可以在 requests.get 里加 verify=False(不推荐,建议升级环境)。

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

  • 异步并发 (Asyncio + Aiohttp)

    • 如果要抓取几百个章节,同步模式(一个接一个)太慢了。改用 aiohttp,可以把总耗时从 10 分钟压缩到 30 秒。但请注意,这对服务器冲击很大,必须限制并发数(Semaphore)。
  • 生成 Markdown 电子书

    • 不只是抓简介,而是把整个 <div class="article-intro"> 的内容抓下来,用 html2text 库转成 Markdown,然后用 Pandoc 生成 PDF。这就变成了一个真正的"电子书爬虫"!

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

这个案例展示了**"列表-详情" (List-Detail)** 模式的标准解法。无论是爬电商商品详情,还是爬新闻网站正文,逻辑都是一样的:先拿到入口列表,再逐个击破

复盘

  • 我们利用了网页的公共组件(左侧导航栏)来快速定位所有链接。
  • 我们实现了简单的内容抽取(获取首段),这是自然语言处理(NLP)语料收集的第一步。

下一步可以做什么?

  • 挑战 MDN:MDN Web Docs (Mozilla) 的结构更复杂,且内容是动态加载的,尝试爬取 MDN 的 JavaScript 引用手册?
  • 制作 Dash 文档:把爬下来的数据制作成 Dash/Zeal 离线文档包,方便写代码时速查。

好了,你的私人知识库已经开始动工了!快去运行代码,把知识"搬"回家吧!

🌟 文末

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

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

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

专栏 👉 《Python爬虫实战》,我会按照"入门 → 进阶 → 工程化 → 项目落地"的路线持续更新,争取让每一篇都做到:

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

📣 想系统提升的小伙伴:强烈建议先订阅专栏,再按目录顺序学习,效率会高很多~

✅ 互动征集

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

评论区留言告诉我你的需求,我会优先安排更新 ✅


⭐️ 若喜欢我,就请关注我叭~(更新不迷路)

⭐️ 若对你有用,就请点赞支持一下叭~(给我一点点动力)

⭐️ 若有疑问,就请评论留言告诉我叭~(我会补坑 & 更新迭代)


免责声明:本文仅用于学习与技术研究,请在合法合规、遵守站点规则与 Robots 协议的前提下使用相关技术。严禁将技术用于任何非法用途或侵害他人权益的行为。

相关推荐
七夜zippoe2 小时前
gRPC高性能RPC框架实战:从Protocol Buffers到流式传输的完整指南
网络·python·网络协议·rpc·protocol
claem2 小时前
Mac端 Python脚本创建与理解
开发语言·python·macos
lixzest2 小时前
目标检测算法应用工程师 面试高频题 + 标准答案
python·yolo·目标检测·计算机视觉
癫狂的兔子2 小时前
【BUG】【Python】【Spider】Compound class names are not allowed.
开发语言·python·bug
木头左3 小时前
基于Backtrader框架的指数期权备兑策略实现与验证
python
李松桃3 小时前
python第三次作业
java·前端·python
m0_561359673 小时前
使用PyTorch构建你的第一个神经网络
jvm·数据库·python
马士兵教育3 小时前
计算机专业学生入行IT行业,编程语言如何选择?
java·开发语言·c++·人工智能·python