三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Python爬虫18个实战案例:从环境搭建到数据存储完整指南

Python爬虫18个实战案例:从环境搭建到数据存储完整指南

1. 先搞清楚这18个案例到底能帮你解决什么问题

如果你刚接触Python爬虫,或者已经看过一些理论但一动手就报错,那这18个带源码的实战案例,最直接的价值就是让你能对照着跑起来,知道一个爬虫从启动到拿到数据,中间每一步具体在做什么。它解决的痛点很明确:理论看懂了,但自己写不出代码;代码能跑了,但一换网站就报错;数据抓到了,但不知道怎么存、怎么洗。

这18个案例不是简单的“Hello World”,而是覆盖了从静态网页、动态加载(Ajax/JS)、模拟登录、反爬应对到数据存储的常见场景。学完之后,你至少能独立完成:从目标网站分析、请求发送、数据解析到结果保存的完整流程。对于小白来说,最关键的不是追求高难度的反爬技巧,而是先建立一套稳定、可复现的爬取流程,这18个案例就是帮你搭建这个流程的脚手架。

我建议你先别急着把所有案例的源码都下载下来。更有效的方法是:先通读一遍案例目录,了解每个案例针对什么类型的网站(如电商、新闻、社交、视频平台),用了什么核心库(requests, BeautifulSoup, Selenium, Scrapy等),以及输出是什么格式(CSV, JSON, 数据库)。这样你就能快速定位到当前你最需要解决的那类问题对应的案例。

2. 环境准备:别在第一步就卡住

在跑任何案例之前,一个干净、可用的Python环境是前提。很多新手的问题都出在环境配置上,比如包冲突、路径不对、依赖缺失。

2.1 Python解释器与包管理

首先,确保你安装的是Python 3.7或以上版本。不建议使用系统自带的Python,更推荐使用MinicondaAnaconda来创建独立的虚拟环境,这样可以避免项目间的包版本冲突。

# 使用conda创建名为spider_env的虚拟环境,指定Python版本 conda create -n spider_env python=3.9 # 激活环境 conda activate spider_env

如果你不用conda,也可以用Python自带的venv

# 在当前目录创建虚拟环境文件夹 python -m venv spider_venv # 激活环境 (Windows) spider_venv\Scripts\activate # 激活环境 (macOS/Linux) source spider_venv/bin/activate

激活环境后,命令行提示符前会出现环境名,如(spider_env),这表示你后续的所有操作都在这个独立环境中。

2.2 核心库安装

爬虫案例最常涉及的几个库,建议一次性安装好基础版本:

pip install requests==2.28.1 beautifulsoup4==4.11.1 lxml==4.9.1
  • requests: 用于发送HTTP请求,获取网页原始内容。这是爬虫的“手”。
  • beautifulsoup4 (bs4): 用于解析HTML/XML文档,提取结构化数据。这是爬虫的“眼睛”。
  • lxml: 是bs4的一个解析器后端,速度比Python内置的html.parser快,通常作为bs4的搭档安装。

对于动态渲染的网站(页面内容由JavaScript加载),你需要Selenium。它的安装稍复杂,需要对应浏览器的驱动(如ChromeDriver)。

  1. 安装Selenium库:
    pip install selenium==4.8.0
  2. 下载与你的Chrome浏览器版本匹配的 ChromeDriver ,将可执行文件放在系统PATH路径下(如Windows的C:\Windows)或项目目录下。

对于大型或复杂的爬取任务,你可能会用到Scrapy框架。它是一个“重型武器”,适合结构化、批量化的爬取。可以先安装,但初期案例可能用不到。

pip install scrapy==2.8.0

2.3 开发工具与目录结构

代码编辑器推荐VSCodePyCharm。用VSCode的话,记得安装Python扩展,并配置选择刚才创建的虚拟环境作为解释器。

建立一个清晰的项目目录,例如:

python_spider_cases/ ├── case_01_xxx/ # 案例1文件夹 │ ├── spider.py # 爬虫主代码 │ └── data/ # 存放爬取的数据 ├── case_02_xxx/ ├── requirements.txt # 统一管理依赖包 └── README.md

在每个案例文件夹里单独运行代码,避免相互干扰。

3. 从静态到动态:案例实战拆解与避坑

拿到18个案例源码后,不要按顺序硬啃。我建议按技术难度和网站类型分组学习,遵循“静态 -> 简单动态 -> 复杂动态(含登录)”的路径。

3.1 静态网页抓取(基础中的基础)

这类案例通常针对新闻门户、博客、论坛等直接返回完整HTML的网站。核心是requests.get()+BeautifulSoup解析

