想进入网络爬虫的世界,却不知从何下手?本指南将摒弃枯燥的理论罗列,通过一个模拟的实战项目------采集一个在线书店的图书信息,手把手带你从零构建一个完整、健壮的 Python 爬虫。读完本文,你不仅能掌握 requests
和 BeautifulSoup
的核心用法,还能学到如何像专业开发者一样思考爬虫的最佳实践。
项目目标:抓取在线书店的图书信息
我们的目标是爬取一个模拟的在线书店网站,提取每本书的书名、价格和详情页链接。
最终我们要采集的数据格式如下:
书名 | 价格 | 链接 |
---|---|---|
《Python编程:从入门到实践》 | ¥55.00 | /books/python-programming |
《流畅的Python》 | ¥79.00 | /books/fluent-python |
... | ... | ... |
第一步:环境准备与项目初始化
在开始编码前,我们需要安装两个核心的 Python 库。
-
安装必要的库 在终端或命令行运行以下命令:
pip install requests beautifulsoup4
requests
: 一个强大而简洁的 HTTP 库,用于向目标网站发送网络请求,获取其 HTML 内容。beautifulsoup4
: 一个神奇的 HTML/XML 解析库,能将复杂的 HTML 文档转换成易于操作的 Python 对象,方便我们从中提取数据。
-
创建项目文件 创建一个名为
book_scraper.py
的 Python 文件,我们将在其中编写所有代码。
第二步:发送第一个网络请求
爬虫的第一步是获取网页的原始 HTML 内容。我们将使用 requests
库来完成这个任务。
假设我们的目标网站 URL 是 https://example-bookstore.com
。
python
# book_scraper.py
import requests
# 目标网站 URL
URL = "https://example-bookstore.com" # 这是一个示例 URL,实际中请替换为真实目标
# 发送 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"
}
try:
response = requests.get(URL, headers=headers, timeout=10)
# raise_for_status() 会在请求失败时 (例如 404, 500 错误) 抛出异常
response.raise_for_status()
print("网页请求成功!")
# response.text 包含了网页的完整 HTML 内容
html_content = response.text
# print(html_content[:500]) # 打印前500个字符,检查一下内容
except requests.exceptions.RequestException as e:
print(f"请求出错: {e}")
exit()
代码解析:
- 我们使用
requests.get()
发送一个 HTTP GET 请求。 - 通过设置
headers
中的User-Agent
,我们将爬虫伪装成一个真实的浏览器用户,提高了成功率。 - 使用
try...except
结构捕获可能发生的网络错误(如连接超时、DNS 查询失败等),并使用response.raise_for_status()
检查 HTTP 状态码,这是编写健壮爬虫的关键一步。
第三步:解析 HTML 并提取数据
拿到了 HTML,接下来就是从中提取我们需要的信息。BeautifulSoup
让这个过程变得异常简单。
首先,我们需要分析目标网页的 HTML 结构。 打开浏览器,访问目标网站,右键点击书名,选择"检查"或"Inspect",你将看到类似这样的 HTML 结构:
ini
<div class="book-card">
<h3 class="book-title">
<a href="/books/python-programming">《Python编程:从入门到实践》</a>
</h3>
<p class="book-price">¥55.00</p>
</div>
<div class="book-card">
<h3 class="book-title">
<a href="/books/fluent-python">《流畅的Python》</a>
</h3>
<p class="book-price">¥79.00</p>
</div>
我们的任务就是:
- 找到所有包含图书信息的
div
容器(class 为book-card
)。 - 在每个容器中,分别提取书名(
h3
标签内的a
标签文本)、价格(p
标签的文本)和链接(a
标签的href
属性)。
现在,我们用 BeautifulSoup
来实现它:
ini
# book_scraper.py (接上文)
from bs4 import BeautifulSoup
# ... (请求部分代码) ...
# 使用 BeautifulSoup 解析 HTML
soup = BeautifulSoup(html_content, "html.parser")
# 查找所有 class="book-card" 的 div 标签
book_cards = soup.find_all("div", class_="book-card")
# 存储提取到的数据
books_data = []
# 遍历每个 book_card,提取信息
for card in book_cards:
# 提取书名
# .find() 方法返回第一个匹配的标签
# .text 用于获取标签内的文本内容,.strip() 用于去除多余的空白
title_element = card.find("h3", class_="book-title").find("a")
title = title_element.text.strip()
# 提取链接
# .get("href") 用于获取标签的 href 属性值
link = title_element.get("href")
# 拼接成完整的 URL
full_link = f"https://example-bookstore.com{link}"
# 提取价格
price_element = card.find("p", class_="book-price")
price = price_element.text.strip()
# 将提取的数据存入列表
books_data.append({
"title": title,
"price": price,
"link": full_link
})
# 打印结果,验证一下
for book in books_data:
print(book)
代码解析:
BeautifulSoup(html_content, "html.parser")
创建一个 BeautifulSoup 对象,它代表了解析后的 HTML 文档。soup.find_all("div", class_="book-card")
是核心的查找方法。它会返回一个列表,包含所有class
属性为book-card
的div
标签。注意class_
的下划线,因为class
是 Python 的关键字。- 我们遍历返回的列表,对每个卡片使用
.find()
来定位内部的元素,并用.text
和.get()
来提取所需的数据。
第四步:存储数据到文件
将数据打印在控制台只是第一步,通常我们需要将它们保存下来以便后续分析。CSV (逗号分隔值) 文件是一种常见且易于处理的格式。
python
# book_scraper.py (接上文)
import csv
import time
# ... (请求和解析部分代码) ...
# 将数据写入 CSV 文件
try:
with open("books.csv", "w", newline="", encoding="utf-8-sig") as csvfile:
# 定义表头
fieldnames = ["title", "price", "link"]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
# 写入表头
writer.writeheader()
# 写入数据
writer.writerows(books_data)
print("数据已成功保存到 books.csv 文件!")
except IOError as e:
print(f"文件写入失败: {e}")
# 爬虫结束,礼貌地等待几秒
time.sleep(2)
代码解析:
- 我们使用 Python 内置的
csv
模块来处理 CSV 文件。 csv.DictWriter
是一个非常方便的工具,它允许我们直接将字典列表(books_data
)写入文件,代码更清晰。encoding="utf-8-sig"
确保中文字符在 Excel 等软件中能正确显示。- 在爬虫的最后加入
time.sleep(2)
是一个非常好的习惯,它可以在多次请求之间增加延迟,减轻目标服务器的压力,体现了"负责任的爬虫"精神。
最终完整代码
下面是集成了所有最佳实践的最终代码,你可以直接复制并运行它(记得将 URL 替换为真实目标)。
python
import requests
from bs4 import BeautifulSoup
import csv
import time
def scrape_bookstore(url):
"""
一个完整的图书信息爬虫函数,包含请求、解析和存储。
"""
print(f"开始爬取: {url}")
# 1. 发送健壮的网络请求
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"
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return
# 2. 解析 HTML
soup = BeautifulSoup(response.text, "html.parser")
book_cards = soup.find_all("div", class_="book-card")
if not book_cards:
print("未找到图书信息卡片,请检查 HTML 结构或 class 名称是否正确。")
return
# 3. 提取数据
books_data = []
base_url = "https://example-bookstore.com" # 提取基础 URL 用于拼接
for card in book_cards:
try:
title_element = card.find("h3", class_="book-title").find("a")
title = title_element.text.strip()
relative_link = title_element.get("href")
full_link = f"{base_url}{relative_link}"
price_element = card.find("p", class_="book-price")
price = price_element.text.strip()
books_data.append({"title": title, "price": price, "link": full_link})
except AttributeError:
# 如果某个卡片结构不完整,跳过它并打印一条警告
print("警告: 一个图书卡片结构不完整,已跳过。")
continue
# 4. 存储到 CSV 文件
try:
with open("books.csv", "w", newline="", encoding="utf-8-sig") as csvfile:
fieldnames = ["title", "price", "link"]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(books_data)
print(f"成功提取 {len(books_data)} 条图书信息,并保存到 books.csv")
except IOError as e:
print(f"文件写入失败: {e}")
if __name__ == "__main__":
# 目标网站
TARGET_URL = "https://example-bookstore.com" # 这是一个示例 URL
scrape_bookstore(TARGET_URL)
# 礼貌地等待
time.sleep(2)
print("爬虫任务结束。")
进阶学习与挑战
恭喜你,已经完成了第一个 Python 爬虫项目!但这仅仅是开始。接下来你可以挑战:
- 处理动态网页 (JavaScript 加载) : 很多现代网站使用 JavaScript 动态加载内容。
requests
只能获取初始的 HTML,无法执行 JS。这时你需要学习Selenium
或Playwright
这样的浏览器自动化工具。 - 大规模爬取与框架 : 当你需要爬取成千上万个页面时,手动管理请求、解析和存储会变得非常复杂。这时,强大的爬虫框架
Scrapy
就派上用场了,它提供了并发请求、数据管道、中间件等高级功能。 - 反爬虫策略: 随着你爬取更复杂的网站,会遇到各种反爬机制,如验证码、IP 封锁、动态 Token 等。学习如何使用代理 IP、轮换 User-Agent、处理 Cookies 是爬虫工程师的必备技能。
- 直接爬取 API: 许多网站(尤其是移动端)的数据是通过 API 接口加载的。通过浏览器开发者工具的"网络"面板找到这些 API,直接请求 JSON 数据通常比解析 HTML 更高效、更稳定。
推荐资源:
- 官方文档 : Requests, BeautifulSoup, Scrapy
- 书籍: 《Web Scraping with Python, 2nd Edition》
希望这篇实战指南能为你打开爬虫世界的大门。祝你探索愉快!