- 获取网页内容:向目标网站的服务器发送请求,下载网页的源代码(通常是 HTML)。
- 解析网页内容:从下载下来的 HTML 源代码中,精准地提取出你想要的信息(比如标题、正文、图片链接等)。
下面我将为你提供一个从入门到实践的完整指南,包含代码示例和详细解释。

第一步:准备工作(安装必要的库)
你需要安装两个核心库:
requests:用于发送网络请求,获取网页源代码,它比 Python 自带的urllib库更简单易用。BeautifulSoup4:用于解析 HTML 和 XML 文档,非常方便地从复杂的网页结构中提取数据。
打开你的终端或命令行工具,运行以下命令进行安装:
pip install requests pip install beautifulsoup4
第二步:获取网页内容
我们将使用 requests 库来获取一个网页的 HTML 内容,以获取我的博客首页为例:
import requests
# 1. 定义目标网址
url = 'https://www.example.com' # 这是一个标准的示例网站,你可以换成任何你想抓取的网址,如 'https://www.zhihu.com'
try:
# 2. 发送 GET 请求,获取响应
# headers 参数可以模拟浏览器访问,避免被一些网站屏蔽
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers)
# 3. 检查请求是否成功 (状态码 200 表示成功)
response.raise_for_status() # 如果请求失败 (404, 500),会抛出异常
# 4. 获取网页的 HTML 内容 (源代码)
html_content = response.text
# 打印前 500 个字符看看效果
print(html_content[:500])
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
代码解释:

import requests:导入requests库。url:你想要抓取的网页地址。headers:一个字典,包含了请求头。User-Agent是最常见的,它告诉服务器你用什么浏览器在访问,很多网站会检查这个值,如果没有,可能会拒绝你的请求。requests.get(url, headers=headers):发送一个 GET 请求到目标网址。response.raise_for_status():这是一个非常好的习惯,如果请求返回了错误状态码(404 Not Found),它会立即停止程序并抛出异常。response.text:获取服务器返回的文本内容,也就是网页的 HTML 源代码。
第三步:解析网页内容(核心步骤)
现在你已经拿到了 HTML 源代码,但它们是一大堆文本,你需要像用“手术刀”一样精确地切出你想要的部分。BeautifulSoup 就是这把“手术刀”。
假设我们要从 https://www.example.com 这个页面中提取所有的链接 (<a> 标签)。
import requests
from bs4 import BeautifulSoup
url = 'https://www.example.com'
try:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers)
response.raise_for_status()
# 1. 创建 BeautifulSoup 对象
# 'html.parser' 是 Python 内置的解析器,简单易用
soup = BeautifulSoup(response.text, 'html.parser')
# 2. 查找并提取数据
# --- 示例 1: 查找所有的 <a> 标签 ---
all_links = soup.find_all('a')
print("--- 所有链接 ---")
for link in all_links:
# 获取标签的文本内容
text = link.text.strip()
# 获取标签的 href 属性 (链接地址)
href = link.get('href')
if href and text: # 确保链接和文本都不为空
print(f"文本: {text}, 链接: {href}")
# --- 示例 2: 查找标题 (通常是 <h1> 标签) ---
# find() 只返回第一个匹配的元素tag = soup.find('h1')
if title_tag:
print("\n--- 页面标题 ---")
print(title_tag.text)
# --- 示例 3: 使用 CSS 选择器 (更强大、更推荐) ---
# 假设我们想找一个 id 为 "main-content" 的 div 下的所有段落
# main_content = soup.select_one('#main-content') # select_one 返回第一个匹配的
# if main_content:
# paragraphs = main_content.find_all('p')
# print("\n--- main-content 下的所有段落 ---")
# for p in paragraphs:
# print(p.text.strip())
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
except Exception as e:
print(f"解析失败: {e}")
BeautifulSoup 核心方法详解:
| 方法 | 描述 | 示例 |
|---|---|---|
soup.find('tag_name') |
查找第一个匹配的标签。 | soup.find('a') |
soup.find_all('tag_name') |
查找所有匹配的标签,返回一个列表。 | soup.find_all('p') |
soup.select('css_selector') |
使用 CSS 选择器查找所有匹配的元素,返回一个列表。功能最强大! | soup.select('div.content > p') |
soup.select_one('css_selector') |
使用 CSS 选择器查找第一个匹配的元素。 | soup.select_one('#title') |
.text |
获取一个标签的所有文本内容(包括其子标签的文本)。 | link.text |
.get('attribute_name') |
获取标签的某个属性值。 | link.get('href'), img.get('src') |
.strip() |
一个字符串方法,用于去除文本开头和结尾的空白字符(如空格、换行)。 | p.text.strip() |
CSS 选择器语法(非常实用):

