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

Ruby on Rails使用Nokogiri爬取图片src后无法保存并展示:报Nil location provided错误

解决Rails中Nokogiri爬取图片时的「Nil location provided」错误

看起来你遇到的这个「Nil location provided. Can't build URI.」错误,主要是因为图片链接处理不严谨,再加上视图里的语法问题导致的,咱们一步步来修复:

错误根源分析

  1. 图片链接为空/无效:当Nokogiri找不到目标img元素,或者src属性为空时,拼接后的image_url会变成无效的URI(比如空字符串或者https://www.jacadi.fr),image_tag处理这种值就会抛出错误。
  2. 循环覆盖属性:你的控制器里用each循环给@product的属性赋值,最后只会保留最后一个循环项的值,如果最后一个图片链接无效,就会导致image_url异常。
  3. 选择器语法错误:你写的css("j-wrapper-content")和css("j-prd-price p")缺少类选择器的.前缀,Nokogiri根本找不到对应的元素,会导致name和price为空。
  4. 视图语法错误:elsif后面没有任何条件判断,这会直接导致视图渲染失败。

完整修复方案

1. 修正控制器代码(处理爬取逻辑)

def scrape
  # 先校验page_url的有效性,避免URI.open直接报错
  return unless page_url.present? && page_url.start_with?('http')

  doc = Nokogiri::HTML(URI.open(page_url))
  # 修正类选择器:添加.前缀,确保能找到目标元素
  items = doc.css(".j-wrapper-content")
  images = doc.css("div.j-img")

  # 处理图片:只取第一个有效的图片链接(按需调整是否要所有图片)
  images.each do |image|
    # 先拿到第一个img元素,避免NodeSet空值问题
    img_element = image.css("img").first
    next unless img_element

    # 清理src值,过滤空字符串
    link = img_element.attr('src').to_s.strip
    next if link.empty?

    # 兼容绝对路径和相对路径,避免重复拼接域名
    @product.image_url = if link.start_with?('http', '//')
                           # 处理//开头的协议相对路径
                           link.start_with?('//') ? "https:#{link}" : link
                         else
                           "https://www.jacadi.fr#{link}"
                         end
    break # 只取第一个有效图片,不需要所有的话就保留这个break
  end

  # 处理产品信息:同样取第一个有效商品数据
  items.each do |item|
    @product.name = item.css("h1").text.strip
    price_text = item.css(".j-prd-price p").text.strip
    # 避免空字符串转float报错
    @product.price = price_text.to_f if price_text.present?
    break # 只取第一个商品,按需移除
  end

  # 保存前做基础校验,避免save!抛出异常
  if @product.name.present? && (@product.image_url.present? || @product.picture.attached?)
    @product.save!
  else
    flash[:alert] = "未能获取有效的产品信息,请检查爬取目标页面结构是否变更"
  end
end

2. 修正视图代码(修复语法错误)

把elsif后面补全条件判断,确保只有当image_url存在时才渲染外部图片:

<% if product.picture.attached? %>
  <%= image_tag(product.picture, class: "card-pict") %>
<% elsif product.image_url.present? %>
  <%= image_tag(product.image_url, class: "card-pict") %>
<% else %>
  <%= image_tag("gift.png", class: "card-pict mini") %>
<% end %>

额外提示

  • 如果需要批量爬取多个产品,不要在循环里复用同一个@product实例,应该在循环内初始化新的Product.new并保存。
  • 爬取外部网站时,最好加上请求头(比如User-Agent),避免被目标网站拦截:
    doc = Nokogiri::HTML(URI.open(page_url, "User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"))
    

内容的提问来源于stack exchange,提问作者Ludovic Villain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:49:09