Руби каждый цикл не заканчивается для каждого элемента - PullRequest
1 голос
/ 24 января 2011

следующий код:

# fetch the top 300 podcasts from itunes
itunes_top_300 = Nokogiri.HTML(open("http://itunes.apple.com/us/rss/toppodcasts/limit=25/xml"))

# parse the returned xml with nokogiri
itunes_top_300.xpath('//feed/entry').each do |entry|
  name = entry.xpath("//name").text
  url = entry.xpath("//link/@href").text
  category = entry.xpath("//category/@term").text
  hosts = entry.xpath("//artist").text
  summary = entry.xpath("//summary").text
  artwork = entry.xpath("//image[@height='170']").text
  return name + url
end

Выводит в виде:

iTunes StoreЭта американская жизньNPR: Подождите, подождите ... Не говорите мне! PodcastStuff, о котором вы должны знать Freakonomics RadioNPR: Свежий воздух PodcastNPR: Автомобильные разговоры Подкаст-радиостанция WNYC Подразумеваемые MePearls перед мультфильмами для свинейМолотка PodcastAPM: Новости домашнего компаньона прерии от Лейк-ВобегонГарри Поттер 1–5 лет Подкаст-переводчик на сайте TheЦессионет - Герои TakersNPR: Подкаст «Планета денег», который вы пропустили в уроке историиОбзор шоу Дэйва РэмсиГлобальные новостиВампиры сосут клипыNPR: Научный пятничный подкастДругие ребята разбиваются и сгораютВернуться к работеNPR: Все песни считаются подкастомNPR: Концертный стол под крошечные подкасты http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewTop?id=38&popId=3http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppodcasts/limit=25/xml?cc=ushttp://itunes.apple.com/us/podcast/this-american-life/id201671138?uo=2&uo=2http://itunes.apple.com/us/podcast/npr-wait-wait-dont-tell-me/id121493804?uo=2&uo=2http://itunes.apple.com/us/podcast/stuff-you-should-know/id278981407?uo=2&uo=2http://itunes.apple.com/us/podcast/freakonomics-radio/id354668519?uo=2&uo=2http://itunes.apple.com/us/podcast/npr-fresh-air-podcast/id214089682?uo=2&uo=2http://itunes.apple.com/us/podcast/npr-car-talk-podcast/id253191823?uo=2&uo=2http://itunes.apple.com/us/podcast/wnycs-radiolab/id152249110?uo=2&uo=2http://itunes.apple.com/us/podcast/despicable-me/id399247154?uo=2&uo=2http://itunes.apple.com/us/podcast/pearls-before-swine-animated/id409382502?uo=2&uo=2http://itunes.apple.com/us/podcast/the-moth-podcast/id275699983?uo=2&uo=2http://itunes.apple.com/us/podcast/apm-a-prairie-home-companions/id215352157?uo=2&uo=2http://itunes.apple.com/us/podcast/harry-potter-years-1-5-podcast/id322144752?uo=2&uo=2http://itunes.apple.com/us/podcast/ace-on-the-house/id414294132?uo=2&uo=2http://itunes.apple.com/us/podcast/takers-takers-featurette-executing/id412910974?uo=2&uo=2http://itunes.apple.com/us/podcast/npr-planet-money-podcast/id290783428?uo=2&uo=2http://itunes.apple.com/us/podcast/stuff-you-missed-in-history/id283605519?uo=2&uo=2http://itunes.apple.com/us/podcast/the-dave-ramsey-show/id77001367?uo=2&uo=2http://itunes.apple.com/us/podcast/book-review/id120315179?uo=2&uo=2http://itunes.apple.com/us/podcast/global-news/id135067274?uo=2&uo=2http://itunes.apple.com/us/podcast/vampires-suck-clips/id405404825?uo=2&uo=2http://itunes.apple.com/us/podcast/npr-science-friday-podcast/id73329284?uo=2&uo=2http://itunes.apple.com/us/podcast/other-guys-crash-and-burn/id407622041?uo=2&uo=2http://itunes.apple.com/us/podcast/back-to-work/id415535037?uo=2&uo=2http://itunes.apple.com/us/podcast/npr-all-songs-considered-podcast/id79687345?uo=2&uo=2http://itunes.apple.com/us/podcast/npr-tiny-desk-concerts-podcast/id362115318?uo=2&uo=2

