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,更推荐使用Miniconda或Anaconda来创建独立的虚拟环境,这样可以避免项目间的包版本冲突。
# 使用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)。
- 安装Selenium库:
pip install selenium==4.8.0 - 下载与你的Chrome浏览器版本匹配的 ChromeDriver ,将可执行文件放在系统PATH路径下(如Windows的
C:\Windows)或项目目录下。
对于大型或复杂的爬取任务,你可能会用到Scrapy框架。它是一个“重型武器”,适合结构化、批量化的爬取。可以先安装,但初期案例可能用不到。
pip install scrapy==2.8.02.3 开发工具与目录结构
代码编辑器推荐VSCode或PyCharm。用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解析。
典型流程:
- 发送请求:使用
requests库,设置headers(模拟浏览器),处理可能的编码问题。 - 解析内容:用
BeautifulSoup加载获取的HTML文本,选择lxml解析器。 - 数据提取:使用
soup.select()或soup.find_all()方法,通过CSS选择器或标签名定位元素。 - 数据保存:将提取的列表数据,用
csv.writer或pandas.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(网络)选项卡,刷新页面,筛选XHR或Fetch类型的请求。你会发现很多返回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)。
步骤:
- 分析登录请求:同样用开发者工具的Network面板,找到登录时提交的POST请求。查看它提交的
Form Data或Payload,以及必要的Headers(如Content-Type)。 - 使用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) - 处理验证码:简单验证码可以用OCR库(如
ddddocr、tesseract)尝试识别,复杂的可能需要人工干预或使用打码平台。这是一个单独的课题,初期案例可能不涉及。
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 高频错误与排查清单
当你运行案例代码出错时,按这个顺序排查:
依赖包未安装或版本不对
- 现象:
ModuleNotFoundError: No module named ‘xxx‘ - 解决:在激活的虚拟环境中,用
pip list检查是否安装。用pip install xxx==版本号重新安装。
- 现象:
网络请求失败
- 现象:
ConnectionError,Timeout,SSLError或返回状态码403、404、429。 - 排查:
- 检查URL是否正确(复制到浏览器试试)。
- 检查
headers是否设置,特别是User-Agent。 - 403可能是被网站屏蔽,尝试增加
headers信息或使用代理(需谨慎合法使用)。 - 429是请求过于频繁,必须增加延时
time.sleep()。 - 检查网络连接和代理设置。
- 现象:
数据解析失败
- 现象:
AttributeError: ‘NoneType‘ object has no attribute ‘text‘或提取到的列表为空。 - 排查:
- 打印响应内容:
print(response.text[:500])看看是否真的拿到了预期的HTML。 - 检查选择器:用浏览器开发者工具的
Elements面板,检查你用的CSS选择器路径是否能唯一定位到目标元素。网页结构可能已更新。 - 动态内容问题:如果网页是JS渲染的,
requests获取的源码里没有数据,需要改用Selenium或查找Ajax接口。
- 打印响应内容:
- 现象:
文件或数据库写入错误
- 现象:
PermissionError或OperationalError。 - 排查:
- 检查文件路径或数据库文件是否有写入权限。
- 检查数据库连接是否已关闭后再执行新操作。
- 确保写入前,目录已经存在(
os.makedirs(‘data‘, exist_ok=True))。
- 现象:
编码与乱码
- 现象:保存的文件用记事本打开乱码,或控制台打印中文乱码。
- 解决:
- 保存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 -*-。
- 保存CSV/JSON时,指定编码为
5. 从模仿到创造:如何利用案例源码提升自己
拿到18个案例源码,最高效的学习方式不是“运行一遍就过”,而是“修改、调试、移植”。
逐行精读与注释:对于每个案例,先确保能运行成功。然后,给每一行关键代码加上你自己的中文注释,理解其用意。尝试修改其中的参数,比如请求头、解析路径、等待时间,观察结果变化。
更换目标网站练习:找一个与案例同类型的网站(比如案例是爬取新闻标题,你就另找一个新闻网站),尝试用相同的技术思路(requests+bs4)去抓取。这个过程会强迫你独立完成“分析页面结构-编写选择器-调试”的全过程,这是能力提升的关键一步。
功能整合与扩展:将不同案例的技术点组合。例如,把案例A的“模拟登录”和案例B的“数据存数据库”结合起来,去爬取一个需要登录才能查看的列表页,并把结果存入SQLite。
构建简单项目:设定一个综合目标,如“监控某个商品的价格变化”。这需要你定时运行爬虫(可以用计划任务
crontab或schedule库)、对比历史数据、甚至设置报警(发送邮件)。一个小项目能串联起爬取、解析、存储、调度多个环节。阅读优秀源码:在GitHub上搜索
scrapy、crawler等关键词,看看成熟的开源爬虫项目是怎么组织代码、处理异常、管理配置的。这能帮你从脚本思维过渡到工程思维。
最后,记住爬虫是工具,核心是数据获取。随着你技能提升,重点会从“如何爬下来”转向“数据有什么价值”以及“如何分析利用”。这18个案例是你起点,真正的学习发生在你关闭源码,面对一个全新网站并开始自己思考如何抓取的那一刻。从模仿开始,以解决自己的实际问题为目标,每一步都动手去试、去错、去改,这才是最有效的学习路径。
