You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用rvest爬虫时如何避免open.connection(x, "rb"): HTTP 404错误?

Mercado Libre爬取时随机出现HTTP 404错误的原因与解决方法

问题背景

我将202个Mercado Libre商品页面的URL存储在向量中,尝试通过for循环结合rvest包爬取页面信息。这些URL来自商品列表页,通过以下代码获取:

get_products <- function(n_page) {
  cat("Scraping index", n_page, "\n")
  page <- str_c(
    "https://lista.mercadolivre.com.br/_Desde_",
    n_page,
    "_CustId_38356530_NoIndex_True"
  ) %>%
    read_html()
  
  tibble(url = page %>% 
      html_elements('a.ui-search-link') %>% 
      html_attr('href') %>% 
      str_subset('tracking_id') %>% 
      unique()
  )}

products_url <- map_dfr(seq(1, 49 * 4, by = 48), get_products)

遇到的问题

爬取过程中反复出现如下错误:

error in open.connection(x, "rb") : HTTP error 404

手动访问报错的URL均能正常打开,且错误出现的位置随机——比如第一次运行时向量第6个URL报错,第二次运行该URL却能正常爬取。目前用try()可以避免循环终止,但希望从根源解决问题,无需多次运行代码完成爬取。

当前爬取代码如下:

for (i in 1:length(standard_ad)) { 
  try(
  collectedtitles <- collect(standard_ad[i],'.ui-pdp-title'))
  assign('standard_titles', append(standard_titles, collectedtitles))
}

自定义的collect函数:

collect <- function(webpage,section) {
  page <- read_html(webpage)
  value <- html_node(page, section)
  value <- html_text(value)
}

错误原因分析

  1. 反爬机制伪装:Mercado Libre的反爬系统会对高频请求的客户端返回404状态码,这并非真的页面不存在,而是网站临时拒绝爬虫访问的伪装手段。
  2. 请求频率过高:未设置请求间隔,短时间内连续发送大量请求,触发了网站的限流策略。
  3. 请求头特征明显:read_html默认的请求头过于简单,容易被识别为爬虫,网站因此返回假404。

预防与解决方法

核心优化方向

  1. 添加模拟浏览器的请求头:用真实浏览器的User-Agent、Referer等信息伪装请求,降低被识别为爬虫的概率。
  2. 设置随机请求间隔:在每次请求之间加入随机等待时间,避免固定频率的请求模式被检测。
  3. 实现请求重试机制:针对临时返回的404错误,自动重试几次,而非直接放弃。
  4. 改用更可控的请求方式:用httr包替代直接调用read_html,灵活处理请求响应。

修改后的代码示例

library(rvest)
library(httr)
library(purrr)
library(stringr)

# 改进后的collect函数:带请求头、重试机制
collect <- function(webpage, section, max_retry = 3) {
  # 模拟真实浏览器的请求头
  browser_headers <- add_headers(
    `User-Agent` = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
    `Accept-Language` = "pt-BR,pt;q=0.9,en;q=0.8",
    `Referer` = "https://lista.mercadolivre.com.br/"
  )
  
  # 重试逻辑
  for (attempt in 1:max_retry) {
    # 发送请求
    response <- try(GET(webpage, browser_headers), silent = TRUE)
    
    # 处理请求错误
    if (inherits(response, "try-error")) {
      Sys.sleep(runif(1, 1.5, 3))
      next
    }
    
    # 检查响应状态码
    if (status_code(response) == 200) {
      page <- content(response, "parsed")
      title_node <- html_node(page, section)
      return(ifelse(is.null(title_node), NA_character_, html_text(title_node)))
    } else if (status_code(response) == 404) {
      # 遇到404随机等待后重试
      Sys.sleep(runif(1, 2, 4))
    } else {
      # 其他异常状态码直接返回NA
      return(NA_character_)
    }
  }
  
  # 多次重试失败返回NA
  return(NA_character_)
}

# 改进后的爬取循环
standard_titles <- c()
for (url in standard_ad) { 
  # 每次请求前随机等待1-3秒
  Sys.sleep(runif(1, 1, 3))
  collected_title <- collect(url, '.ui-pdp-title')
  standard_titles <- c(standard_titles, collected_title)
}

额外注意事项

  • 随机等待时间建议设置在1-5秒区间,不要过短,避免触发反爬;
  • User-Agent可以定期替换为最新的浏览器标识,避免被网站列入爬虫黑名单;
  • 若爬取量较大,可分批次处理URL,每爬取20-30个URL后暂停一段时间;
  • 不要在短时间内重复运行爬取代码,给网站服务器留缓冲时间。

内容的提问来源于stack exchange,提问作者Marina Bonatti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:25:08