使用Ruby Mechanize爬取美国务院页面遭遇403 Forbidden错误求助
403 Forbidden错误排查(Ruby Mechanize爬取美国国务院页面)
报错信息
403 => Net::HTTPForbidden for https://www.state.gov/countries-areas-archive/tunisia/page/2/ -- unhandled response (Mechanize::ResponseCodeError)
问题描述
我想要爬取美国国务院关于突尼斯的9页声明,但访问第二页时出现上述403错误,我的Ruby Mechanize代码如下,请问问题出在哪里?
require 'mechanize' agent = Mechanize.new 9.times do |i| page = agent.get("https://www.state.gov/countries-areas-archive/tunisia/page/#{i+1}/") page.search('a.collection-result_link').each do |link| agent.click(link) url = agent.page.search('link[rel = "canonical"]').attr('href').text wrapped_url = url.gsub(url, "<a href='#{url}'>الرابط</a>") title = agent.page.search('h1.featured-content__headline report-header__headline stars-above').text statements = [wrapped_url, title] puts statements end end
问题根源
403错误是网站服务器直接拒绝了你的请求,核心原因是反爬机制识别出你是爬虫,而非正常用户:
- Mechanize默认的请求头特征明显,比如
User-Agent是Mechanize专属标识,很容易被拦截 - 爬取速度过快,没有设置请求间隔,触发了网站的访问频率限制
- 缺少真实浏览器会携带的必要请求头(如
Accept-Language、Referer等),请求特征不符合正常用户行为
修复方案
1. 伪装浏览器请求头
给Mechanize设置主流浏览器的User-Agent,模拟真实用户访问:
agent = Mechanize.new # 使用预设的Chrome浏览器UA agent.user_agent_alias = 'Chrome' # 也可以自定义UA字符串 # agent.user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
2. 添加请求间隔
每次请求后暂停几秒,避免触发频率限制:
9.times do |i| page = agent.get("https://www.state.gov/countries-areas-archive/tunisia/page/#{i+1}/") page.search('a.collection-result_link').each do |link| agent.click(link) # 你的处理代码... sleep(2) # 每次点击详情页后暂停2秒 end sleep(3) # 每页爬完后暂停3秒 end
3. 补充必要请求头
添加真实浏览器会携带的请求头,进一步模拟正常请求:
agent.add_field('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8') agent.add_field('Accept-Language', 'en-US,en;q=0.5') agent.add_field('Referer', 'https://www.state.gov/countries-areas-archive/tunisia/')
4. 捕获异常避免程序崩溃
添加异常捕获逻辑,遇到错误时可以记录信息或尝试重试:
9.times do |i| begin page = agent.get("https://www.state.gov/countries-areas-archive/tunisia/page/#{i+1}/") # 后续处理代码... rescue Mechanize::ResponseCodeError => e puts "请求第#{i+1}页失败: #{e.message}" sleep(5) retry # 可选:重试一次 end end
额外注意事项
- 先查看网站的
robots.txt文件(https://www.state.gov/robots.txt),确认目标页面是否允许爬取,避免违反网站规则 - 不要过度爬取,避免给服务器造成过大压力,否则可能被永久封禁IP
内容的提问来源于stack exchange,提问作者Karim Bn Abdlaziz
相关产品推荐
相关产品推荐

