スクレイピングしてDBに保存したい人向けです
外部からデータ取ってくることに憧れてたので、初めてスクレイピングやった忘備録です。
初めてスクレイピングしたのでおてやわらかにお願いします笑
何をスクレイピングしたの?
paypayのキャンペーンwebページから店舗名を取得しました!
スクレイピング前のDB
スクレイピング後のDB
手順
- nokogiriでweb上のテキストを配列形式で取得する
- ↑の配列をactiverecord-importで一度のクエリで保存する
環境
- sqlite3
- ruby 2.6.3
- Rails 6.0.2.1
Gemfile.
gem 'activerecord-import'
gem 'nokogiri'
bundle install
しといてください!
まずはスクレイピングしてみる
今回はcontrollerから呼び出したかったので、moduleとして作成します。
app/controllers/concerns/paypay_scrapes_concern.rb
module PaypayScrapesConcern
require 'open-uri'
require 'nokogiri'
def scrape_paypay_shops
url = 'https://paypay.ne.jp/notice/20200604/01/'
charset = nil
html = open(url) do |f|
charset = f.charset
f.read
end
doc = Nokogiri::HTML.parse(html, nil, charset)
@shops = doc.xpath('//div[@class="article__contents post"]').css('tr').map do |node|
@shops << node.css("td[1]").text
end.drop(1)
end
end
結果を確認してみます。
$ ruby paypay_scrapes_concern.rb
=> ["あさひ", "味千ラーメン 掛川インター店", "遠州屋", "株式会社縁 開縁ダイニング縁や", "大石農場ハム工房", "大手門うおそう", "OZ", "KAKEGAWA 1番地", "掛川グランドホテル", "華月苑", "インド・ネパール料理レストラン GANESHA", "かねきや旅館", "カレー・ザ・ロック", "喜縁旬菜 ZIKAN", "喬菜 まさ吉", "餃子と串カツ 遠州誠家", "串&Bar FuQ(ふく)", "琴菊", "ことのや", "魚処 粋", "椎の木茶屋", "真味楼", "寿し処 八幡", "タナカ", "中国料理四川", "戸塚屋", "巴屋", "ナムズ", "にんちゃんち ", "ひいらぎや", "ファニーファーム", "Food Labo 房’s", "ふらっと", "ベル・エポック", "MAX'S DINER", "まるましらすや", "麺屋 RiQ", "八咫烏", "ラーメン 男前", "らーめん若虎", "LA MAREA 1980 DAN"]
controllerに新しくメソッド追加
shops_controller.rb
def create_paypay_shops
@shops = scrape_paypay_shops
shops = []
@shops.each do |shop|
shops << Shop.new(name: shop)
end
# DBアクセス一回で配列を保存できるgem activerecord-import
Shop.import shops
end
こんな感じで保存できると思います。
今後はDBのバリデーションとかもやりたいですね。笑
2021.03.09 追記 Activerecord-importの書き方について
Activerecord-importの公式ドキュメントによると、columns-and-arraysが一番早いそうですね。
shops_controller.rb
def paypay_save
@shops = scrape_paypay_shops
shops = []
@shops.each do |shop|
shops << Shop.new(name: shop)
end
# DBアクセス一回で配列を保存できるgem activerecord-import
Shop.import shops
end
# ↑をリファクタリングしてみましょう
def paypay_save
# eachの中でShop.newをしないことでパフォーマンス改善
Shop.import [:name], [scrape_paypay_shops]
end
重複していたらupdateしたりignoreするコマンドもあるみたいなので試してみてください!
参考
https://morizyun.github.io/blog/ruby-nokogiri-scraping-tutorial/index.html
https://qiita.com/superman9387/items/1981a24664b260e77238
https://qiita.com/makicamel/items/b6d4f3d2661fc66103ed