'# 爬虫笔记1:pycharm通过requests模块实现1简单爬虫2输入关键词获取搜索到的网页数据
一、背景与问题
在数据驱动的软件开发中,爬虫技术是获取互联网数据的重要手段。传统开发场景中,手动抓取数据需要频繁切换浏览器、记录URL、筛选内容,效率低下。通过requests模块实现的爬虫,能够自动化完成网络请求、数据解析和存储,大大提升开发效率。
然而,实际开发中常遇到以下问题:
- 基础请求无法获取数据(如反爬虫机制)
- 无法处理分页数据
- 网络异常处理不完善
- 多参数组合查询时URL构造错误
- 数据格式解析失败
二、基本原理
HTTP协议是爬虫工作的核心,requests模块封装了完整的HTTP请求流程:
- 连接建立:通过TCP协议建立与服务器的连接
- 请求发送:构造包含请求头(headers)、参数(params)、正文(body)的HTTP请求
- 响应接收:获取服务器返回的HTTP状态码、响应头、响应体
- 数据解析:将响应体中的HTML/XML/JSON等格式数据转换为结构化数据
requests模块的关键技术点:
- 会话管理:通过Session对象保持连接复用
- 异常处理:封装了超时、连接错误等异常类型
- 请求方法:支持GET/POST/PUT/DELETE等HTTP方法
- 请求头控制:可自定义User-Agent、Referer等字段
三、环境准备
1. 安装依赖
pip install requests2. PyCharm配置
- 创建新项目:File → New Project
- 添加Python解释器:Preferences → Project: Interpreter
- 安装requests库:在终端执行
pip install requests
3. 网络环境
- 确保网络连接正常
部分网站可能需要配置代理:
proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080' }
四、核心实现
1. 基础请求示例
import requests
# 发送GET请求
response = requests.get('https://httpbin.org/get', params={'key': 'value'}, headers={'User-Agent': 'Mozilla/5.0'})
# 打印响应内容
print(response.status_code) # 输出HTTP状态码
print(response.headers) # 输出响应头
print(response.text) # 输出响应体内容
print(response.json()) # 解析JSON格式响应关键代码解释:
params参数用于构建查询字符串(URL编码)headers参数模拟浏览器请求头response.json()自动处理JSON格式的响应体
2. 带参数的搜索请求
def search_web(keyword):
url = 'https://api.example.com/search'
payload = {
'q': keyword,
'count': 10,
'type': 'web'
}
headers = {
'User-Agent': 'Mozilla/5.0',
'Accept-Language': 'en-US'
}
try:
response = requests.get(url, params=payload, headers=headers, timeout=5)
response.raise_for_status() # 检查HTTP错误
return response.json()
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
return None关键代码解释:
params参数自动进行URL编码raise_for_status()检查4xx/5xx错误timeout参数防止长时间等待response.json()处理JSON响应
3. 分页数据处理
def get_pagination_data(base_url, page_size=10, max_pages=5):
all_data = []
for page in range(1, max_pages+1):
params = {'page': page, 'size': page_size}
response = requests.get(base_url, params=params, timeout=5)
if response.status_code == 200:
all_data.extend(response.json()['items'])
else:
break
return all_data关键代码解释:
- 使用循环处理多页数据
- 每页数据通过params参数传递
- 响应数据合并到all_data列表中
- 简单的错误处理机制
五、完整案例
1. 百度搜索结果爬取案例
import requests
import time
def baidu_search(keyword, max_results=10):
base_url = 'https://api.baidu.com/search'
headers = {
'User-Agent': 'Mozilla/5.0',
'Referer': 'https://www.baidu.com/',
'Accept-Language': 'zh-CN,zh;q=0.9'
}
results = []
for i in range(1, max_results+1):
params = {
'q': keyword,
'pn': i, # 页码参数
'rn': 10, # 每页结果数
'ie': 'utf8'
}
try:
response = requests.get(base_url, params=params, headers=headers, timeout=10)
if response.status_code == 200:
data = response.json()
results.extend(data['results'])
else:
print(f"请求失败,状态码: {response.status_code}")
break
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
break
time.sleep(1) # 防止请求过快
return results运行示例:
if __name__ == '__main__':
keywords = input("请输入搜索关键词: ")
results = baidu_search(keywords)
print(f"共获取到{len(results)}条结果")关键点分析:
- 使用百度API进行搜索,实际开发中需申请API密钥
- 页码参数
pn和每页结果数rn的组合控制分页 - 使用
time.sleep(1)控制请求频率,避免被封禁 - 异常处理机制确保程序稳定性
六、源码解析
1. requests.get()的内部机制
def get(url, **kwargs):
return request('GET', url, **kwargs)- 会话管理:自动创建Session对象
- 适配器机制:使用HTTPAdapter处理不同协议
- 连接池:复用TCP连接提高效率
2. Session对象的使用
session = requests.Session()
session.headers.update({'User-Agent': 'CustomAgent'})
response = session.get('https://example.com')- 保持会话状态(如cookies)
- 提升连接复用效率
- 支持自定义headers和cookies
3. 异常处理机制
try:
response = requests.get('https://example.com', timeout=5)
except requests.exceptions.Timeout:
print("请求超时")
except requests.exceptions.ConnectionError:
print("连接错误")
except requests.exceptions.HTTPError as e:
print(f"HTTP错误: {e.response.status_code}")七、进阶使用
1. 使用Session复用连接
session = requests.Session()
session.headers.update({
'User-Agent': 'Mozilla/5.0',
'Accept-Language': 'en-US'
})
response1 = session.get('https://example.com')
response2 = session.get('https://another-example.com')2. 处理复杂headers
headers = {
'User-Agent': 'Mozilla/5.0',
'Accept': 'text/html,application/xhtml+xml',
'Accept-Encoding': 'gzip',
'Accept-Language': 'en-US,en;q=0.9'
}3. 使用cookies
cookies = {
'session_id': '123456',
'user_token': 'abcdef'
}
response = requests.get('https://example.com', cookies=cookies)八、性能与工程实践
1. 性能优化方案
| 优化策略 | 说明 |
|---|---|
| 连接复用 | 使用Session对象保持连接 |
| 并发处理 | 使用concurrent.futures或asyncio进行并发 |
| 缓存机制 | 使用redis缓存常见请求结果 |
| 压缩传输 | 设置Accept-Encoding: gzip |
2. 异常处理规范
def safe_request(url):
try:
return requests.get(url, timeout=5)
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
return None3. 安全风险分析
- IP封禁:频繁请求可能导致被封禁
- 反爬虫机制:网站可能使用验证码、JavaScript渲染
- 数据泄露:未加密的请求可能暴露敏感信息
- 法律风险:违反网站的robots.txt协议
九、常见问题与踩坑
1. 常见错误及解决办法
| 错误类型 | 错误示例 | 解决方案 |
|---|---|---|
| User-Agent缺失 | requests.exceptions.HTTPError: 403 Forbidden | 设置合理的User-Agent |
| 超时异常 | requests.exceptions.Timeout | 调整timeout参数或增加重试机制 |
| SSL证书错误 | requests.exceptions.SSLError | 使用verify=False或安装证书 |
2. 分页处理错误
# 错误示例
params = {'page': 1, 'size': 10}
response = requests.get(url, params=params)问题:未处理分页参数的递增逻辑,导致无法获取后续页数据
3. 请求参数拼接错误
# 错误示例
url = 'https://api.example.com/search'
params = {'q': 'python', 'page': 2, 'size': 10}
response = requests.get(url, params=params)问题:未正确处理URL编码,导致参数解析错误
十、最佳实践
1. 推荐方案
- 使用Session对象:保持连接复用,提高效率
- 合理设置headers:模拟真实浏览器行为
- 异常处理机制:确保程序健壮性
- 参数校验:防止非法输入导致错误
- 日志记录:记录请求和响应信息便于调试
2. 推荐目录结构
project/
├── config/ # 配置文件
├── utils/ # 工具函数
│ └── requests_utils.py
├── core/ # 核心逻辑
│ └── crawler.py
├── tests/ # 测试用例
└── main.py # 启动文件3. 推荐代码规范
- 使用
requests.Session()保持连接 - 所有请求必须包含User-Agent
- 使用
timeout参数控制请求时间 - 所有异常必须有对应的处理逻辑
十一、总结
通过requests模块实现的简单爬虫,是数据采集的基础工具。在实际开发中,需要充分理解HTTP协议原理,合理使用Session对象,设置合理的headers,处理异常情况,并注意安全风险。
本方案适用于:
- 数据采集需求明确的场景
- 需要批量处理数据的场景
- 需要自动化获取数据的场景
但不适用于:
- 需要处理动态加载内容的场景(需使用Selenium)
- 需要处理复杂反爬机制的场景
- 需要处理大量数据的场景(需结合数据库)
在开发过程中,要始终遵循合法合规的原则,尊重网站的robots.txt协议,合理控制请求频率,避免对服务器造成过大负担。