当前位置: 首页 > news >正文

Python爬虫入门实战:18个案例掌握HTTP请求、数据解析与存储

大家好,我是你们的技术博主。今天这篇文章想和大家聊一聊 Python 爬虫入门实战。网上关于 Python 爬虫的教程非常多,但大多只讲爬虫库的用法,或者直接丢出几个大网站的抓取案例就不管了,新手照着写,没过几天就被反爬机制拦截,不仅练不了手,还容易丧失信心。

本文会换一种思路:不追求“抓取某个大平台”,而是把爬虫开发中最常用、最核心的 18 个真实场景拆解成独立案例。每个案例都配套完整源码,覆盖请求、解析、数据提取、数据清洗、数据存储、异常处理、翻页、会话保持、定时调度等知识点。你只要把每个案例跑通,就等于把爬虫开发的整个知识体系打了一遍。

本文适合以下读者:

  • 刚学完 Python 基础语法,想了解爬虫怎么入门的同学;
  • 有一定 Python 基础,但觉得“网上爬虫教程不够系统”的同学;
  • 想用 Python 自动化获取公开数据、练习数据采集技能的开发者。

文章内容偏实操,不做过多的底层原理挖掘,但会解释每个关键步骤的语义,让你不仅会写代码,还知道为什么要这样写。

1. 认识 Python 爬虫

1.1 什么是爬虫

爬虫(Web Crawler)从广义上讲,是“按照一定规则,自动请求互联网上的资源,并从响应结果中提取所需数据的程序”。它本质上就是一段自动化代码,模拟浏览器向服务器发送 HTTP 请求,再对服务器返回的 HTML、JSON 等数据做解析。

用通俗的例子解释:你打开浏览器访问新闻网站,看到网页上的标题、正文、日期,这个过程可以理解成“手动爬取”。爬虫程序就是把这些手工操作自动化:

  • 浏览器地址栏输入网址 → 程序用代码请求 URL;
  • 浏览器渲染出页面 → 程序把返回内容解析成字符串或 JSON;
  • 人用眼睛找标题 → 程序用解析库、正则表达式按规则提取;
  • 人复制粘贴到本地 → 程序自动写入 CSV、Excel 或数据库。

1.2 爬虫的应用场景

爬虫的能力放在真实业务里,常见应用场景有:

  1. 搜索引擎:搜索引擎本身就是大型爬虫系统,不断抓取网页并建立索引。
  2. 数据分析与行业调研:抓取招聘网站的岗位要求、电商平台的商品价格、天气数据、公开论文元数据等进行趋势分析。
  3. 舆情监控与新闻聚合:采集新闻网站、论坛的公开内容,做一些关键词统计。
  4. 自动化测试:模拟用户在网站上的请求行为,配合接口测试框架使用。
  5. 个人数据备份:将自己在某个平台公开过的内容批量下载到本地收藏。

需要注意的是,爬虫本身只是一个技术工具。工具没有原罪,关键取决于使用方式。你在学习阶段,最好优先选择公开接口、官方 API、以及允许抓取的练习页面,不要一上来就去爬那种有明显反爬策略的电商平台或社交平台,更不要用爬虫获取非公开数据,也不要对目标站点造成压力。

1.3 本文的 18 个案例设计逻辑

这 18 个案例,我会按照爬虫开发流程从易到难安排:

阶段案例编号学习目标
请求基础案例 1-4学会用 urllib、requests 发起 HTTP 请求
页面解析案例 5-7学会 BeautifulSoup、XPath、正则提取数据
场景进阶案例 8-12学会翻页、图片下载、请求头和 Session 处理
数据持久化案例 13-16学会保存到 CSV、Excel、SQLite,断点续爬
工程化与稳定性案例 17-18学会异常处理、超时重试、定时调度

每节代码都尽量保证精简、可独立运行,并标注文件路径。你可以新建一个python_spider_practice文件夹,把每个案例保存为单独的.py文件。

2. 环境准备

在开始写代码之前,先检查一下本机环境。下面这些工具是运行本文案例需要准备的:

