Python 网络爬虫教程
欢迎学习 Python 网络爬虫!本教程将带你从零基础开始,逐步掌握网络爬虫的核心知识和技能。
什么是网络爬虫?
网络爬虫(Web Crawler)是一种自动化程序,用于从互联网上批量获取网页内容并提取所需数据。它模拟浏览器访问网站的行为,按照一定的规则自动抓取网页信息。
爬虫的工作原理
爬虫的基本流程:
- 发起请求:向目标网站发送 HTTP 请求
- 获取响应:接收服务器返回的响应内容
- 解析内容:解析 HTML 或 JSON 数据
- 提取数据:从解析结果中提取所需信息
- 存储数据:将数据保存到本地文件或数据库
- 遍历页面:继续抓取下一个页面
为什么学习 Python 爬虫?
- 数据获取:批量获取公开可用的网络数据
- 自动化:替代人工操作,提高工作效率
- 市场调研:采集竞品价格、用户评价等信息
- 学术研究:收集科研数据、新闻舆情等
- 技能扩展:提升 Python 编程能力
爬虫技术栈
核心工具
| 工具 | 用途 | 特点 |
|---|---|---|
| requests | HTTP 请求 | 简单易用,Python 最流行的 HTTP 库 |
| urllib | HTTP 请求 | Python 标准库,功能全面 |
| httpx | HTTP 请求 | 支持异步,现代化的 requests 替代品 |
| BeautifulSoup | HTML 解析 | API 友好,易于上手 |
| lxml | HTML/XML 解析 | 性能高,支持 XPath |
| selectolax | HTML 解析 | 速度极快,内存占用低 |
| Scrapy | 爬虫框架 | 功能完整,适合大规模爬取 |
| Selenium | 浏览器自动化 | 支持 JavaScript 渲染 |
| Playwright | 浏览器自动化 | 现代化的 Selenium 替代品 |
工具选择建议
- 入门推荐:
requests+BeautifulSoup,学习曲线平缓,适合初学者 - 生产环境:
Scrapy框架,功能完整,效率高 - 动态页面:
Selenium或Playwright,需要渲染 JavaScript - 高性能:
httpx(异步)+selectolax(快速解析)
教程目录
入门基础
- 环境配置 - 安装 Python 和相关库
- HTTP 基础 - 理解 HTTP 协议
- requests 库 - 发送 HTTP 请求
数据解析
- BeautifulSoup 基础 - 解析 HTML 内容
进阶技巧
框架与工具
- Scrapy 框架 - 专业爬虫框架
- Selenium 自动化 - 浏览器自动化工具
实战案例
- 实战案例 - 综合实战项目
知识速查
- 速查表 - 常用代码片段速查
法律法规与伦理
重要提示
网络爬虫涉及法律法规和伦理道德问题,请在合法合规的前提下使用。
注意事项
- 遵守 robots.txt:查看网站的爬虫协议,尊重网站的抓取规则
- 控制请求频率:避免对目标网站造成过大压力
- 遵守使用条款:不要违反网站的服务条款
- 保护隐私数据:不要爬取涉及个人隐私的数据
- 合理使用数据:获取的数据仅用于正当目的
robots.txt 详解
robots.txt 是网站根目录下的一个文本文件,用于告诉爬虫哪些页面可以抓取,哪些不可以。这是互联网社区约定的道德规范,虽然没有强制执行力,但遵守它是爬虫开发者的基本素养。
robots.txt 的位置和格式
robots.txt 必须放在网站根目录下,通过 /robots.txt 访问。例如:
https://www.example.com/robots.txthttps://www.baidu.com/robots.txt
常见指令说明
# robots.txt 示例
# User-agent: 指定规则适用的爬虫
# * 表示所有爬虫
User-agent: *
# Disallow: 禁止访问的路径
Disallow: /admin/ # 禁止访问 /admin/ 目录
Disallow: /private/ # 禁止访问 /private/ 目录
Disallow: /search # 禁止访问以 /search 开头的路径
Disallow: /*.pdf$ # 禁止访问所有 PDF 文件
# Allow: 允许访问的路径
Allow: /public/ # 允许访问 /public/ 目录
Allow: /images/ # 允许访问 /images/ 目录
# Crawl-delay: 爬取延迟(秒)
Crawl-delay: 10 # 每次请求间隔至少 10 秒
# Sitemap: 网站地图位置
Sitemap: https://example.com/sitemap.xml
Python 解析 robots.txt
Python 标准库提供了 urllib.robotparser 模块来解析 robots.txt:
import urllib.robotparser
from urllib.parse import urlparse
def check_robots_txt(target_url, user_agent='MyBot'):
"""
检查目标 URL 是否允许被爬取
参数:
target_url: 要爬取的目标 URL
user_agent: 爬虫的 User-Agent 名称
返回:
bool: True 表示允许爬取,False 表示禁止
"""
# 解析目标 URL,获取网站根目录
parsed = urlparse(target_url)
base_url = f'{parsed.scheme}://{parsed.netloc}'
# 创建 robots.txt 解析器
rp = urllib.robotparser.RobotFileParser()
rp.set_url(f'{base_url}/robots.txt')
try:
# 读取并解析 robots.txt
rp.read()
# 检查是否允许爬取
can_fetch = rp.can_fetch(user_agent, target_url)
# 获取建议的爬取延迟
crawl_delay = rp.crawl_delay(user_agent)
print(f'网站: {base_url}')
print(f'目标: {target_url}')
print(f'允许爬取: {"是" if can_fetch else "否"}')
if crawl_delay:
print(f'建议延迟: {crawl_delay} 秒')
return can_fetch
except Exception as e:
print(f'无法读取 robots.txt: {e}')
# 如果无法读取 robots.txt,默认允许(但应谨慎)
return True
# 使用示例
if __name__ == '__main__':
# 检查是否可以爬取
url = 'https://www.example.com/some-page'
if check_robots_txt(url, 'MySpider'):
print('可以进行爬取')
else:
print('robots.txt 禁止爬取此页面')
常见网站的 robots.txt 示例
淘宝网:
User-agent: *
Disallow: /
淘宝禁止所有爬虫访问任何页面(但实际上主流搜索引擎有白名单)。
知乎:
User-agent: *
Disallow: /login
Disallow: /logout
Disallow: /signin
Disallow: /signup
知乎只禁止了登录注册相关页面。
维基百科:
User-agent: *
Disallow: /wiki/Special:
Disallow: /wiki/Spezial:
Allow: /wiki/Special:Search
维基百科允许爬取大部分内容,只限制了一些特殊页面。
robots.txt 的局限性
需要理解 robots.txt 的几个重要特点:
- 非强制性:robots.txt 只是道德规范,技术上无法阻止爬虫访问
- 不同爬虫不同规则:网站可以为不同爬虫设置不同规则
- 缓存机制:解析器通常会缓存结果,不会每次都请求
- 子域名独立:每个子域名需要单独的 robots.txt
最佳实践
import requests
import time
import urllib.robotparser
from urllib.parse import urlparse
class EthicalSpider:
"""遵守爬虫道德规范的爬虫基类"""
def __init__(self, user_agent='EthicalSpider/1.0'):
self.user_agent = user_agent
self.session = requests.Session()
self.session.headers.update({
'User-Agent': user_agent
})
self.robots_cache = {} # 缓存各网站的 robots 解析结果
def get_robots_parser(self, base_url):
"""获取并缓存 robots.txt 解析器"""
if base_url not in self.robots_cache:
rp = urllib.robotparser.RobotFileParser()
rp.set_url(f'{base_url}/robots.txt')
try:
rp.read()
self.robots_cache[base_url] = rp
except Exception:
self.robots_cache[base_url] = None
return self.robots_cache[base_url]
def can_fetch(self, url):
"""检查是否允许爬取指定 URL"""
parsed = urlparse(url)
base_url = f'{parsed.scheme}://{parsed.netloc}'
rp = self.get_robots_parser(base_url)
if rp is None:
return True # 无 robots.txt,默认允许
return rp.can_fetch(self.user_agent, url)
def get_crawl_delay(self, url):
"""获取建议的爬取延迟"""
parsed = urlparse(url)
base_url = f'{parsed.scheme}://{parsed.netloc}'
rp = self.get_robots_parser(base_url)
if rp is None:
return 1 # 默认 1 秒
delay = rp.crawl_delay(self.user_agent)
return float(delay) if delay else 1
def fetch(self, url, **kwargs):
"""获取页面(遵守 robots.txt 和爬取延迟)"""
# 检查 robots.txt
if not self.can_fetch(url):
raise PermissionError(f'robots.txt 禁止爬取: {url}')
# 遵守爬取延迟
delay = self.get_crawl_delay(url)
time.sleep(delay)
# 发送请求
response = self.session.get(url, **kwargs)
return response
# 使用示例
spider = EthicalSpider()
try:
response = spider.fetch('https://example.com/page')
print(response.status_code)
except PermissionError as e:
print(f'爬取被拒绝: {e}')
建议做法
# 合理的爬虫应该这样做:
import time
# 1. 设置合理的请求间隔
DELAY = 2 # 2秒间隔
time.sleep(DELAY)
# 2. 设置正确的 User-Agent
headers = {
'User-Agent': 'Mozilla/5.0 (compatible; MyBot/1.0; +http://example.com/bot)'
}
# 3. 尊重 robots.txt
# 使用 urllib.robotparser.RobotFileParser 检查是否允许爬取
# 4. 只爬取公开数据
# 不要绕过登录验证或支付墙
学习建议
- 动手实践:每学一个知识点,都要动手编写代码验证
- 循序渐进:按照教程顺序学习,不要跳跃
- 分析网页:学会使用浏览器开发者工具分析网页结构
- 阅读文档:遇到问题查阅官方文档
- 遵守规则:养成良好的爬虫素养
参考资料
- Requests 官方文档 - Python 最流行的 HTTP 库
- BeautifulSoup 官方文档 - HTML/XML 解析库
- Scrapy 官方文档 - 专业爬虫框架
- Playwright 官方文档 - 现代浏览器自动化
- MDN HTTP 文档 - HTTP 协议参考
准备好开始学习了吗?点击下一章开始你的爬虫之旅!