如何构建简单的 Web 爬虫:从零开始的 Python 教程
简介
在数据驱动的时代,从互联网上自动获取信息是一项非常实用的技能。Web 爬虫(Web Crawler 或 Web Scraper)就是这样一个自动化程序,它能够按照一定的规则,在互联网上浏览并抓取所需的数据。本文将带领你,从零开始,使用 Python 语言构建一个简单但功能完整的 Web 爬虫。
我们将以抓取一个虚构的图书网站为例,学习爬虫的基本原理、所需工具以及核心代码实现。无论你是想分析市场数据、跟踪新闻动态,还是为自己的项目收集信息,掌握爬虫技术都将为你打开一扇新的大门。
在开始之前,如果你需要一台笔记本电脑来进行高强度的编程和数据处理,一台性能良好的设备会让开发过程更顺畅。
前置准备
在开始编写爬虫前,请确保你的开发环境已准备就绪:
- 安装 Python:访问 Python 官网 下载并安装最新版本的 Python(建议 3.8 或以上)。安装时请勾选 “Add Python to PATH”。
- 安装代码编辑器:推荐使用 Visual Studio Code、PyCharm 或其他你熟悉的编辑器。一个趁手的编辑器能极大提升效率,如果你正在寻找,可以考虑一款适合编程的机械键盘。
-
安装必要的 Python 库:打开终端(Windows 上是命令提示符或 PowerShell,macOS/Linux 上是终端),运行以下命令安装
requests和beautifulsoup4库。
bash
pip install requests beautifulsoup4requests:用于向目标网站发送 HTTP 请求,获取网页的 HTML 源代码。beautifulsoup4(通常简写为bs4):用于解析 HTML/XML 文档,从中提取我们需要的数据。
-
了解基础:你需要具备基本的 Python 语法知识(如变量、循环、函数)以及对 HTML 结构的简单了解(知道什么是标签、属性)。
第一步:分析目标网站与页面结构
在编写爬虫代码前,最重要的一步是手动分析你想要抓取的网站。
- 用浏览器打开目标网站(例如
http://books.example.com)。 - 右键点击页面,选择“检查”或“查看页面源代码”。
- 在开发者工具中,观察你感兴趣的数据(如书名、作者、价格)是如何嵌套在 HTML 标签中的。特别关注:
- 标签类型:书名是否在
<h2>或<div class="title">标签内? - 属性:是否有特殊的
class或id可以唯一定位到数据块? - 规律:所有图书信息的 HTML 结构是否一致?
- 标签类型:书名是否在
例如,我们可能发现所有图书信息都包含在一个 <div class="book-item"> 中,书名在 <h2 class="book-name"> 里,价格在 <span class="price"> 里。
第二步:发送HTTP请求获取页面
我们的爬虫第一步是模拟浏览器,向服务器请求网页内容。
import requests
from bs4 import BeautifulSoup
# 目标网页URL
url = "http://books.example.com"
# 添加请求头,模拟浏览器访问,避免被某些网站拦截
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:
# 发送GET请求
response = requests.get(url, headers=headers)
# 检查请求是否成功 (状态码200表示成功)
response.raise_for_status()
# 设置正确的编码,防止中文乱码
response.encoding = response.apparent_encoding
html_content = response.text
print("页面获取成功!")
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
html_content = None
第三步:解析HTML并提取数据
获得 HTML 字符串后,我们使用 BeautifulSoup 来解析它,并提取我们需要的数据。
if html_content:
# 使用BeautifulSoup解析HTML
soup = BeautifulSoup(html_content, 'html.parser')
# 根据第一步的分析,查找所有图书信息的容器
book_items = soup.find_all('div', class_='book-item')
books_data = []
for item in book_items:
# 提取书名
title = item.find('h2', class_='book-name').get_text(strip=True)
# 提取作者
author = item.find('span', class_='author').get_text(strip=True)
# 提取价格
price = item.find('span', class_='price').get_text(strip=True)
# 将数据存储为字典
book_info = {
'书名': title,
'作者': author,
'价格': price
}
books_data.append(book_info)
print(f"找到书籍:《{title}》,作者:{author},价格:{price}")
print(f"\n总共找到 {len(books_data)} 本书籍的信息。")
第四步:保存数据到文件
提取的数据通常需要保存下来以便后续分析。最简单的方式是保存到 CSV 文件。
import csv
if books_data:
# 定义CSV文件名
filename = "books_data.csv"
# 获取字典的键作为列名
fieldnames = books_data[0].keys()
# 写入CSV文件
with open(filename, 'w', newline='', encoding='utf-8-sig') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader() # 写入表头
writer.writerows(books_data) # 写入所有数据行
print(f"数据已成功保存至文件:{filename}")
第五步:扩展功能 – 分页处理
很多网站的数据分布在多个页面。我们需要找到翻页的URL规律并循环抓取。
import time
base_url = "http://books.example.com/page/"
all_books_data = []
for page_num in range(1, 6): # 抓取前5页作为示例
page_url = f"{base_url}{page_num}"
print(f"正在抓取第 {page_num} 页: {page_url}")
# 重复第二、三步的过程(可以封装成函数)
# ... 这里调用获取和解析页面的函数,并将结果合并到 all_books_data ...
# 非常重要:设置延迟,避免过于频繁的请求给服务器造成压力
time.sleep(2) # 休息2秒
# 保存所有页面的数据
# ...
代码示例:整合完整脚本
将以上步骤整合成一个更完整的、结构化的脚本。
import requests
from bs4 import BeautifulSoup
import csv
import time
class BookScraper:
def __init__(self, base_url):
self.base_url = base_url
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
self.all_books = []
def fetch_page(self, url):
"""获取单个页面的HTML内容"""
try:
response = requests.get(url, headers=self.headers)
response.raise_for_status()
response.encoding = response.apparent_encoding
return response.text
except requests.exceptions.RequestException as e:
print(f"抓取 {url} 时出错: {e}")
return None
def parse_page(self, html_content):
"""解析HTML,提取书籍信息"""
soup = BeautifulSoup(html_content, 'html.parser')
book_items = soup.find_all('div', class_='book-item')
page_books = []
for item in book_items:
try:
title = item.find('h2', class_='book-name').get_text(strip=True)
author = item.find('span', class_='author').get_text(strip=True)
price = item.find('span', class_='price').get_text(strip=True)
page_books.append({
'书名': title,
'作者': author,
'价格': price
})
except AttributeError:
# 处理某些字段可能缺失的情况
continue
return page_books
def save_to_csv(self, data, filename):
"""将数据保存到CSV文件"""
if not data:
return
with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.DictWriter(f, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
def run(self, total_pages=3, output_file='books.csv'):
"""运行爬虫主程序"""
for page in range(1, total_pages + 1):
url = f"{self.base_url}page/{page}"
print(f"正在处理: {url}")
html = self.fetch_page(url)
if html:
books_on_page = self.parse_page(html)
self.all_books.extend(books_on_page)
print(f" 本页找到 {len(books_on_page)} 本书。")
# 礼貌性爬虫,每次请求后等待
time.sleep(1.5)
print(f"\n爬取完成!总计获取 {len(self.all_books)} 本书籍信息。")
self.save_to_csv(self.all_books, output_file)
print(f"结果已保存至 {output_file}")
# 使用示例
if __name__ == "__main__":
# 请替换为实际的目标网站地址
scraper = BookScraper("http://books.example.com/")
scraper.run(total_pages=3, output_file="my_books.csv")
相关工具推荐
- 高级请求库:
httpx(支持异步) 或Scrapy(一个功能强大的爬虫框架)。 - 动态页面处理:如果网站大量使用 JavaScript 渲染内容,
requests无法获取,你需要使用Selenium或Playwright这类自动化测试工具来模拟浏览器操作。 - 数据存储:对于大量数据,可以考虑使用数据库,如
SQLite(轻量级)、MySQL或MongoDB。 - 代理服务:频繁抓取可能被目标网站封禁IP,这时可以使用代理IP池服务。
- 开发装备:长时间盯着屏幕编写和调试代码,保护视力很重要。一台低蓝光的显示器和一副防蓝光眼镜值得考虑。
常见问题
Q1: 爬虫运行时报错 “403 Forbidden” 或 “404 Not Found”?
A: 这可能是网站反爬机制启动了。首先检查 User-Agent 是否设置得当。其次,检查 URL 是否正确。有时还需要处理 Cookie 或添加更多请求头。
Q2: 提取的数据是乱码?
A: 通常是编码问题。确保在获取 response 后正确设置了 response.encoding,可以尝试 utf-8, gbk, gb2312 等。使用 response.apparent_encoding 让 requests 自动检测。
Q3: 如何抓取需要登录的网站?
A: 需要使用 requests.Session() 来维持会话,并在会话中发送登录的POST请求(带上正确的账号密码数据),之后这个会话的后续请求就会自动带上登录后的Cookie。
Q4: 爬虫的法律和道德边界在哪里?
A: 务必遵守:
1. 检查网站的 robots.txt 文件(通常在网站根目录,如 http://example.com/robots.txt),了解网站所有者允许和禁止抓取的范围。
2. 控制抓取频率,避免对目标网站服务器造成过大压力(即“礼貌性爬虫”)。
3. 不抓取受版权保护或隐私数据,遵守当地法律法规。
4. 抓取的数据仅用于个人学习或研究目的。
总结
恭喜你!通过本教程,你已经掌握了使用 Python 构建基础 Web 爬虫的完整流程:从分析页面、发送请求、解析数据到保存结果,并了解了如何处理分页和常见问题。
爬虫技术是一把双刃剑,它能高效地获取信息,但也伴随着法律和道德风险。请始终在合法合规、尊重他人知识产权和服务器资源的前提下使用这项技术。
下一步,你可以尝试:
* 为你自己感兴趣的真实网站(在遵守其规则的前提下)编写爬虫。
* 学习使用 Scrapy 框架来构建更强大、更稳定的爬虫项目。
* 结合 Pandas 库,对抓取到的数据进行清洗和分析。
如果你经常需要处理数据或运行脚本,一个高速稳定的移动硬盘或网络附属存储(NAS)会很有帮助。祝你编程愉快,探索无限可能的数据世界!