rubyクローラー データをmysql保存時のエラー解決方法について
受付中
回答 0
投稿
- 評価
- クリップ 1
- VIEW 1,098
前提・実現したいこと
ruby初心者でクローラーを作成してます。
その中でWebから取得した情報をmysqlに登録する箇所でエラーが発生しました。
発生している問題・エラーメッセージ
/Users/hiroyuki/.rbenv/versions/2.1.3/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': /Users/hiroyuki/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/anemone-0.7.2/lib/anemone/storage/mysql.rb:105: can't find string "SQL" anywhere before EOF (SyntaxError)
/Users/hiroyuki/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/anemone-0.7.2/lib/anemone/storage/mysql.rb:82: syntax error, unexpected end-of-input, expecting tSTRING_CONTENT or tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
from /Users/hiroyuki/.rbenv/versions/2.1.3/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Users/hiroyuki/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/anemone-0.7.2/lib/anemone/storage.rb:44:in `MySQL'
from anemone-mysql.rb:8:in `<main>'
該当のソースコード
require 'anemone'
urls = []
urls.push("http://www.yahoo.co.jp")
opts = {
:storage => Anemone::Storage::MySQL(),
:depth_limit => 0
}
Anemone.crawl(urls, opts) do |anemone|
anemone.on_every_page do |page|
puts page.url
puts page.doc.xpath("//title/text()").to_s if page.doc
end
end
試したこと
補足情報(言語/FW/ツール等のバージョンなど)
関係ファイルのソースコードを下記に記載します。
mysql.rb
begin
require 'mysql2'
rescue LoadError
puts "You need the mysql2 gem to use Anemone::Storage::MySQL"
exit
end
module Anemone
module Storage
class MySQL
def initialize(opts = {})
host = opts[:host] || 'localhost'
username = opts[:username] || 'crawler'
password = opts[:password] || 'anemone_pass'
database = opts[:database] || 'anemone'
@db = Mysql2::Client.new(:host => host, :username => username, :password => password, :database => database)
create_schema
end
def [](url)
value = @db.query("SELECT data FROM anemone_storage WHERE page_key = '#{get_hash_value(url)}'").first['data']
if value
Marshal.load(value)
end
end
def []=(url, value)
data = Marshal.dump(value)
key = get_hash_value(url)
if has_key?(url)
@db.query("UPDATE anemone_storage SET page_data = '#{data}' WHERE page_key = '#{key}'")
else
@db.query("INSERT INTO anemone_storage (page_key, page_data) VALUES('#{key}', '#{data}')")
end
end
def delete(url)
page = self[url]
@db.query("DELETE FROM anemone_storage WHERE page_key = '#{get_hash_value(url)}'")
page
end
def each
@db.execute("SELECT page_key, page_data FROM anemone_storage ORDER BY id") do |row|
value = Marshal.load(row[1])
yield row[0], value
end
end
def merge!(hash)
hash.each { |key, value| self[key] = value }
self
end
def size
@db.query('SELECT COUNT(*) FROM anemone_storage')
end
def keys
@db.query("SELECT page_key FROM anemone_storage ORDER BY id").map{|t| t[0]}
end
def has_key?(url)
key = get_hash_value(url)
result = @db.query("SELECT count(id) FROM anemone_storage WHERE page_key = '#{key}'")
if result.first['count(id)'] > 0
return true
else
return false
end
end
def close
@db.close
end
private
def create_schema
@db.query <<-SQL
create table if not exists anemone_storage (
id int(11) NOT NULL auto_increment,
page_key varchar(255),
page_data BLOB,
PRIMARY KEY (id),
key (page_key)
) DEFAULT CHARSET=utf8;SQL
end
def load_page(hash)
BINARY_FIELDS.each do |field|
hash[field] = hash[field].to_s
end
Page.from_hash(hash)
end
def get_hash_value(key)
Digest::SHA1.hexdigest(key)
end
end
end
end
storage.rb
module Anemone
module Storage
def self.Hash(*args)
hash = Hash.new(*args)
add close method for compatibility with Storage::Base
class << hash; def close; end; end
hash
end
def self.PStore(*args)
require 'anemone/storage/pstore'
self::PStore.new(*args)
end
def self.TokyoCabinet(file = 'anemone.tch')
require 'anemone/storage/tokyo_cabinet'
self::TokyoCabinet.new(file)
end
def self.KyotoCabinet(file = 'anemone.kch')
require 'anemone/storage/kyoto_cabinet'
self::KyotoCabinet.new(file)
end
def self.MongoDB(mongo_db = nil, collection_name = 'pages')
require 'anemone/storage/mongodb'
mongo_db ||= Mongo::Connection.new.db('anemone')
raise "First argument must be an instance of Mongo::DB" unless mongo_db.is_a?(Mongo::DB)
self::MongoDB.new(mongo_db, collection_name)
end
def self.Redis(opts = {})
require 'anemone/storage/redis'
self::Redis.new(opts)
end
def self.SQLite3(file = 'anemone.db')
require 'anemone/storage/sqlite3'
self::SQLite3.new(file)
end
def self.MySQL(opts = {})
require 'anemone/storage/mysql'
self::MySQL.new(opts)
end
end
end
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
まだ回答がついていません
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる