遵守规范的抓取实践
遵守 robots.txt、设置用户代理请求头、延迟请求并使用缓存。
遵守规范的抓取实践 是 CoddyKit 上的免费 AI Agents 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。
为什么负责任地抓取很重要
网页抓取可能会给服务器造成压力、违反服务条款,还可能导致智能体的 IP 被封禁。负责任的抓取程序会遵守速率限制,表明自身身份,并遵循网站公布的规则。
本课将介绍如何以合乎道德且可持续的方式进行抓取所需的工具和技术。
检查 robots.txt
每个网站都可以发布一个 robots.txt 文件,说明自动化智能体可以或不可以访问哪些路径。Python 标准库包含用于解析该文件的 urllib.robotparser。
抓取网站前,请始终检查 robots.txt。
import urllib.robotparser
rp = urllib.robotparser.RobotFileParser()
rp.set_url('https://example.com/robots.txt')
rp.read()
# Check if our bot can fetch a specific path
can_fetch = rp.can_fetch('MyAgent/1.0', 'https://example.com/public-data')
print(f'Can fetch: {can_fetch}') # True or False
cannot_fetch = rp.can_fetch('*', 'https://example.com/private/admin')
print(f'Admin allowed: {cannot_fetch}') # Often False设置描述性 User-Agent
User-Agent HTTP 标头用于标识请求的发起者。诚实的 User-Agent 可以让网站管理员了解您的机器人是什么,以及在出现问题时如何联系您。伪装成浏览器以规避拦截会引发道德问题。
import httpx
headers = {
# Honest, descriptive User-Agent
'User-Agent': 'MyResearchBot/1.0 (contact: me@example.com; purpose: academic research)'
}
response = httpx.get(
'https://example.com/data',
headers=headers,
timeout=10.0
)
print(response.status_code)使用 time.sleep() 进行速率限制
每秒发送数百个请求可能会使服务器不堪重负,而且通常会被视为拒绝服务攻击。请使用 time.sleep() 在请求之间添加延迟。使用 random.uniform() 可以让延迟不那么机械,更接近人类行为。
import time
import random
import httpx
urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3'
]
for url in urls:
response = httpx.get(url, timeout=10.0)
print(f'Fetched {url}: {response.status_code}')
# Wait between 1 and 3 seconds before the next request
delay = random.uniform(1, 3)
print(f'Sleeping {delay:.1f}s...')
time.sleep(delay)遵守 Retry-After 标头
当服务器返回 429 Too Many Requests 时,通常会包含一个 Retry-After 标头,指定需要等待的秒数。您的智能体应当读取并遵守该标头,而不是立即重试。
import time
import httpx
def fetch_with_retry(url: str) -> httpx.Response:
while True:
response = httpx.get(url, timeout=10.0)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 5))
print(f'Rate limited. Waiting {retry_after}s...')
time.sleep(retry_after)
continue # retry
response.raise_for_status()
return response缓存响应以避免重复获取
requests-cache 会自动将 HTTP 响应缓存到磁盘。如果您的智能体需要多次获取同一个网址(例如在开发或重新运行期间),系统会立即返回缓存的响应,而不会再次访问服务器。
# pip install requests-cache
import requests_cache
# Install the cache globally — cached responses expire after 1 hour
requests_cache.install_cache(
'agent_cache',
backend='sqlite',
expire_after=3600 # seconds
)
import requests
# First call: fetches from network and caches
response = requests.get('https://api.example.com/data')
print(response.from_cache) # False
# Second call: returns cached result instantly
response2 = requests.get('https://api.example.com/data')
print(response2.from_cache) # True使用 httpx 进行基于文件的手动缓存
如果您不想使用 requests-cache,简单的基于文件的缓存也很有效。将响应存储为以网址哈希为键的 JSON 文件,并在文件仍然足够新时重新加载它们。
import hashlib
import json
import os
import time
import httpx
CACHE_DIR = '/tmp/agent_cache'
os.makedirs(CACHE_DIR, exist_ok=True)
def cached_get(url: str, ttl_seconds: int = 3600) -> dict:
key = hashlib.md5(url.encode()).hexdigest()
cache_file = os.path.join(CACHE_DIR, key + '.json')
if os.path.exists(cache_file):
age = time.time() - os.path.getmtime(cache_file)
if age < ttl_seconds:
with open(cache_file) as f:
return json.load(f)
response = httpx.get(url, timeout=10.0)
response.raise_for_status()
data = response.json()
with open(cache_file, 'w') as f:
json.dump(data, f)
return data阅读服务条款
抓取任何网站前,请先阅读其服务条款。许多网站会明确禁止自动化访问或将其数据用于商业用途。违反服务条款可能导致法律诉讼,而不仅仅是 IP 被封禁。
如果存在官方 API,请始终优先使用它,而不是抓取 HTML——官方 API 更快、更稳定,也更安全地规避法律风险。
错误时使用指数退避
请求失败时,请不要立即重试。请使用指数退避:等待 1 秒,然后等待 2 秒,再等待 4 秒,依此类推。这样可以避免不断请求处于故障状态的服务器,也是生产环境智能体中常用的专业模式。
import time
import httpx
def fetch_with_backoff(url: str, max_retries: int = 4) -> dict:
for attempt in range(max_retries):
try:
response = httpx.get(url, timeout=10.0)
response.raise_for_status()
return response.json()
except (httpx.HTTPStatusError, httpx.RequestError) as e:
if attempt == max_retries - 1:
raise
wait = 2 ** attempt # 1, 2, 4, 8 seconds
print(f'Attempt {attempt+1} failed: {e}. Retrying in {wait}s...')
time.sleep(wait)
return {}只抓取所需内容
只获取智能体实际需要的内容,以减少服务器负载。当一个小型 API 端点能够返回相同数据时,请避免下载完整页面。请使用 HEAD 请求检查资源是否发生变化,然后再获取完整正文。
import httpx
def has_page_changed(url: str, last_etag: str = None) -> bool:
headers = {}
if last_etag:
headers['If-None-Match'] = last_etag
response = httpx.head(url, headers=headers, timeout=5.0)
if response.status_code == 304: # Not Modified
return False
new_etag = response.headers.get('ETag')
print(f'New ETag: {new_etag}')
return True负责任抓取规则总结
智能体抓取任何网站前,请快速检查以下事项:
- 检查
robots.txt并遵守禁止访问规则 - 设置诚实且具有描述性的
User-Agent - 在请求之间添加随机延迟(
time.sleep(random.uniform(1,3))) - 在收到 429 响应时遵守
Retry-After标头 - 缓存响应,避免重复获取
- 阅读网站的服务条款
- 在可用时优先使用官方 API,而不是抓取 HTML
知识检查:负责任地抓取
请测试您对合乎道德且负责任的抓取实践的理解。
回顾:负责任的抓取实践
现在,您已经拥有一套完整的负责任抓取工具:
- 使用
robotparser检查您获准访问的内容 - 使用具有描述性的
User-Agent标头标识您的机器人 - 在请求之间使用
time.sleep(random.uniform(1,3)) - 使用
requests-cache或手动缓存,避免重复获取 - 使用指数退避处理错误
- 提高法律意识:始终检查服务条款
负责任的抓取有助于构建更健康的网络,并让您的智能体在不被封禁的情况下持续运行。
用 AI 导师学习 AI Agents — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 60
- 课程
- 239
常见问题解答
「遵守规范的抓取实践」课时是免费的吗?
是的 — 「遵守规范的抓取实践」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。
「遵守规范的抓取实践」这节课中我会学到什么?
遵守 robots.txt、设置用户代理请求头、延迟请求并使用缓存。 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Agents 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「遵守规范的抓取实践」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Agents 课中编写并运行代码吗?
能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。