首页 > 解决方案 > 如何将 URL 数组作为函数的参数传递

问题描述

我想将我的第一个函数返回的 URL 数组传递给我的第二个函数,但是我不确定如何执行此操作。

require 'open-uri'
require 'nokogiri'
require 'byebug'

def fetch_recipe_urls
  base_url = 'https://cooking.nytimes.com'
  easy_recipe_url = 'https://cooking.nytimes.com/search?q=easy'
  easy_searchpage = Nokogiri::HTML(open(easy_recipe_url))
  recipes = easy_searchpage.search('//article[@class="card recipe-card"]/@data-url')
  recipes_url_array = recipes.map do |recipe|
    uri = URI.parse(recipe.text)
    uri.scheme = "http"
    uri.host = "cooking.nytimes.com"
    uri.query = nil
    uri.to_s
  end

end

def scraper(url)
  html_file = open(url).read
  html_doc = Nokogiri::HTML(html_file)
  recipes = Array.new
  recipe = {
    title: html_doc.css('h1.recipe-title').text.strip,
    time: html_doc.css('span.recipe-yield-value').text.split("servings")[1],
    steps: html_doc.css('ol.recipe-steps').text.split.join(" "),
    ingredients: html_doc.css('ul.recipe-ingredients').text.split.join(" ")
  }

  recipes << recipe
end

标签: arraysrubynokogiri

解决方案


由于调用后有一个数组fetch_recipe_urls,因此可以迭代并调用scraper其中的每个 URL:

def scraper(url)
  html_file = open(url).read
  html_doc = Nokogiri::HTML(html_file)

  {
    title: html_doc.css('h1.recipe-title').text.strip,
    time: html_doc.css('span.recipe-yield-value').text.split("servings")[1],
    steps: html_doc.css('ol.recipe-steps').text.split.join(" "),
    ingredients: html_doc.css('ul.recipe-ingredients').text.split.join(" ")
  }
end

fetch_recipe_urls.map { |url| scraper(url) }

但我实际上会将代码构造为:

BASE_URL = 'https://cooking.nytimes.com/'

def fetch_recipe_urls
  page = Nokogiri::HTML(open(BASE_URL + 'search?q=easy'))
  recipes = page.search('//article[@class="card recipe-card"]/@data-url')
  recipes.map { |recipe_node| BASE_URL + URI.parse(recipe_node.text).to_s }
end

def scrape(url)
  html_doc = Nokogiri::HTML(open(url).read)

  {
    title: html_doc.css('h1.recipe-title').text.strip,
    time: html_doc.css('span.recipe-yield-value').text.split("servings")[1],
    steps: html_doc.css('ol.recipe-steps').text.split.join(" "),
    ingredients: html_doc.css('ul.recipe-ingredients').text.split.join(" ")
  }
end

fetch_recipe_urls.map { |url| scrape(url) }

您也可以调用scrape/ scraperinside fetch_recipe_urls,但我建议采用单一责任方法。一个更好的主意是制作这个 OOP 并构造一个Scraper类和一个CookingRecipe更符合习惯的方法。


推荐阅读