典型流程:

  1. 发送请求:使用requests库,设置headers(模拟浏览器),处理可能的编码问题。
  2. 解析内容:用BeautifulSoup加载获取的HTML文本,选择lxml解析器。
  3. 数据提取:使用soup.select()soup.find_all()方法,通过CSS选择器或标签名定位元素。
  4. 数据保存:将提取的列表数据,用csv.writerpandas.to_csv保存为CSV文件,或用json.dump保存为JSON。

避坑点:

  • 请求头(Headers):很多网站会检查User-Agent。不加的话可能被拒绝或返回异常页面。最少要加上:
    headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...' } response = requests.get(url, headers=headers)
  • 编码问题:如果打印出的网页内容乱码,不要盲目用utf-8解码。先看response.encoding,或者通过response.apparent_encoding让requests自动判断,再设置response.encoding = ‘xxx‘
  • 解析器选择lxml解析速度快,但需要额外安装C库(前面已装)。如果环境受限,可以用Python内置的html.parser,但处理复杂HTML时可能不如lxml稳定。
  • 网络异常处理:一定要用try-except包裹请求代码,捕获requests.exceptions.RequestException异常,并设置合理的timeout参数,避免程序因网络问题无限挂起。
    try: response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() # 如果状态码不是200,抛出HTTPError异常 except requests.exceptions.RequestException as e: print(f“请求失败: {e}“) return None

3.2 动态内容抓取(Ajax/JS渲染)

现在很多网站(如电商商品列表、社交媒体瀑布流)的数据是通过JavaScript异步加载的。直接requests.get()拿到的HTML是空的容器,看不到数据。这时有两条路:

方案一:直接找Ajax接口(推荐)这是最高效的方法。打开浏览器的开发者工具(F12),切换到Network(网络)选项卡,刷新页面,筛选XHRFetch类型的请求。你会发现很多返回JSON数据的请求,这些就是Ajax接口。直接模拟这些接口的请求(URL、参数、Headers,有时包括Cookies),就能拿到结构化数据,连HTML解析都省了。

方案二:使用Selenium模拟浏览器当数据接口被混淆、参数复杂难以模拟时,就用Selenium。它真正控制一个浏览器去加载页面,等JS执行完毕后再获取完整的页面源代码。

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome() # 确保chromedriver在PATH中 driver.get(url) # 等待某个关键元素加载出来 try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, “.product-list“)) ) # 获取渲染后的页面源码 page_source = driver.page_source # 然后用BeautifulSoup解析page_source finally: driver.quit() # 一定要关闭浏览器,释放资源

Selenium避坑点:

  • 驱动匹配:ChromeDriver版本必须与已安装的Chrome浏览器主版本号完全匹配。
  • 隐式/显式等待:不要用time.sleep(固定时间),效率低且不稳定。学会用WebDriverWait配合expected_conditions进行显式等待。
  • 资源消耗:每个Selenium实例都是一个完整的浏览器进程,非常消耗内存和CPU。不适合大规模并发爬取。

3.3 需要登录的网站抓取

爬取个人中心、订单列表等页面,必须先登录。核心是维持会话(Session)

步骤:

  1. 分析登录请求:同样用开发者工具的Network面板,找到登录时提交的POST请求。查看它提交的Form DataPayload,以及必要的Headers(如Content-Type)。
  2. 使用Session对象requests.Session()会自动处理Cookies,在后续请求中保持登录状态。
    session = requests.Session() login_data = { ‘username‘: ‘your_username‘, ‘password‘: ‘your_password‘, ‘csrf_token‘: ‘...‘ # 经常需要从登录页HTML中先提取一个token } # 先GET登录页,可能为了获取token或初始化cookies login_page = session.get(login_url) # 提交登录请求 login_response = session.post(login_url, data=login_data) # 登录成功后,用同一个session访问需要认证的页面 profile_page = session.get(profile_url)
  3. 处理验证码:简单验证码可以用OCR库(如ddddocrtesseract)尝试识别,复杂的可能需要人工干预或使用打码平台。这是一个单独的课题,初期案例可能不涉及。

4. 数据存储、伦理边界与常见错误排查

爬虫不只是“抓”,还要“存”和“管”。更要清楚什么能爬,什么不能爬。

4.1 数据存储选择

根据数据量和后续用途选择:

  • CSV文件:适合表格型数据,简单直观,可以用Excel打开。使用csv模块或pandas
  • JSON文件:适合嵌套的、结构化的数据(如从API接口直接返回的数据)。使用json模块。
  • 数据库(SQLite/MySQL/MongoDB):适合数据量大、需要频繁查询或关联的数据。SQLite无需安装服务器,是轻量级首选。
    import sqlite3 conn = sqlite3.connect(‘spider_data.db‘) cursor = conn.cursor() cursor.execute(‘‘‘CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, title TEXT, url TEXT)‘‘‘) cursor.execute(“INSERT INTO articles (title, url) VALUES (?, ?)“, (title, url)) conn.commit() conn.close()