2.1 Python 环境

  • Python 3.8 及以上版本(建议使用 3.10 或 3.11,较新的版本对类型注解和异步支持更好)。
  • 安装方式:Windows 用户到 Python 官网下载安装包,勾选“Add Python to PATH”;macOS/Linux 用户可以使用系统自带的 Python 3,也可以使用 Homebrew 或 apt 安装。

检查方式:

python --version # 或者 python3 --version

如果命令提示找不到 Python,请检查环境变量。

2.2 第三方爬虫库

本文主要使用以下第三方库:

库名用途
requests最常用的 HTTP 请求库,API 简洁
beautifulsoup4解析 HTML 文档,提供便捷的节点搜索方式
lxml高性能解析器,配合 XPath 使用
openpyxl写入 Excel 文件
APScheduler定时任务调度(作为可选扩展)

安装命令:

pip install requests beautifulsoup4 lxml openpyxl APScheduler

如果你的环境是 Python 3.10 以下,且安装 lxml 时遇到编译错误,请先升级 pip:

pip install --upgrade pip

2.3 IDE 建议

推荐使用 VS Code 或者 PyCharm。如果你是新手,VS Code 轻量,配置 Python 插件后就能直接调试,比较方便。如果使用 PyCharm,建议选择 Community 版本即可。

3. 第一组案例:HTTP 请求基础

看过爬虫源码的同学都知道,爬虫的第一步是向服务器发出请求。本组 4 个案例会帮你建立 HTTP 请求的基本认知。

3.1 案例 1:用 urllib 请求网页并获取标题

为什么要先学 urllib?因为它是 Python 标准库自带的模块,不需要安装任何第三方依赖,适合理解 HTTP 请求的过程。

# 文件路径:python_spider_practice/case01_urllib_title.py import urllib.request url = "https://www.example.com" # 1. 发起 GET 请求 response = urllib.request.urlopen(url, timeout=5) # 2. 读取响应内容 html = response.read().decode("utf-8") # 3. 用字符串查找的方式粗略提取 title 标签内容 start = html.find("<title>") + len("<title>") end = html.find("</title>") title = html[start:end] print("页面标题:", title)

代码说明:

  • urlopen是 urllib 内置的请求方法,返回一个类文件对象;
  • read()读取二进制内容,使用decode("utf-8")转成字符串;
  • find方法定位<title>标签的位置,这种方式虽然不够优雅,但能很好说明“解析”的本质。

3.2 案例 2:requests 发起 GET 请求

相比 urllib,requests 的代码更简洁,也是大多数 Python 爬虫的标配。下面请求一个公共 JSON 占位接口,这是学习数据抓取时很常用的练习接口,返回的是模拟数据,不涉及敏感信息。

# 文件路径:python_spider_practice/case02_requests_get.py import requests url = "https://jsonplaceholder.typicode.com/posts/1" response = requests.get(url, timeout=5) print("HTTP 状态码:", response.status_code) print("响应文本:", response.text) print("JSON 数据:", response.json())

代码说明:

  • response.status_code表示 HTTP 状态码,200 表示成功,404 表示资源不存在;
  • response.json()会把 JSON 字符串自动转成 Python 字典。

运行输出大致如下:

