用 Python 获取网络资源(一):Requests 库入门与实践
学习概述
在网络数据采集领域,Python 有着得天独厚的优势,这得益于其丰富的第三方库生态。其中,requests 库是最简单、最人性化的 HTTP 客户端库之一,它让发送 HTTP 请求变得像访问本地文件一样简单。
通过本篇的学习,你将掌握:
- 使用 Requests 库发送 HTTP 请求
- 处理服务器响应,获取文本和二进制内容
- 设置请求头,模拟浏览器访问
- 使用正则表达式初步提取网页信息
- 了解 IP 代理的基本使用场景
用 Python 获取网络数据
为什么选择 Requests 库?
- 简单易用:API 设计直观,学习成本低
- 功能全面:支持 GET、POST 等各种 HTTP 方法,自动处理编码、Cookie 等
- 社区活跃:文档完善,遇到问题容易找到解决方案
初识 Requests:获取网页 HTML
下面是一个最简单的例子,演示如何使用 requests 获取搜狐首页的 HTML 代码:
import requests
resp = requests.get('https://www.sohu.com/')
if resp.status_code == 200:
print(resp.text[:1000])
else:
print(f'请求失败,状态码:{resp.status_code}')
代码解析:requests.get() 发送 GET 请求,返回一个 Response 对象;resp.status_code 获取 HTTP 状态码;resp.text 获取响应内容的文本形式(自动解码)。
从 HTML 中提取信息:正则表达式初试
获取 HTML 只是第一步,我们通常需要从中提取特定信息。正则表达式是文本匹配的利器,下面示例从搜狐首页提取新闻标题和链接:
import re
import requests
pattern = re.compile(r'<a.*?href="(.*?)".*?title="(.*?)".*?>')
resp = requests.get('https://www.sohu.com/')
if resp.status_code == 200:
all_matches = pattern.findall(resp.text)
for href, title in all_matches[:5]:
print(f'标题:{title}')
print(f'链接:{href}')
print('-' * 50)
注意:实际项目中,正则表达式可能因网页结构变化而失效。更稳定的解析方式(如 BeautifulSoup)将在后续文章介绍。
获取二进制资源:下载图片
Requests 不仅可以获取文本,还能下载图片、视频等二进制文件:
import requests
logo_url = 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
resp = requests.get(logo_url)
if resp.status_code == 200:
with open('baidu_logo.png', 'wb') as f:
f.write(resp.content)
print('图片下载完成!')
else:
print('下载失败')
提示:resp.content 返回的是二进制数据,而 resp.text 返回的是解码后的文本。
实战项目:爬取豆瓣电影 Top250
让我们用一个完整的实战项目巩固所学——爬取豆瓣电影 Top250 榜单。
1. 分析目标网站
2. 编写爬虫代码
import random
import re
import time
import requests
for page in range(1, 11):
start = (page - 1) * 25
resp = requests.get(
url=f'https://movie.douban.com/top250?start={start}',
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'}
)
if resp.status_code != 200:
print(f'第{page}页请求失败')
continue
title_pattern = re.compile(r'<span>([^&]*?)</span>')
titles = title_pattern.findall(resp.text)
rating_pattern = re.compile(r'<span.*?>(.*?)</span>')
ratings = rating_pattern.findall(resp.text)
print(f'\n========== 第{page}页 ==========')
for i, (title, rating) in enumerate(zip(titles, ratings), 1):
print(f'{i:2d}. {title:30} 评分:{rating}')
delay = random.uniform(1, 3)
time.sleep(delay)
()
关键点说明:User-Agent 设置:模拟浏览器访问,绕过基础反爬;正则表达式匹配:通过分析 HTML 结构定位目标数据;延迟机制:添加随机延迟,尊重目标网站,避免被封 IP。
3. 应对反爬:使用 IP 代理
当频繁访问同一网站时,你的 IP 可能会被限制。这时可以使用代理服务隐藏真实 IP。以下以示例代理配置为例:
import requests
import re
APP_KEY = '你的 AppKey'
PROXY_HOST = 'proxy.example.com:9001'
for page in range(1, 4):
resp = requests.get(
url=f'https://movie.douban.com/top250?start={(page - 1)*25}',
headers={
'Proxy-Authorization': f'Basic {APP_KEY}',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
},
proxies={
'http': f'http://{PROXY_HOST}',
'https': f'https://{PROXY_HOST}'
},
verify=False
)
if resp.status_code == 200:
titles = re.findall(r'<span>([^&]*?)</span>', resp.text)
print(f'第{page}页获取到{len(titles)}部电影')
else:
print(f'第{page}页请求失败:{resp.status_code}')
time.sleep(1)
爬虫开发注意事项
- 频率控制:合理设置请求间隔,避免对目标服务器造成压力
- 异常处理:网络请求可能失败,添加重试机制
- 遵守协议:查看目标网站的
robots.txt,尊重爬取规则
- 数据存储:及时保存已获取数据,避免重复工作
拓展学习:Requests 库更多功能
Requests 库还有很多高级功能值得探索:
- 会话保持:使用
Session 对象维持 Cookie
- 文件上传:模拟表单文件上传
- SSL 证书验证:处理 HTTPS 请求
- 超时设置:防止请求无限等待
- 身份认证:支持 Basic Auth、OAuth 等
总结与预告
今天,我们学会了使用 Requests 库发送 HTTP 请求并获取响应内容,这是网络爬虫最基础也是最核心的一步。同时,我们用正则表达式进行了初步的数据提取,完成了豆瓣电影 Top250 的爬取实战。
然而,正则表达式编写和维护成本较高,特别是面对复杂的 HTML 结构时。下一篇文章,我们将介绍两种更优雅的 HTML 解析工具:BeautifulSoup 和 lxml,它们能让我们用更直观的方式提取网页数据。
动手练习
- 基础任务:使用 Requests 下载一张你喜欢的图片,并保存到本地。
- 进阶任务:修改豆瓣电影爬虫,同时提取电影的导演、主演和上映年份信息。
- 挑战任务:尝试爬取知乎热榜,提取问题标题和热度值。
提示:知乎反爬较严,需要仔细设置请求头,并考虑使用 IP 代理。