4.2 遵守Robots协议与法律法规

这是最重要的红线。

  • 查看Robots.txt:在网站域名后加上/robots.txt(如https://www.example.com/robots.txt),查看该网站允许或禁止爬虫抓取的目录。务必尊重这些规则
  • 控制访问频率:在循环请求中增加time.sleep(random.uniform(1, 3)),模拟人类浏览间隔,减轻服务器压力。这是最基本的道德和技术要求。
  • 识别公开数据与个人隐私:只爬取网站公开显示的信息,切勿尝试破解、入侵获取非公开数据,绝对不要抓取和保存用户的个人敏感信息(如身份证号、电话号码、详细住址)。
  • 版权与用途:注意数据的版权归属,爬取的数据仅用于个人学习、研究或公益目的,切勿用于商业牟利或损害他人权益的活动。

4.3 高频错误与排查清单

当你运行案例代码出错时,按这个顺序排查:

  1. 依赖包未安装或版本不对

    • 现象ModuleNotFoundError: No module named ‘xxx‘
    • 解决:在激活的虚拟环境中,用pip list检查是否安装。用pip install xxx==版本号重新安装。
  2. 网络请求失败

    • 现象ConnectionError,Timeout,SSLError或返回状态码403404429
    • 排查
      • 检查URL是否正确(复制到浏览器试试)。
      • 检查headers是否设置,特别是User-Agent
      • 403可能是被网站屏蔽,尝试增加headers信息或使用代理(需谨慎合法使用)。
      • 429是请求过于频繁,必须增加延时time.sleep()
      • 检查网络连接和代理设置。
  3. 数据解析失败

    • 现象AttributeError: ‘NoneType‘ object has no attribute ‘text‘或提取到的列表为空。
    • 排查
      • 打印响应内容print(response.text[:500])看看是否真的拿到了预期的HTML。
      • 检查选择器:用浏览器开发者工具的Elements面板,检查你用的CSS选择器路径是否能唯一定位到目标元素。网页结构可能已更新。
      • 动态内容问题:如果网页是JS渲染的,requests获取的源码里没有数据,需要改用Selenium或查找Ajax接口。
  4. 文件或数据库写入错误

    • 现象PermissionErrorOperationalError
    • 排查
      • 检查文件路径或数据库文件是否有写入权限。
      • 检查数据库连接是否已关闭后再执行新操作。
      • 确保写入前,目录已经存在(os.makedirs(‘data‘, exist_ok=True))。
  5. 编码与乱码

    • 现象:保存的文件用记事本打开乱码,或控制台打印中文乱码。
    • 解决
      • 保存CSV/JSON时,指定编码为utf-8-sig(适合Excel打开)。
      with open(‘data.csv‘, ‘w‘, newline=‘‘, encoding=‘utf-8-sig‘) as f: writer = csv.writer(f)
      • 在代码文件开头加# -*- coding: utf-8 -*-

5. 从模仿到创造:如何利用案例源码提升自己

拿到18个案例源码,最高效的学习方式不是“运行一遍就过”,而是“修改、调试、移植”。

  1. 逐行精读与注释:对于每个案例,先确保能运行成功。然后,给每一行关键代码加上你自己的中文注释,理解其用意。尝试修改其中的参数,比如请求头、解析路径、等待时间,观察结果变化。

  2. 更换目标网站练习:找一个与案例同类型的网站(比如案例是爬取新闻标题,你就另找一个新闻网站),尝试用相同的技术思路(requests+bs4)去抓取。这个过程会强迫你独立完成“分析页面结构-编写选择器-调试”的全过程,这是能力提升的关键一步。

  3. 功能整合与扩展:将不同案例的技术点组合。例如,把案例A的“模拟登录”和案例B的“数据存数据库”结合起来,去爬取一个需要登录才能查看的列表页,并把结果存入SQLite。

  4. 构建简单项目:设定一个综合目标,如“监控某个商品的价格变化”。这需要你定时运行爬虫(可以用计划任务crontabschedule库)、对比历史数据、甚至设置报警(发送邮件)。一个小项目能串联起爬取、解析、存储、调度多个环节。

  5. 阅读优秀源码:在GitHub上搜索scrapycrawler等关键词,看看成熟的开源爬虫项目是怎么组织代码、处理异常、管理配置的。这能帮你从脚本思维过渡到工程思维。

最后,记住爬虫是工具,核心是数据获取。随着你技能提升,重点会从“如何爬下来”转向“数据有什么价值”以及“如何分析利用”。这18个案例是你起点,真正的学习发生在你关闭源码,面对一个全新网站并开始自己思考如何抓取的那一刻。从模仿开始,以解决自己的实际问题为目标,每一步都动手去试、去错、去改,这才是最有效的学习路径。

← 返回列表