tag:p选择所有<p>#id:#main-content选择id="main-content"的元素。.class:.article选择所有class="article"的元素。[attribute]:[href]选择所有有href属性的元素。parent > child:div > p选择所有父级是<div>的<p>ancestor descendant:div p选择所有在<div>内部的<p>标签(不限层级)。
完整实战案例:抓取豆瓣 Top 250 电影的标题和评分
这个例子将把上面所有知识串联起来。
目标: 获取豆瓣电影 Top 250 页面前 10 部电影的标题和评分。
网址: https://movie.douban.com/top250
import requests
from bs4 import BeautifulSoup
import time # 用于延时,避免请求过于频繁
def scrape_douban_top250():
"""
抓取豆瓣电影 Top 250 的前 10 部电影信息
"""
base_url = 'https://movie.douban.com/top250'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
all_movies_data = []
try:
# 发送请求
response = requests.get(base_url, headers=headers)
response.raise_for_status()
# 解析 HTML
soup = BeautifulSoup(response.text, 'html.parser')
# 使用 CSS 选择器精确定位电影条目
# 检查网页结构,电影信息都在 <ol class="grid_view"> 下的 <li> 标签里
movie_items = soup.select('ol.grid_view li')
print(f"找到 {len(movie_items)} 部电影信息。")
# 遍历每个电影条目
for item in movie_items[:10]: # 只取前10部
# 提取标题
# 标题在 <span class="title"> 标签里
title_tag = item.select_one('span.title')
title = title_tag.text.strip() if title_tag else "未知标题"
# 提取评分
# 评分在 <span class="rating_num"> 标签里
rating_tag = item.select_one('span.rating_num')
rating = rating_tag.text.strip() if rating_tag else "未知评分"
all_movies_data.append({'title': title, 'rating': rating})
# 打印提取到的信息
print(f"电影: {title}, 评分: {rating}")
# 礼貌性延时,防止被封禁
time.sleep(1)
except requests.exceptions.RequestException as e:
print(f"网络请求失败: {e}")
except Exception as e:
print(f"解析过程中发生错误: {e}")
return all_movies_data
# 运行函数
if __name__ == '__main__':
movie_data = scrape_douban_top250()
# 你可以将结果保存到文件或数据库中
# import json
# with open('movies.json', 'w', encoding='utf-8') as f:
# json.dump(movie_data, f, ensure_ascii=False, indent=4)
# print("\n数据已保存到 movies.json")
重要注意事项与进阶
-
合法性:
- 永远遵守网站的
robots.txt协议,你可以在网站域名后加上/robots.txt查看(https://www.example.com/robots.txt),它规定了哪些页面可以抓取,哪些不可以。 - 不要过度频繁地请求同一个网站,这会给对方服务器带来巨大压力,使用
time.sleep()进行延时是一个好习惯。 - 仅用于个人学习和研究,不要用于商业用途或恶意爬取。
- 永远遵守网站的
-
反爬虫机制:
- User-Agent 检测:如上所述,设置
headers。 - IP 封禁:如果请求太频繁,你的 IP 可能会被暂时封禁,解决方案是使用代理 IP 池。
- 验证码:网站可能会弹出验证码让你证明是“人”,处理验证码比较复杂,可能需要使用第三方服务。
- 动态加载:很多网站内容是通过 JavaScript 动态加载的,
requests只能获取初始的 HTML,看不到 JS 加载的内容,这时你需要使用更强大的工具,如 Selenium 或 Playwright,它们可以模拟一个真实的浏览器来执行 JS 并获取最终渲染后的页面。
- User-Agent 检测:如上所述,设置
-
数据存储:
- 抓取到的数据可以保存为 CSV、JSON 文件,或者存入 SQLite、MySQL 等数据库中,方便后续分析。
希望这份详细的指南能帮助你顺利入门 Python 网页抓取!祝你学习愉快!