Вы можете видеть, что он получает имя для всех элементов, прежде чем перейти к URL. Я хочу, чтобы он оценил имя, а затем URL и т. Д. Для каждого элемента, прежде чем переходить к следующему. Что я делаю не так.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 24 января 2011

Есть несколько причин этой проблемы. Во-первых, когда вы используете return внутри каждого цикла, вы фактически разрываете его, поэтому он повторяется только один раз, а не 25 раз.

Во-вторых, вы можете не заметить, что он запускается только один раз, потому что когда вы используете // имя в xpath, он возвращает все имена.

Возможно, вы могли бы сделать что-то вроде этого:

# Returns top 25 since the url includes limit=25
itunes_top_25 = Nokogiri.XML(open("http://itunes.apple.com/us/rss/toppodcasts/limit=25/xml"))

names_and_urls = itunes_top_25.xpath('//feed/entry').map do |entry|
  name = entry.xpath("./name").text
  url = entry.xpath("./link/@href").text
  category = entry.xpath("./category/@term").text
  hosts = entry.xpath("./artist").text
  summary = entry.xpath("./summary").text
  artwork = entry.xpath("./image[@height='170']").text
  [name, url]
end    

Я изменил // имя на ./name, чтобы оно возвращалось только для текущего узла. Я также изменил каждый на map, чтобы он назначал переменную массиву со всеми значениями, возвращаемыми блоком. И я удалил звонок, чтобы вернуться, так как это не нужно.

Таким образом, это приведет к массиву массивов, содержащих имена и URL-адреса

1 голос
/ 24 января 2011

Вызывая return, вы останавливаете цикл each на первой итерации.Возможно, ты не хотел этого.Кроме того, используя xpath //name внутри цикла, вы начинаете с начала документа и находите каждый элемент имени во всем документе.Следовательно, когда вы находите первый <entry>, вы затем возвращаете массив, сформированный путем объединения массива каждого <name> элемента в документе с массивом каждого <url> элемента в документе.

Возможно, выхотите ли это:

require 'nokogiri'
require 'open-uri'
# fetch the top 300 podcasts from itunes
# Use XML instead of HTML
itunes_top_300 = Nokogiri::XML(open("http://itunes.apple.com/us/rss/toppodcasts/limit=25/xml"))
itunes_top_300.remove_namespaces!

itunes_top_300.xpath('//entry').each do |entry|
  name = entry.xpath("name").text
  url = entry.xpath("link/@href").text
  puts "#{name}: #{url}"
end
#=> This American Life: http://itunes.apple.com/us/podcast/this-american-life/id201671138?uo=2&uo=2
#=> NPR: Wait Wait... Don't Tell Me! Podcast: http://itunes.apple.com/us/podcast/npr-wait-wait-dont-tell-me/id121493804?uo=2&uo=2
#=> Stuff You Should Know: http://itunes.apple.com/us/podcast/stuff-you-should-know/id278981407?uo=2&uo=2

... или, возможно, это:

# Convert XML entries into an array of hashes
parsed = itunes_top_300.xpath('//entry').map do |entry|
  name = entry.xpath("name").text
  url = entry.xpath("link/@href").text
  { name:name, url:url }
end

require 'pp'
pp parsed[0..3]
#=> [{:name=>"This American Life",
#=>   :url=>"http://itunes.apple.com/us/podcast/this-american-life/id201671138?uo=2&uo=2"},
#=>  {:name=>"NPR: Wait Wait... Don't Tell Me! Podcast",
#=>   :url=>"http://itunes.apple.com/us/podcast/npr-wait-wait-dont-tell-me/id121493804?uo=2&uo=2"},
#=>  {:name=>"Stuff You Should Know",
#=>   :url=>"http://itunes.apple.com/us/podcast/stuff-you-should-know/id278981407?uo=2&uo=2"},
#=>  {:name=>"Freakonomics Radio",
#=>   :url=>"http://itunes.apple.com/us/podcast/freakonomics-radio/id354668519?uo=2&uo=2"}]
0 голосов
/ 24 января 2011

Вы объявляете переменные с тем, что вам нужно, а затем выбрасываете их, потому что вместо этого вы только return name + url.

пытаетесь return name + url + category + thing1 + thing2

еще лучше

return [url,category,thing1,thing2]

...