78143


**環境**

ruby 2.7.2  
rails 6.1  
macOS

**前提**

ポートフォリオ作成のため、現在自作アプリを実装しております。  
その中で、DBに必要なデータを保存するため、Rubyのnokogiriでスクレイピングを行なっています。

**解決したいこと**

`<a class="flower-
spot"`内のhref属性の値を取得し、その値をもとに`link_url`を作成して遷移を行い、遷移後のページから必要なデータをDBに保存。  
それを同名クラスの数だけ繰り返したいです。

[![画像の説明をここに入力](https://i.stack.imgur.com/5kyXR.png)](https://i.stack.imgur.com/5kyXR.png)

**試したこと**

nokogiriに関連する記事を調べ、下記コードを作成した所、必要なデータをDBに保存することはできました。  
しかし、コードが冗長で見辛くなっているため、改善したいです。  
詳しい方がいましたら是非アドバイスいただけると幸いです。  
何卒よろしくお願いします。

**該当するソースコード**

`db/schema.rb`

[code]

    create_table "spots", force: :cascade do |t|
        t.string "name", null: false
        t.string "location", null: false
        t.text "feature", null: false
        t.string "image"
        t.string "url"
        t.float "latitude"
        t.float "longitude"
        t.datetime "created_at", precision: 6, null: false
        t.datetime "updated_at", precision: 6, null: false
        t.integer "area_id"
        t.index ["area_id"], name: "index_spots_on_area_id"
      end
    
[/code]

`app/models/scraping.rb`

[code]

    class Scraping < ApplicationRecord
      require 'open-uri'
      require 'nokogiri'
    
      def self.spot_scrape
        base_url = 'https://loconavi.jp/'
        features_url = 'features/hananomeisho'
        url = "#{base_url}#{features_url}?flower=229"
    
        html = URI.open(url).read
        doc = Nokogiri::HTML.parse(html)
        # href属性値の取得(相対URL)
        # _[0]_として一番目のflower-spotクラスを対象
        href = doc.css('.flower-spot')[0]["href"]
        # 相対URLから絶対URLを作成
        link_url = "#{base_url}#{href}"
    
        html = URI.open(link_url).read
        doc = Nokogiri::HTML.parse(html)
    
        doc.css('.main-left-layout').each do | node |
          sleep 1
          # DBに取得したデータを保存
          Spot.create!(
            name: node.at_css('.block').inner_text,
            location: node.css('.t-cell')[2].inner_text,
            feature: node.at_css('.text').inner_text,
            image: node.at_css('img').attribute('src'),
            url: node.at_css('#information p a')["href"]
          )
        end
    
        html = URI.open(url).read
        doc = Nokogiri::HTML.parse(html)
        href = doc.css('.flower-spot')[1]["href"]
        link_url = "#{base_url}#{href}"
    
        html = URI.open(link_url).read
        doc = Nokogiri::HTML.parse(html)
    
        doc.css('.main-left-layout').each do | node |
          sleep 1
          Spot.create!(
            name: node.at_css('.block').inner_text,
            location: node.css('.t-cell')[2].inner_text,
            feature: node.at_css('.text').inner_text,
            image: node.at_css('img').attribute('src'),
            url: node.at_css('#information p a')["href"]
          )
        end
    
        html = URI.open(url).read
        doc = Nokogiri::HTML.parse(html)
        href = doc.css('.flower-spot')[2]["href"]
        link_url = "#{base_url}#{href}"
    
        html = URI.open(link_url).read
        doc = Nokogiri::HTML.parse(html)
    
        doc.css('.main-left-layout').each do | node |
          sleep 1
          Spot.create!(
            name: node.at_css('.block').inner_text,
            location: node.css('.t-cell')[2].inner_text,
            feature: node.at_css('.text').inner_text,
            image: node.at_css('img').attribute('src'),
            url: node.at_css('#information p a')["href"]
          )
          break
        end
      end
    
[/code]


CC BY-SA 4.0
2021-07-12T14:01:12.847
78137
2021-07-13T00:37:08.130
2021-07-12T21:42:50.987
46968
46968
question
ruby-on-rails ruby web-scraping rubygems nokogiri
同名クラスをもつ複数のaタグを順番に繰り返し処理し、必要なデータをDBに保存したい


冗長というのは、次の行の

[code]

        href = doc.css('.flower-spot')[0]["href"]
    
[/code]

`[0]` の部分が `0`, `1`, `2` と異なるだけで、他はまったく同じ処理が3回繰り返されているということだと思います。

`times` を使うと、

[code]

    3.times do |i|
      # i の値が 0, 1, 2 と変化して繰り返す
    end
    
[/code]

のように書けるので、次のようにループにすることができます。

[code]

      3.times do |i|
        html = URI.open(url).read
        doc = Nokogiri::HTML.parse(html)
        href = doc.css('.flower-spot')[i]["href"]  # ここで 0, 1, 2 の代わりに i を使う
        link_url = "#{base_url}#{href}"
    
        html = URI.open(link_url).read
        doc = Nokogiri::HTML.parse(html)
    
        doc.css('.main-left-layout').each do | node |
          sleep 1
          Spot.create!(
            name: node.at_css('.block').inner_text,
            location: node.css('.t-cell')[2].inner_text,
            feature: node.at_css('.text').inner_text,
            image: node.at_css('img').attribute('src'),
            url: node.at_css('#information p a')["href"]
          )
        end
      end
    
[/code]


CC BY-SA 4.0
2021-07-13T00:37:08.130
78143
2021-07-13T00:37:08.130
3249
78137
answer