
本文详解 yelp 爬虫遭遇 503 service unavailable 的根本原因,强调遵守 robots.txt、合理限速、解析响应头等关键实践,并提供可落地的 scrapy 配置优化方案与替代建议。
Yelp 明确将网络爬虫视为高风险行为——其反爬机制成熟且严格。你遇到的 503 Service Unavailable 并非偶然网络故障,而是 Yelp 服务端主动拒绝请求的明确信号:它已将你的 IP(或整个请求模式)识别为异常流量,触发了防护策略(如速率限制、IP 封禁或 Cloudflare 挑战)。仅靠轮换 User-Agent 或关闭 ROBOTSTXT_OBEY 不仅无效,反而会加速被封。
? 根本问题剖析
- 违反 robots.txt 是红线:Yelp 的 https://www.yelp.com/robots.txt 明确禁止对 /search、/biz/ 等核心路径的自动化抓取。Scrapy 中设置 ROBOTSTXT_OBEY = False 属于技术上可行但法律与道德上不可接受的行为,极易触发风控。
- 缺乏请求节流(Throttling):你的代码中未设置 DOWNLOAD_DELAY 或 AUTOTHROTTLE_ENABLED,导致短时间内高频请求(尤其分页循环),服务器视同 DoS 攻击。
- 忽略响应头中的关键指令:Yelp 响应头可能包含 Retry-After、X-RateLimit-Remaining 或 X-RateLimit-Reset 等字段(类似 GitHub API 示例),但你的爬虫未解析并响应这些“减速”提示。
- User-Agent 轮换治标不治本:现代 WAF(如 Cloudflare)通过 TLS 指纹、请求时序、JS 行为等多维特征识别爬虫,单一 UA 变化毫无意义。
✅ 合规、可持续的实践方案
1. 优先使用官方 API
Yelp 提供 Yelp Fusion API(需申请 Key),支持餐厅搜索、详情、评论等结构化数据,免费层含 5,000 次/天调用,且明确允许商用。这是唯一合法、稳定、无需反爬对抗的方案:
import requests
headers = {"Authorization": "Bearer YOUR_API_KEY"}
params = {
"term": "restaurants",
"location": "San Francisco, CA",
"limit": 50,
"offset": 0
}
response = requests.get("https://api.yelp.com/v3/businesses/search",
headers=headers, params=params)
data = response.json() # 直接获取 JSON,无 HTML 解析负担2. 若必须爬取网页(仅限合规场景),请严格遵循:
启用并尊重 robots.txt:ROBOTSTXT_OBEY = True,并手动检查 https://www.yelp.com/robots.txt 中的 Disallow 规则;
-
强制限速:在 settings.py 中配置:
# 至少 2–5 秒延迟,模拟真实用户 DOWNLOAD_DELAY = 3 RANDOMIZE_DOWNLOAD_DELAY = True # 在 ±0.5x 范围内随机波动 AUTOTHROTTLE_ENABLED = True AUTOTHROTTLE_START_DELAY = 3 AUTOTHROTTLE_MAX_DELAY = 10
-
添加请求头合法性:使用固定、真实的 UA + Accept-Language、Accept-Encoding 等:
# settings.py DEFAULT_REQUEST_HEADERS = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', } USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' -
解析响应头并动态退避:在 parse() 方法中检查状态码与头信息:
def parse(self, response): if response.status == 503: # 遇到 503,立即暂停并重试(避免死循环) self.logger.warning(f"503 received, sleeping 60s...") time.sleep(60) yield scrapy.Request(response.url, callback=self.parse, dont_filter=True) return # 检查 Retry-After 头(若有) retry_after = response.headers.get('Retry-After') if retry_after: delay = int(retry_after) if retry_after.isdigit() else 60 time.sleep(delay) # 正常解析逻辑...
3. 替代方案建议
- 数据采购:Yelp 允许企业通过 Yelp for Business 或第三方数据提供商(如 Bright Data、Apify)获取合规数据集;
- 学术合作:若属研究用途,可联系 Yelp Research 团队申请数据访问权限;
- 转向公开数据源:如 USDA 餐厅数据库、OpenStreetMap POI 数据等。
⚠️ 重要提醒
- 法律风险:违反 Yelp 的《Terms of Service》可能导致法律追责(参考 hiQ Labs v. LinkedIn 案例,但 Yelp 条款更严格);
- 技术成本远超收益:维护高可用爬虫需持续对抗 JS 渲染、验证码、指纹检测,投入产出比极低;
- 道德责任:公共资源属于所有用户,高频爬取会挤占正常用户带宽,损害平台生态。
结论:放弃对抗式爬取,拥抱官方 API 或合规数据渠道,是唯一可持续、零风险的技术选择。真正的工程能力,不在于“如何绕过”,而在于“如何优雅协作”。