HTTP 状态码: 200 响应文本: { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit ..." } JSON 数据: {'userId': 1, 'id': 1, 'title': '...', 'body': '...'}

3.3 案例 3:requests 发送 POST 表单请求

很多网页的搜索功能,本质是向服务器提交一个表单。requests 发送表单数据,只需要提供一个字典给data参数。

# 文件路径:python_spider_practice/case03_requests_post.py import requests # 注意:以下示例用的是公开测试地址,实际开发中请替换为真实的表单提交接口 url = "https://httpbin.org/post" form_data = { "username": "test_user", "keyword": "python 爬虫" } response = requests.post(url, data=form_data, timeout=5) print("状态码:", response.status_code) print("返回内容:", response.text)

httpbin.org 是一个常用于调试 HTTP 请求的公开测试服务,它能原样返回你提交的数据,非常适合学习时验证请求是否正确。

3.4 案例 4:抓取公开 JSON 接口并解析

很多时候,服务器返回的不是 HTML,而是 JSON 数据。比如 GitHub 的公开搜索 API、天气公开接口、RSS 服务等。这类数据是结构化数据,解析起来更方便。

# 文件路径:python_spider_practice/case04_json_api.py import requests # 使用 GitHub 公开搜索 API:搜索 Python 语言中 star 数较高的仓库 url = "https://api.github.com/search/repositories" params = { "q": "language:python", "sort": "stars", "order": "desc", "per_page": 5 } headers = { "Accept": "application/vnd.github+json", "User-Agent": "Mozilla/5.0 (Python Spider Learning)" } response = requests.get(url, params=params, headers=headers, timeout=10) # 判断请求是否成功,GitHub API 有请求频率限制 if response.status_code == 200: data = response.json() print("返回仓库数量:", data.get("total_count")) for item in data.get("items", []): print(item.get("full_name"), "Stars:", item.get("stargazers_count")) else: print("请求失败,状态码:", response.status_code) print("响应内容:", response.text)

代码说明:

  • params参数会自动把字典拼接到 URL 的查询字符串中;
  • GitHub 官方 API 要求请求头携带User-Agent,否则可能返回 403;
  • response.json()把 JSON 转成 Python 字典,再通过get方法安全读取字段。

4. 第二组案例:从 HTML 中提取数据

第一组案例演示了怎么把数据“拿回来”,接下来要解决的是“怎么把想要的内容从 HTML 中挑出来”。

4.1 案例 5:BeautifulSoup 解析标题和所有链接

BeautifulSoup 是很流行的 HTML 解析库,它把 HTML 文档转换成一棵节点树,通过标签名、class、id 等属性定位元素。

# 文件路径:python_spider_practice/case05_bs4_parse.py import requests from bs4 import BeautifulSoup url = "https://www.example.com" response = requests.get(url, timeout=5) response.encoding = "utf-8" soup = BeautifulSoup(response.text, "html.parser") # 1. 获取页面标题 print("标题:", soup.title.string) # 2. 获取页面中所有 a 标签的 href 链接 links = soup.find_all("a") for link in links[:10]: # 只打印前 10 个,避免输出过长 href = link.get("href") text = link.get_text(strip=True) print("链接文本:", text, "| 链接地址:", href)

代码说明:

  • BeautifulSoup(response.text, "html.parser")表示用 Python 内置的解析器解析文档;
  • soup.find_all("a")返回所有<a>标签的列表;
  • link.get("href")获取属性值;如果属性不存在,返回None

在实际项目中,更常用的是lxml解析器,速度更快:

soup = BeautifulSoup(response.text, "lxml")

4.2 案例 6:使用 lxml + XPath 精准提取

XPath 是一种在 XML/HTML 文档中查找信息的路径表达式语言。它比 BeautifulSoup 的选择器更适合复杂层级定位。

# 文件路径:python_spider_practice/case06_xpath_parse.py import requests from lxml import html url = "https://example.com" response = requests.get(url, timeout=5) response.encoding = "utf-8" tree = html.fromstring(response.text) # 提取页面标题 title = tree.xpath("//title/text()") print("标题:", title[0] if title else "未找到标题") # 提取所有链接 links = tree.xpath("//a/@href") for link in links[:10]: print(link)

XPath 常用语法:

  • //title:在文档任意位置找title节点;
  • /text():获取节点文本;
  • //a/@href:获取所有a节点的href属性;
  • //div[@class="content"]//p:找到 class 为 content 的 div 下所有 p 标签。

4.3 案例 7:正则表达式提取特定内容

正则表达式适合提取有明显规则特征的文本。比如邮箱地址、手机号、日期等。这里先声明:示例数据来自我们自造的演示文本,不涉及任何真实个人信息。

# 文件路径:python_spider_practice/case07_regex_extract.py import re demo_text = """ 联系邮箱:contact@example.com,备用邮箱:support@test.org。 产品上线日期:2025-06-18,版本号:v2.3.1。 """ # 1. 提取邮箱 email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" emails = re.findall(email_pattern, demo_text) print("邮箱列表:", emails) # 2. 提取日期 date_pattern = r"\d{4}-\d{2}-\d{2}" dates = re.findall(date_pattern, demo_text) print("日期列表:", dates) # 3. 提取版本号 version_pattern = r"v\d+\.\d+\.\d+" versions = re.findall(version_pattern, demo_text) print("版本列表:", versions)

在真实爬虫中,正则可以配合 BeautifulSoup 一起使用:先用解析库定位到某个区域,再用正则从该区域的文本中提取字段。

5. 第三组案例:进阶采集场景

本组案例开始接触真实开发中更常见的场景:翻页、下载文件、处理 Cookie 和 Session。

5.1 案例 8:翻页采集列表数据

很多网站的数据都分页展示。翻页采集的核心,是找到翻页时 URL 变化的规律,或者 POST 参数中页码字段的变化规律。

下面用一个模拟的分页请求例子来讲:

# 文件路径:python_spider_practice/case08_pagination.py import requests # 这是一个演示性质的公共接口,每页返回 10 条数据 base_url = "https://jsonplaceholder.typicode.com/posts" page_size = 10 total_pages = 3 for page in range(1, total_pages + 1): params = { "_page": page, "_limit": page_size } response = requests.get(base_url, params=params, timeout=5) data = response.json() print(f"第 {page} 页,获取 {len(data)} 条数据") # 这里可以继续做数据清洗、入库等操作

代码说明:

  • 这里用的公共接口,_page_limit是分页参数;
  • 在电商、招聘等场景,分页参数名称可能是pagepageNumoffset等,需要根据实际情况调整。

5.2 案例 9:批量下载图片

图片下载从本质上说,就是把服务器返回的二进制内容写入本地文件。

# 文件路径:python_spider_practice/case09_download_images.py import requests from pathlib import Path # 这里使用两张占位图片链接,方便演示;实际项目中请替换为合法的图片地址 image_urls = [ "https://www.example.com/images/demo1.jpg", "https://www.example.com/images/demo2.jpg" ] save_dir = Path("images") save_dir.mkdir(exist_ok=True) for index, image_url in enumerate(image_urls, start=1): response = requests.get(image_url, timeout=10) if response.status_code == 200: # 根据 URL 后缀推断文件扩展名 suffix = Path(image_url).suffix or ".jpg" file_name = f"image_{index}{suffix}" file_path = save_dir / file_name # 以二进制模式写入文件 file_path.write_bytes(response.content) print("已下载:", file_path)

代码说明:

  • response.content返回二进制内容,适合图片、文件下载;
  • 使用pathlib处理路径比字符串拼接更安全;
  • mkdir(exist_ok=True)确保目录存在,重复运行不会报错。

5.3 案例 10:模拟请求头,提升请求兼容性

很多服务器会检查请求头User-Agent,如果发现请求来自陌生程序,可能直接拒绝或限制访问。模拟常见的浏览器请求头,是爬虫开发中最基本的操作。

# 文件路径:python_spider_practice/case10_headers.py import requests url = "https://httpbin.org/headers" 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", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9" } response = requests.get(url, headers=headers, timeout=5) print(response.text)

代码说明:

  • User-Agent是当前浏览器环境的标识;
  • 设置Accept表示希望服务器返回什么类型的资源;
  • 在爬虫开发中,建议不要把请求头伪装得过于“假”,更不要伪造身份信息去绕过平台限制。

5.4 案例 11:使用 Session 维持会话状态

有些网站需要先登录才能访问目标页面。登录后的身份凭证通常保存在 Cookie 中。requests 的Session对象可以自动保存 Cookie,并对后续请求持续生效。

下面的例子用公开的 httpbin cookies 接口演示 Session 行为:

# 文件路径:python_spider_practice/case11_session.py import requests # 创建 Session 对象 session = requests.Session() # 第一步:访问设置 Cookie 的接口 set_cookie_url = "https://httpbin.org/cookies/set/username/spider_learner" session.get(set_cookie_url, timeout=5) # 第二步:访问获取 Cookie 的接口,验证 Session 中是否保存了 Cookie get_cookie_url = "https://httpbin.org/cookies" response = session.get(get_cookie_url, timeout=5) print("Session 中保存的 Cookie:", response.json())

代码说明:

  • session.get()会保存服务器通过Set-Cookie方式下发的 Cookie;
  • 后续同一个 Session 发起请求时会自动携带这些 Cookie;
  • 在真实项目中,登录通常需要构造 POST 请求,把用户名、密码发给登录接口,成功后 Session 就自动保持登录状态。

5.5 案例 12:处理超时与异常

网络请求大概率会遇到超时、DNS 解析失败、连接被重置等情况。如果不做异常处理,爬虫很可能运行到一半就崩溃退出。

# 文件路径:python_spider_practice/case12_timeout_retry.py import time import requests from requests.exceptions import RequestException def fetch_with_retry(url, max_retries=3, timeout=5): for attempt in range(1, max_retries + 1): try: response = requests.get(url, timeout=timeout) response.raise_for_status() # 状态码不是 2xx 时抛出异常 return response except RequestException as e: print(f"第 {attempt} 次请求失败:{e}") if attempt < max_retries: wait_time = 2 ** attempt # 指数退避 print(f"等待 {wait_time} 秒后重试...") time.sleep(wait_time) return None url = "https://httpbin.org/delay/3" response = fetch_with_retry(url, timeout=2) if response: print("请求成功") else: print("重试多次后仍然失败")

代码说明:

  • timeout=2表示连接和读取的等待时间;
  • raise_for_status()会在返回 4xx、5xx 时主动抛异常;
  • 重试使用指数退避策略,避免在服务端异常时加剧压力。

6. 第四组案例:数据持久化

爬虫抓回来的数据,最终要落地存储。这里介绍三种最常见的方式:CSV、Excel、SQLite。

6.1 案例 13:保存数据到 CSV 文件

CSV 是最通用的表格格式,Excel、数据库工具都能打开。

# 文件路径:python_spider_practice/case13_save_csv.py import csv # 模拟爬取到的数据 data_list = [ {"title": "Python 爬虫入门", "author": "小明", "views": 1200}, {"title": "requests 库实战", "author": "小红", "views": 890}, {"title": "BeautifulSoup 解析技巧", "author": "小刚", "views": 1560}, ] with open("articles.csv", "w", encoding="utf-8", newline="") as f: fieldnames = ["title", "author", "views"] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerows(data_list) print("CSV 文件保存成功")

注意:写入 CSV 时指定encoding="utf-8"可以确保中文不乱码。部分旧版 Excel 打开 UTF-8 CSV 会乱码,如果你要兼容旧版 Excel,可以改成utf-8-sig

6.2 案例 14:保存数据到 Excel 文件

Excel 文件更适合做数据分析和展示。openpyxl 库支持 xlsx 格式的写入。

# 文件路径:python_spider_practice/case14_save_excel.py from openpyxl import Workbook wb = Workbook() ws = wb.active ws.title = "爬虫数据" # 表头 ws.append(["标题", "作者", "阅读量"]) # 数据行 data_list = [ ["Python 爬虫入门", "小明", 1200], ["requests 库实战", "小红", 890], ["BeautifulSoup 解析技巧", "小刚", 1560], ] for row in data_list: ws.append(row) wb.save("articles.xlsx") print("Excel 文件保存成功")

如果你要处理大量数据,可以使用write_only=True模式减少内存占用:

from openpyxl import Workbook wb = Workbook(write_only=True) ws = wb.create_sheet(title="爬虫数据") ws.append(["标题", "作者", "阅读量"]) # 循环中写入数据... wb.save("articles_large.xlsx")

6.3 案例 15:保存数据到 SQLite 数据库

SQLite 是轻量级数据库,无需安装服务端,非常适合爬虫阶段的本地存储。

# 文件路径:python_spider_practice/case15_save_sqlite.py import sqlite3 # 连接数据库,如果文件不存在会自动创建 conn = sqlite3.connect("articles.db") cursor = conn.cursor() # 创建表 cursor.execute(""" CREATE TABLE IF NOT EXISTS articles ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, author TEXT, views INTEGER ) """) # 模拟数据 data_list = [ ("Python 爬虫入门", "小明", 1200), ("requests 库实战", "小红", 890), ("BeautifulSoup 解析技巧", "小刚", 1560), ] cursor.executemany( "INSERT INTO articles (title, author, views) VALUES (?, ?, ?)", data_list ) conn.commit() # 查询数据 cursor.execute("SELECT * FROM articles") rows = cursor.fetchall() for row in rows: print(row) conn.close()

代码说明:

  • 使用?占位符来传参,可以有效防止 SQL 注入,这是数据库操作的标准做法;
  • executemany批量插入多条记录,性能比逐条插入更好;
  • 对爬取到的数据入库前,建议做去重处理,可以通过给关键字段加唯一索引实现。

6.4 案例 16:断点续爬

如果爬虫跑了一半崩溃了,重新从第一页开始爬会很浪费时间。断点续爬的核心思路是记录“已经处理到的位置”,下次启动时从该位置继续。

# 文件路径:python_spider_practice/case16_resume_crawl.py import json from pathlib import Path status_file = Path("crawl_status.json") def load_status(): if status_file.exists(): data = json.loads(status_file.read_text(encoding="utf-8")) return data.get("last_page", 0) return 0 def save_status(page): status_file.write_text( json.dumps({"last_page": page}, ensure_ascii=False, indent=2), encoding="utf-8" ) # 模拟分页爬取 start_page = load_status() for page in range(start_page, 10): print(f"正在爬取第 {page + 1} 页...") # 这里写入真正的爬取逻辑 # 每爬完一页就保存状态 save_status(page + 1) print("全部爬取完成")

这种“状态持久化”的思想,在真实爬虫项目中非常重要。你可以把状态存到文件、数据库或 Redis 中。

7. 第五组案例:工程化与稳定性

爬虫不只是“写几行代码抓数据”,还要考虑异常处理、日志记录、定时执行等工程问题。

7.1 案例 17:统一异常处理与日志记录

日志可以帮助你在爬虫无人值守运行时追踪问题。Python 标准库logging提供了非常完整的日志能力。

# 文件路径:python_spider_practice/case17_logging.py import logging import requests # 配置日志 logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("spider.log", encoding="utf-8"), logging.StreamHandler() ] ) def crawl_page(url): try: logging.info("开始请求:%s", url) response = requests.get(url, timeout=5) response.raise_for_status() logging.info("请求成功,数据长度:%d", len(response.text)) return response.text except requests.exceptions.Timeout: logging.error("请求超时:%s", url) except requests.exceptions.RequestException as e: logging.exception("请求异常:%s", url) return None if __name__ == "__main__": html = crawl_page("https://jsonplaceholder.typicode.com/posts/1") if html: print("拿到页面内容")

代码说明:

  • FileHandler把日志写入文件,StreamHandler同时输出到控制台;
  • logging.exception会输出完整异常堆栈,便于排查问题;
  • 正确定位异常日志级别,能显著减少后期维护成本。

7.2 案例 18:定时爬虫任务调度

爬虫经常需要按固定周期执行。比如每天早上 8 点抓取一次天气预报、每周抓取一次榜单数据。APScheduler 是一个轻量级任务调度库,适合爬虫场景。

# 文件路径:python_spider_practice/case18_scheduler.py import time from datetime import datetime from apscheduler.schedulers.blocking import BlockingScheduler def job(): print(f"{datetime.now()} 开始执行定时爬虫任务") # 这里放你的爬虫主逻辑 # 比如 requests 请求、数据解析、入库等 print("任务执行完成") scheduler = BlockingScheduler() # 每 10 分钟执行一次 scheduler.add_job(job, "interval", minutes=10) # 也可以改成每天固定时间执行 # scheduler.add_job(job, "cron", hour=8, minute=0) print("调度器启动,按 Ctrl+C 结束") scheduler.start()

如果你想部署在服务器上,更推荐使用系统级的定时任务工具(Windows 的任务计划程序、Linux 的 crontab),这样即使 Python 进程意外退出,任务也会由操作系统重新拉起。

8. 爬虫开发中的常见问题与排查思路

以下是我在实际爬虫开发中经常遇到的问题,整理成了一张速查表:

问题现象常见原因解决思路
请求返回 403服务器拒绝访问,通常是缺少请求头或触发了反爬策略添加User-AgentReferer等请求头;降低请求频率
请求返回 404URL 拼写错误,或列表页与详情页 URL 规则不一致在浏览器中手动访问,检查 URL 实际路径
中文乱码页面编码不是 UTF-8,响应内容被错误解码查看响应头中的charset字段,指定response.encoding
请求超时目标网站响应慢,或网络环境不稳定设置合理 timeout,加入重试机制
JSON 解析失败返回内容不是 JSON 格式,可能被重定向到登录页或验证页面先打印response.text确认内容格式
数据提取结果为空XPath/CSS 选择器写错,或页面为动态渲染用浏览器开发者工具检查实际元素结构;考虑使用 Selenium 等工具
爬取过程中被限制访问请求频率过高,触发了服务端限制增加间隔时间,设置随机延迟,控制并发数
Excel 打开 CSV 乱码CSV 文件编码与 Excel 默认编码不一致写入时使用utf-8-sig编码

排查异常时,建议按照“先看状态码 → 再看响应文本 → 接着定位解析逻辑 → 最后检查数据存储”的顺序进行,大部分问题都能快速锁定。

9. 最佳实践与工程建议

这里结合平时做爬虫项目的经验,给大家一些比较实用的建议。

9.1 遵守规则与底线

  • 只抓取公开、合法、允许访问的数据;
  • 遵守目标网站的 robots.txt 协议和用户协议;
  • 控制请求频率,不要对目标服务器造成压力;
  • 不要将爬虫用于批量注册、刷票、恶意攻击、未授权抓取个人隐私等行为;
  • 下载的数据仅用于学习研究,不要用于商业用途或公开传播。

9.2 代码设计规范

  • 把请求、解析、存储三个流程拆分成独立函数,便于测试和维护;
  • 使用配置模块统一管理 URL、headers、超时时间、重试次数;
  • 对关键路径使用 try-except 包裹,但不要吞掉异常,至少要记录日志;
  • 为每个函数写简要注释,说明入参、返回值和注意事项。

大型爬虫项目可以参考下面的分层:

spider_project/ ├── config.py # 全局配置 ├── spiders/ # 各个爬虫模块 │ ├── article_spider.py │ └── image_spider.py ├── parsers/ # 解析模块 ├── storage/ # 数据存储模块 ├── utils/ # 通用工具 └── run.py # 启动入口

9.3 数据清洗与去重

爬取到的数据通常不干净,入库前要处理:

  • 去空格、去换行、去除 HTML 标签;
  • 统一日期格式;
  • 去除重复数据(可以用数据库唯一索引或 set 集合);
  • 对字段缺失的数据做默认值处理。

9.4 性能与稳定性

  • 对耗时操作设置合理的超时时间;
  • 使用 Session 复用连接;
  • 如果并发量较大,考虑使用线程池控制并发上限;
  • 加入失败重试和失败 URL 记录;
  • 生产环境使用 Supervisor、systemd、Docker 等方式管理爬虫进程。

9.5 学会利用官方 API

如果能找到官方 API,优先使用 API 而不是解析 HTML。API 返回的是结构化 JSON 数据,稳定、高效、不容易因为页面改版而失效。很多平台都提供了公开 API 或开发者接口,这是更友好、更合规的数据获取方式。

10. 总结与下一步学习建议

到这里,18 个 Python 爬虫实战案例就全部过完一遍了。你掌握了以下这些能力:

  • 用 urllib、requests 发起 HTTP 请求;
  • 用 BeautifulSoup、XPath、正则表达式提取数据;
  • 处理翻页、图片下载、Cookie 会话、超时与异常重试;
  • 把数据保存到 CSV、Excel、SQLite;
  • 使用日志、定时任务来提升爬虫的工程化能力。

如果你把每个案例都亲手敲一遍,再尝试改一改数据源和解析规则,就已经具备独立开发大部分静态网页爬虫的能力了。

接下来,建议你按这样的顺序继续深入:

  1. 用官方 API 做一个小项目,比如利用 GitHub API 抓取开源项目信息,保存到数据库;
  2. 找一个合法的公开练习站点,尝试完成列表页 → 详情页 → 多字段采集 → 数据持久化的全流程;
  3. 学习 CSS 选择器,配合 BeautifulSoup 的select方法使用,它比find_all在一些场景下更简洁;
  4. 了解 requests-html、Selenium、Playwright 这类工具在动态页面中的用途;
  5. 学习 Scrapy 框架,进一步掌握分布式爬虫和管道处理。

爬虫这门技术,实践价值很高,但它真正考验的是你的排查能力、数据清洗能力和工程意识。入门阶段不要贪多,先跑通这 18 个案例,你对 Python 爬虫的技术体系就会有一个非常完整的感觉。如果文章对你有帮助,欢迎收藏备用。后面我也会继续更新爬虫和数据采集相关的实战内容。

http://www.cnnetsun.cn/news/4296425.html

相关文章:

  • 技术博客选题边界:为什么社会新闻不能写成CSDN教程
  • AI芯片竞争背后:GPU、CUDA与大模型算力生态解析
  • Claude记忆升级实战:跨聊天持久化项目上下文与Claude Code配置
  • STM32未用FLASH区域填充:链接脚本配置与固件校验优化
  • 零基础Python学习路径:从环境配置到爬虫与数据分析实战
  • 深入解析SambaNova RDU:可重构数据流芯片如何革新大模型推理
  • Win10+VS2019编译Curl 7.84.0:从环境配置到项目集成的完整指南
  • Java秋招面试核心考点全梳理:从基础到项目实践
  • 从零搭建弹幕标签点名系统:Python+Redis实现直播间指人游戏
  • SASS2MLIR:将NVIDIA机器码提升到MLIR实现GPU性能优化
  • 从robots.txt到Shelf Protocol:电商数据如何实现商业授权
  • VC6.0股票行情软件核心模块:多线程实时刷新与MFC界面优化
  • 迷你主机如何跑本地大模型?AMD Ryzen AI Max+ 395用统一内存突破显存瓶颈
  • AI画板不靠谱,查错却靠谱:PCB设计检查工具链实战
  • DeepSeek V4 Flash 0731 成本评估:API计费与本地部署全解析
  • Windows平台CMake 3.31.10深度解析:从部署、生成器选择到编码问题解决
  • figma爱丽丝测评:可动塑料小人如何治愈手办冷淡期
  • 从AI价值占比到AI工程化:普通团队的落地路径
  • 从点灯到做项目:32位单片机学习路径与工程化实践
  • 两年经验社招微信五轮面试全流程复盘与经验总结
  • 智能车竞赛新手备赛指南:从零到稳定完赛的完整路线图
  • 从零备战智能车竞赛:规则、硬件与PID调试全流程复盘
  • 轮腿机器人竞赛实战复盘:从机械结构到PID与视觉识别的工程优化
  • CodeBuddy NPC深度评测:从安装部署到团队级AI员工落地
  • 700个智能体并发请求Hugging Face:从限流原理到请求层设计实战
  • 时间步条件Transformer:单模型实现灵活多时效AI天气预报
  • Revenue Agents:用AI Agent实现客户流失预警与增购挖掘的架构与代码实践
  • ST-Link/V2配TXB0108导致nRST被拉低?根因分析与改造方案
  • 视觉大模型微调实战:从LoRA策略到Qwen2-VL工业级应用部署
  • AI自动化测试入门:Python+Playwright+Pytest实战路线