クローリングで得たデータをデータベースに挿入する
今回はクローリングで得たデータをデータベースに挿入してみる。
目次
準備
PostgreSQLをインストールする
PostgreSQLのWebサイトは以下のとおり。
https://www.postgresql.org/
日本語のサイト
日本PostgreSQLユーザー会
https://www.postgresql.jp/
このブログでもインストール方法や使い方を記事にしている。
Windows10にPostgreSQLをインストールする - ローイングファンの日記
macOS10にPostgreSQLをインストールする - ローイングファンの日記
PostreSQLにデータベースとテーブルをつくる
今回はデータベース名sampledb、テーブル名sampledbsをつくっておく。
データベースとテーブルの作り方は前に書いた。
PostgreSQLのデータベースをつくる - ローイングファンの日記
PostgreSQLにテーブルをつくる - ローイングファンの日記
テーブルの内容は次のとおり。
create_sampledbs.sql
create table sampledbs( id serial primary key, column1 text, column2 text );
Active Recordをインストールする
Active RecordはBundlerの--pathオプションつきでインストールした。
今回のようにPostgreSQLを操作する場合はPgのインストールも必要。
Active Recordの解説ページは以下のとおり。
Ruby on Rails ガイド
Active Record の基礎
https://railsguides.jp/active_record_basics.html
このブログでもインストールや使い方を何度か記事にしている。
Bundlerを使ってgemをインストールする - ローイングファンの日記
RubyからPostgreSQLを操作する - ローイングファンの日記
Active RecordでPostgreSQLを操作する - ローイングファンの日記
あいまい検索 Active Record where like - ローイングファンの日記
クローリングで得た情報をPostgreSQLに挿入するコード
今回はクローリングにopen-uriライブラリを使う。
コードを書く。
crawl.rb
require 'open-uri' require 'active_record' #PostgreSQLに接続 ActiveRecord::Base.establish_connection( #項目は環境に応じて書きかえる adapter: "postgresql", host: "", username: "Username", password: "", database: "sampledb" ) class Sampledb < ActiveRecord::Base end #クラスを定義する class Crawler def initialize #巡回したいURLを配列に格納する @urls = [ "URL1", "URL2", "URL3", ] end #crawlで得た情報を配列に格納するまでのメソッドを定義する def collector collections = [] @urls.each do |url| begin open(url,"r:utf-8") do |html| readhtml = html.read scandatas = [] s1 = readhtml.scan(/<title>(.*)<\/title>/) s2 = readhtml.scan(/<h1>(.*)<\/h1>/) scandatas << s1 << s2 collections << scandatas.flatten end rescue next end sleep(1) end collections end end crawler = Crawler.new collections = crawler.collector collections.each do |collection| Sampledb.create( column1: collection[0], column2: collection[1] ) end records = Sampledb.all records.each do |record| puts "s1 => #{record['column1']} : s2 => #{record['column2']}" end
コードの説明
コードの説明は次のとおり。
- open-uriとActive Recordをrequireする
- PostgreSQLに接続する
- host、passwordは必要に応じて記入する
- クラスを定義する
- 初期設定(newメソッド)をinitializeで定義する
- 巡回したいWebページのURLを配列に格納してインスタンス変数を初期化する
- HTMLから必要な情報を抽出して配列に格納するメソッドを定義する
- 全てを収める配列をループの外で初期化しておく
- URLの入った配列をループさせる
- ファイル(URL)が開けなかったときに備えて
begin rescue
で例外処理を設定する - open-uriライブラリのopenメソッドでHTMLを取得する
r:utf-8
オプションをつけないとHTMLがバイト列になってしまう
- 抽出するデータを収める配列をループ内で初期化する
- 抽出したいデータをscanメソッドで抜き取る
- 正規表現のキャプチャをつかう
- 抽出したデータを
<<
メソッドで配列に格納する - 抽出したデータが格納された配列を全体を収める配列に格納する
- rescue節 ファイルが開けなかったときは
next
で次のeach(URL)に進む - 1秒間sleepしてクローリングの間隔をおく
- 最後に全体が収まった配列を呼び出しておく
- 初期設定(newメソッド)をinitializeで定義する
- 定義したCrawlerクラスのインスタンスをnewメソッドでつくる
- 定義したcollectorメソッドを実行する
- collectorメソッドでつくられた配列からeachメソッドでデータを取りだす
- 取りだしたデータをActive Recordのcreateメソッドでデータベースに挿入していく
- データベースの全てのレコードをallメソッドで取りだす
- 全てのレコードをeachメソッドでループして1行ずつputsメソッドで出力していく
補則説明
- Pgはインストールするだけでrequireは不要
- ループの外で初期化された配列には要素が蓄積されていき、ループ内で初期化される配列は繰り返しのつど空になる
- 確認の意味で最後にレコードを出力している
コードの実行
Rubyコードを実行する前にPostgreSQLサーバーを起動しておく。
Active Recordをbundle install --path ...
でインストールしている場合はRubyコマンドの前にbundle exec
コマンドをつける。
ターミナル/PowerShell
bundle exec ruby crawl.rb
ターミナル/PowerShellに出力されれば成功。
scanメソッド部分をアレンジすれば応用が可能。
scanメソッドに合わせてデータベースのテーブルを定義する。
一応うごくけれどクラス定義はうまくない。改善が必要。
今回の動作確認環境
macOS 10.13.4
Ruby 2.4.4p296
ターミナル 2.8.2
Windows10 1709
Ruby 2.5.1p57 [x64-mingw32]
Windows PowerShell 5.1
PostgreSQL 10.3
Active Record 5.2.0
Pg 1.0.0