前几篇实战中,我们的数据均来自手动录入或本地生成。但在真实开发中,更多场景需要从网络自动抓取有价值的信息——比如行业资讯、公开榜单等。今天,我们将聚焦Python爬虫的基础实战,从核心概念、合规原则到完整项目开发,打通“数据获取→解析→存储”的全流程。本文不仅教你写代码,更帮你建立合规爬取的思维框架,为后续数据分析、Web开发等进阶方向打下坚实基础。
️ 一、爬虫核心认知:是什么、为什么、怎么做
在动手写代码前,先厘清爬虫的本质与边界。Python爬虫本质上是一段自动化程序,它模拟浏览器向目标网站发送HTTP请求,获取服务器返回的数据,再通过解析提取出有价值的信息,最终保存到本地文件或数据库中。其核心工作流程可概括为四步:
- 发送请求:模拟浏览器向服务器发送GET/POST请求,携带必要的请求头(如User-Agent),获取响应数据(HTML源码、JSON等)。
- 解析数据:对响应数据进行处理,提取所需内容(如文本、链接、图片地址),过滤无关信息。常用工具有BeautifulSoup4和正则表达式。
- 数据存储:将结构化数据写入JSON、CSV文件或数据库,便于后续分析或使用。
- 自动化控制:通过循环、分页等技术实现批量爬取,提升效率。
重要提示:爬虫开发必须遵守法律法规和平台规则。核心原则包括:遵守robots协议、控制爬取频率(使用time.sleep())、尊重版权与隐私、伪装请求头、不突破反爬机制。本次实战选用豆瓣公开榜单等无反爬限制的测试网站,仅用于学习目的。
⚙️ 二、核心技术拆解:请求发送与数据解析
爬虫的两大核心技能是“发送请求获取数据”和“解析提取数据”。我们先分别掌握它们,再结合实战整合应用。
1. 网络请求:requests模块基础用法
Python的requests库是爬虫中最常用的HTTP工具,支持GET/POST请求,能轻松处理请求头和响应数据。以下是GET请求的典型用法:
import requests
import time
# 1. 定义目标URL(以豆瓣电影Top250公开榜单为例,合规爬取)
url = "https://movie.douban.com/top250?start=0&filter="
# 2. 定义请求头,伪装成浏览器(从浏览器开发者工具中复制真实User-Agent)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
try:
# 3. 发送GET请求,设置超时时间(避免无限等待)
response = requests.get(url, headers=headers, timeout=10)
# 4. 校验响应状态码(200表示请求成功)
if response.status_code == 200:
# 获取网页源码(文本形式)
html = response.text
print("请求成功,网页源码长度:", len(html))
else:
print(f"请求失败,状态码:{response.status_code}")
except requests.exceptions.RequestException as e:
print(f"请求异常:{str(e)}")
# 控制爬取频率,间隔1秒
time.sleep(1)
响应对象提供多种数据获取方式:
response.text:获取文本形式的数据(适用于HTML)。response.content:获取二进制数据(适用于图片、视频)。response.json():自动解析JSON格式数据(适用于API接口)。response.status_code:获取状态码,判断请求是否成功。
2. 数据解析:BeautifulSoup4与正则表达式
获取HTML源码后,需要提取有效信息。BeautifulSoup4(bs4) 通过标签、属性定位元素,简单直观;正则表达式 则适用于复杂文本匹配。新手推荐优先使用bs4:
from bs4 import BeautifulSoup
import requests
# 先发送请求获取网页源码(复用上面的请求逻辑)
url = "https://movie.douban.com/top250?start=0&filter="
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
# 初始化bs4解析器(指定lxml解析器,需提前安装:pip install lxml)
soup = BeautifulSoup(response.text, "lxml")
# 1. 按标签+类名定位元素(提取电影列表项)
movie_list = soup.find_all("div", class_="item") # find_all返回所有匹配元素的列表
print(f"共找到 {len(movie_list)} 部电影")
# 2. 遍历电影列表,提取每部电影的信息
for movie in movie_list:
# 提取电影名称(定位span标签,class为title)
name = movie.find("span", class_="title").get_text() # get_text()获取标签内文本
# 提取评分(定位span标签,class为rating_num)
score = movie.find("span", class_="rating_num").get_text()
# 提取简介(定位p标签,获取文本并处理)
info = movie.find("p", class_="").get_text(strip=True).replace("\n", " ")
# 提取详情链接
link = movie.find("a")["href"] # 获取a标签的href属性值
# 打印提取的信息
print(f"电影名称:{name}")
print(f"评分:{score}")
print(f"详情链接:{link}")
print("-"*50)
except requests.exceptions.RequestException as e:
print(f"请求异常:{str(e)}")
bs4核心方法:
soup.find(tag, attrs):查找第一个匹配元素。soup.find_all(tag, attrs):查找所有匹配元素,返回列表。element.get_text(strip=True):获取元素内文本。element["attr_name"]:获取属性值(如href、src)。
当数据无法通过标签准确定位时,可结合正则表达式匹配文本模式:
import re
import requests
url = "https://movie.douban.com/top250?start=0&filter="
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
# 定义正则表达式模式(匹配电影名称,需结合网页源码调整)
pattern = re.compile(r'([^<]+)', re.S)
# 查找所有匹配的结果
names = re.findall(pattern, response.text)
# 去重(过滤重复的电影名称标签)
unique_names = list(set(names))
print("提取的电影名称:")
for idx, name in enumerate(unique_names, 1):
print(f"{idx}. {name}")
except requests.exceptions.RequestException as e:
print(f"请求异常:{str(e)}")
⚠️ 注意:正则表达式的核心是“精准匹配文本模式”,需结合网页源码结构调整表达式。建议先掌握bs4,再逐步过渡到正则表达式处理复杂场景。
三、实战案例:豆瓣电影Top250爬取(完整项目)
现在,我们将前面学到的请求发送、数据解析、持久化技术整合起来,开发一个完整的爬虫项目——爬取豆瓣电影Top250的全部电影信息(名称、评分、导演、详情链接),并存储到JSON与CSV文件中。项目严格遵循模块化开发思想。
1. 项目架构设计
按“请求模块→解析模块→存储模块→主程序”拆分代码,结构清晰、易于维护:
douban_movie_spider/ # 爬虫项目根目录
├── spider.py # 核心爬虫模块:封装请求、解析逻辑
├── storage.py # 存储模块:封装JSON、CSV文件持久化
├── main.py # 主程序:调度爬虫与存储,控制整体流程
└── movies.json # 存储爬取结果(自动生成)
└── movies.csv # 存储爬取结果(自动生成)
2. 逐模块实现
(1)核心爬虫模块:spider.py
# spider.py:豆瓣电影Top250爬虫核心模块
import requests
from bs4 import BeautifulSoup
import time
import random
class DoubanMovieSpider:
def __init__(self):
self.base_url = "https://movie.douban.com/top250?start={}&filter="
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept-Language": "zh-CN,zh;q=0.9" # 增加语言头,提升兼容性
}
self.movie_list = [] # 存储所有电影信息
def send_request(self, url):
"""发送请求,获取网页源码"""
try:
# 随机设置请求间隔(1-3秒),模拟人工浏览,避免被封禁
time.sleep(random.uniform(1, 3))
response = requests.get(url, headers=self.headers, timeout=15)
if response.status_code == 200:
return response.text
else:
print(f"请求失败,状态码:{response.status_code},URL:{url}")
return None
except requests.exceptions.RequestException as e:
print(f"请求异常:{str(e)},URL:{url}")
return None
def parse_html(self, html):
"""解析网页源码,提取电影信息"""
if not html:
return
soup = BeautifulSoup(html, "lxml")
movie_items = soup.find_all("div", class_="item")
for item in movie_items:
# 提取核心信息
movie_info = {
"name": item.find("span", class_="title").get_text(), # 电影名称
"score": item.find("span", class_="rating_num").get_text(), # 评分
"director": item.find("p", class_="").get_text(strip=True).split("\n")[0].split("导演: ")[1].split("主演: ")[0], # 导演
"link": item.find("a")["href"], # 详情链接
"quote": item.find("span", class_="inq").get_text() if item.find("span", class_="inq") else "无简介" # 简介(可选)
}
self.movie_list.append(movie_info)
print(f"已提取:{movie_info['name']}")
def crawl(self):
"""批量爬取所有页面(Top250共10页,每页25条)"""
print("开始爬取豆瓣电影Top250...")
for page in range(10):
start = page * 25 # 每页起始位置(0,25,50...225)
url = self.base_url.format(start)
print(f"正在爬取第{page+1}页,URL:{url}")
html = self.send_request(url)
self.parse_html(html)
print(f"爬取完成,共提取 {len(self.movie_list)} 部电影信息")
return self.movie_list
(2)存储模块:storage.py
# storage.py:数据存储模块(JSON+CSV)
import json
import csv
class DataStorage:
@staticmethod
def save_to_json(data, file_path="movies.json"):
"""将数据保存到JSON文件"""
try:
with open(file_path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"数据已成功保存到JSON文件:{file_path}")
except Exception as e:
print(f"JSON文件保存失败:{str(e)}")
@staticmethod
def save_to_csv(data, file_path="movies.csv"):
"""将数据保存到CSV文件(更适合表格类数据)"""
if not data:
print("无数据可保存到CSV文件")
return
try:
# 获取字段名(字典的键)
fieldnames = data[0].keys()
with open(file_path, "w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader() # 写入表头
writer.writerows(data) # 写入数据
print(f"数据已成功保存到CSV文件:{file_path}")
except Exception as e:
print(f"CSV文件保存失败:{str(e)}")
(3)主程序:main.py
# main.py:豆瓣电影爬虫主程序
from spider import DoubanMovieSpider
from storage import DataStorage
def main():
# 初始化爬虫
spider = DoubanMovieSpider()
# 开始爬取
movie_data = spider.crawl()
# 保存数据(JSON+CSV双格式)
if movie_data:
DataStorage.save_to_json(movie_data)
DataStorage.save_to_csv(movie_data)
print("爬虫程序执行完毕!")
if __name__ == "__main__":
main()
3. 运行与验证
运行main.py,程序将自动爬取10页数据,过程中打印每部电影的名称,最终生成movies.json与movies.csv文件。验证要点:
- ✅ JSON文件:结构清晰,包含名称、评分、导演等信息,无乱码。
- ✅ CSV文件:表头与数据对应,可用Excel直接打开分析。
- ✅ 爬取过程:无请求异常提示,爬取频率合理(已设置间隔),未被封禁IP。
️ 四、常见问题与排查技巧
爬虫开发中难免遇到各种问题,以下总结高频问题及解决方案:
- 请求被拒绝(状态码403/404):未设置请求头、频率过高、IP被封。解决方案:添加完整请求头(User-Agent、Referer),增加请求间隔,必要时更换IP。
- 解析失败(提取不到数据):网页结构变化、解析表达式错误、编码问题。解决方案:用F12开发者工具重新查看源码,调整解析逻辑;设置
response.encoding="utf-8"。 - 请求超时/连接错误:网络不稳定、服务器响应慢。解决方案:设置更长的超时时间,检查网络连接。
- 被网站封禁IP:频繁请求、未伪装浏览器。解决方案:停止爬取一段时间,优化请求头与频率,严格遵守合规原则。
[AFFILIATE_SLOT_1]
五、Python基础阶段知识体系总结
至此,Python基础阶段的全部核心内容已讲解完毕。从基础语法到三大实战项目,我们构建了完整的知识与技能体系。以下是核心知识总结:
1. 核心语法模块
- 数据类型:整数、浮点数、字符串、列表、字典、元组、集合的特性与常用方法。
- 流程控制:if-elif-else条件判断、for/while循环,结合break、continue控制流程。
- 函数编程:函数定义、参数传递(位置参数、关键字参数、默认参数)、返回值,理解封装思想。
2. 进阶核心模块
- 面向对象编程:类与对象、封装、初始化方法,适用于复杂项目。
- 异常处理:try-except捕获异常,raise主动抛出异常,确保程序稳定。
- 模块化与包:按功能拆分模块,理解“高内聚、低耦合”原则。
- 文件持久化:JSON、CSV、文本文件的读写方法,实现数据长期存储。
3. 实战项目模块
- 猜数字游戏:巩固基础语法与异常处理,建立项目思维。
- 简易通讯录:掌握面向对象封装与JSON持久化,学会分层开发。
- 爬虫入门:打通“数据获取→解析→存储”全流程,掌握合规爬取要点。
4. 核心思维总结
基础阶段不仅是学习语法,更重要的是培养正确的开发思维:封装思维(提升复用性)、模块化思维(降低耦合)、异常防护思维(保证稳定)、合规思维(坚守技术底线)。这些思维同样适用于Java、TypeScript、C++、Go等语言的学习,是程序员通用的核心素养。
[AFFILIATE_SLOT_2]
六、全文总结
Python基础阶段的学习之旅至此圆满结束。从一行行简单的打印语句,到能独立开发功能完整的实战项目,你不仅掌握了Python的核心语法与技能,更建立了系统化的开发思维与问题处理能力。这些知识是后续学习数据分析、Web开发、人工智能等进阶方向的坚实基础。记住:编程学习没有捷径,唯有“理解+实践+复盘”才能真正掌握。基础阶段的结束,正是进阶学习的开始。愿你在Python的世界里继续深耕,写出更优秀的代码,实现更多有趣的想法!
浙公网安备 33010602011771号