概要
一時期呼吸するようにスクレイピングをしていたのですが、最近しておらず職場で少々それ関係の話題になったのであらためてここに簡単なものを残しておこうと思う。
環境
ruby 3.1.2
準備
rubyなのでGemfileを定義します。
Gemfile
source 'https://rubygems.org'
gem 'nokogiri'
HTMLのパースのためにnokogiriを使うのでこれだけ用意します。
ほかは標準で入っているものでjsonのパースとかしてくれる(強い)
作業ディレクトリで下記のコマンドを実行
bundle install --path .bundle
ただのbundle installだとグローバルに入っちゃったりするので、パス指定しておくほうがおすすめです。
実装
では、結論から
require 'net/http'
require 'uri'
require 'nokogiri'
require 'kconv'
require 'json'
require 'pp'
uri = URI.parse("https://tabelog.com/kanagawa/A1401/A140101/14011244/")
request = Net::HTTP::Get.new(uri)
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
doc = Nokogiri::HTML.parse(response.body.toutf8, nil, 'utf-8')
p '###ページタイトル取得###'
p doc.title
json = JSON.parse(doc.css('script[type="application/ld+json"]')[0])
p '###お店の名前を取得###'
p json['name']
p '###画像の一覧を取得###'
doc.css('.js-mainphoto-slider img').map do |img|
p img['src']
end
これで食べログのある飲食店の店の名前と使われている画像の一覧(URL)を取得できます。
結果
###ページタイトル取得###
おでんと庭先地鶏 はれ晴れ 横浜店 (はればれ) - 横浜/居酒屋/ネット予約可 | 食べログ
###お店の名前を取得###
おでんと庭先地鶏 はれ晴れ 横浜店
###画像の一覧を取得###
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/132571/132571144.jpg?token=20cb762&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/24900/24900734.jpg?token=b9868a4&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/56132/56132013.jpg?token=fe9448b&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/78170/78170969.jpg?token=3fd4c48&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/56132/56132018.jpg?token=b87b67e&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/164984/a21f498d57e0457c36be973f135bac48.jpg?token=d673ae7&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/180013/db2d95a874b50da3583495e37adadb02.jpg?token=c6f6e88&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/183264/b46e2b28ba4a9198d62b3bae77ce86f7.jpg?token=3291219&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/183264/f1706f12f7eaf63b6103aa6ef52db217.jpg?token=13b84c0&api=v2
https://tblg.k-img.com/resize/660x370c/restaurant/images/Rvw/183334/7a5fd20ba0cc51c95fae81fece7c9475.jpg?token=13ebd97&api=v2
解説
軽くコードの解説します。
1. ページ情報の取得
まず、何はともあれページの情報をとってくる必要があります。
リクエスト用のGemなどもありますが、標準で入っているnet/httpがただのリクエスト飛ばすのにはわかりやすいのでこちらを利用。
URLを指定し、Getのリクエストでページの情報を取得してます。
uri = URI.parse("https://tabelog.com/kanagawa/A1401/A140101/14011244/")
request = Net::HTTP::Get.new(uri)
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
2. 取得したHTMLを解析
上記で取得したページ情報からbody情報を使います。
また、その際に.toutf8
してましてこれをしておくとshift-jisとかのものもutf-8にしてくれてその後の処理で文字化けてるとか言う悲しい気持ちにならないで済みます。
doc = Nokogiri::HTML.parse(response.body.toutf8, nil, 'utf-8')
3. 情報の取得
もうここからはなんの情報がほしいかっていうここの要件に関わる部分になります。
パターンがおおいほうが幸せな人もおおいかなと思っていくつか書いてます。
p '###ページタイトル取得###'
p doc.title
json = JSON.parse(doc.css('script[type="application/ld+json"]')[0])
p '###お店の名前を取得###'
p json['name']
p '###画像の一覧を取得###'
doc.css('.js-mainphoto-slider img').map do |img|
p img['src']
end
1個目はnokogiriの方の機能でページのタイトルをとってくるものになってます。
2個目はページの中に埋め込まれているjson情報をパースしてそこから情報を取得しています。
3個目はhtmlの中から特定の要素をセレクタ指定してとってきています。
大体この3パターンを抑えておけばあとは自力で情報までたどりつけるかと.....