miby 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +7 -0
- data/Readme.rd +160 -0
- data/bin/miby +50 -0
- data/etc/pagestruct.yaml +201 -0
- data/etc/test_pagestruct.yaml +202 -0
- data/lib/base.rb +61 -0
- data/lib/config.rb +28 -0
- data/lib/http.rb +34 -0
- data/lib/miby.rb +35 -0
- data/lib/mixi.rb +179 -0
- data/lib/page.rb +183 -0
- data/lib/pagestruct.rb +68 -0
- data/lib/user.rb +66 -0
- data/test/test_config.rb +17 -0
- data/test/test_http.rb +25 -0
- data/test/test_miby.rb +27 -0
- data/test/test_mixi.rb +53 -0
- data/test/test_page.rb +32 -0
- data/test/test_pagestruct.rb +44 -0
- data/test/test_setup.rb +6 -0
- data/test/test_user.rb +44 -0
- metadata +66 -0
data/lib/base.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Mibyの基本ファイル
|
2
|
+
# 他のMibyライブラリファイルはこのファイルをrequireする必要があります。
|
3
|
+
$:.push File.dirname(__FILE__) + "/../lib"
|
4
|
+
require 'nkf'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'config'
|
7
|
+
|
8
|
+
|
9
|
+
class String
|
10
|
+
def to_utf8
|
11
|
+
NKF.nkf("-Lu -d -w", self)
|
12
|
+
end
|
13
|
+
alias utf8 to_utf8
|
14
|
+
|
15
|
+
def to_euc
|
16
|
+
NKF.nkf("-e", self)
|
17
|
+
end
|
18
|
+
alias euc to_euc
|
19
|
+
|
20
|
+
# nkf_charset:: -e:EUC, -w:UTF-8, -s:SJIS(*INOF* mixiの文字コードはEUC)
|
21
|
+
def to_uri_encode(nkf_charset = "-e")
|
22
|
+
URI.encode(NKF.nkf(nkf_charset, self))
|
23
|
+
end
|
24
|
+
alias uri_encode to_uri_encode
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
module Miby
|
29
|
+
VERSION = "0.0.1"
|
30
|
+
CONFIG_FILE = File.dirname(__FILE__) + '/../etc/miby.conf'
|
31
|
+
USER_FILE = File.dirname(__FILE__) + '/../etc/user.yaml'
|
32
|
+
PAGESTRUCT_FILE = File.dirname(__FILE__) + '/../etc/pagestruct.yaml'
|
33
|
+
|
34
|
+
# Mibyの規定モジュール
|
35
|
+
module Base
|
36
|
+
# 1行入力して、入力された文字列を返します。
|
37
|
+
# term:: 入力行に表示する文字列
|
38
|
+
def input_line(term = "Input", io = $stdin)
|
39
|
+
print "#{term}: "; io.__send__(:gets).to_s.chomp
|
40
|
+
end
|
41
|
+
|
42
|
+
# 複数行入力して、入力された文字列を返します。
|
43
|
+
# io オブジェクトが設定されていなければ ENV['EDITOR'] を起動します。
|
44
|
+
def input_lines(io = nil)
|
45
|
+
if io.nil?
|
46
|
+
raise "No set IO and env['EDITOR']" if ENV['EDITOR'] == nil
|
47
|
+
temp_file = Tempfile.new("miby_base_get_lines")
|
48
|
+
system "#{ENV['EDITOR']} #{temp_file.path}"
|
49
|
+
io = temp_file
|
50
|
+
end
|
51
|
+
io.readlines.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# *warning* This method is obsolete. Please using String#uri_encode
|
56
|
+
def encode(str)
|
57
|
+
URI.encode(NKF.nkf("-e", str.to_s))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/lib/config.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Miby
|
3
|
+
# Miby::CONFIG_FILEで指定されあた設定ファイル(デフォルトは etc/miby.conf)を読み込み、設定情報をアクセサメソッドに登録します。
|
4
|
+
#
|
5
|
+
# == 使い方
|
6
|
+
# オブジェクトを生成したらアクセサメソッドで値を呼びだします。
|
7
|
+
# config = Miby::Config.new
|
8
|
+
# config.http_address #=> mixi.jp
|
9
|
+
#
|
10
|
+
# == miby.conf
|
11
|
+
# mibyの設定ファイルは @name のインスタンス変数で指定します。
|
12
|
+
# 指定できる変数は下のアクセサメソッドに登録されている必要があります。
|
13
|
+
# 設定できる項目の目的は Miby::CONFIG_FILE のファイルを参照してください(デフォルトは conf/miby.conf)。
|
14
|
+
# 例)
|
15
|
+
# @http_address = "mixi.jp" # mixiのベースURL(通常は mixi.jp)
|
16
|
+
# @http_port = "80" # HTTPサーバのポート番号(通常は80)
|
17
|
+
# @proxy_addr = "proxy" # プロキシのホスト名(nilなら無効)
|
18
|
+
# @proxy_port = "8080" # プロキシのポート番号(nilなら無効)
|
19
|
+
class Config
|
20
|
+
def initialize(path = CONFIG_FILE)
|
21
|
+
instance_eval File.read(path)
|
22
|
+
end
|
23
|
+
attr_reader :http_address, :http_port, :proxy_addr, :proxy_port
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
|
data/lib/http.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
$:.push File.dirname(__FILE__) + "/../lib"
|
2
|
+
require 'base'
|
3
|
+
require 'net/http'
|
4
|
+
Net::HTTP.version_1_2
|
5
|
+
|
6
|
+
module Miby
|
7
|
+
# Mibyで利用するのhttpメソッドを提供します。
|
8
|
+
# 接続するホストのアドレスやプロキシの設定は Miby::Config で設定します。
|
9
|
+
#
|
10
|
+
# == 使い方
|
11
|
+
# 実行したい処理をブロックで渡します。ブロック内で利用できるメソッドは Net::HTTPと同じです。
|
12
|
+
# http_response = HTTP.new.connection {|http|
|
13
|
+
# http.get(path)
|
14
|
+
# ...
|
15
|
+
# }
|
16
|
+
class HTTP
|
17
|
+
def initialize(config = Config.new)
|
18
|
+
@http_address = config.http_address
|
19
|
+
@http_port = config.http_port
|
20
|
+
@proxy_addr = config.proxy_addr
|
21
|
+
@proxy_port = config.proxy_port
|
22
|
+
end
|
23
|
+
attr_reader :http_address, :http_port, :proxy_addr, :proxy_port
|
24
|
+
|
25
|
+
# ホスト @http_address に接続しブロックをを実行します。
|
26
|
+
# 成功した場合は Net::HTTPResponse のインスタンスを返します。
|
27
|
+
def connection(&block)
|
28
|
+
puts "connection : #@http_address, #@http_port, #@proxy_addr, #@proxy_port" if $VERBOSE
|
29
|
+
Net::HTTP.start(@http_address, @http_port, @proxy_addr, @proxy_port, &block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
data/lib/miby.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# = miby : Mixi from Ruby
|
2
|
+
# Miby(ミビー) は Ruby から mixi を操作するためのライブラリです。
|
3
|
+
#
|
4
|
+
# == 使い方
|
5
|
+
# require 'miby/miby'
|
6
|
+
# miby = Miby::Miby.new
|
7
|
+
# page = miby.get_page("friend_diary")
|
8
|
+
# page.format_items.each do |item|
|
9
|
+
# puts "#{item["title"]} #{item["name"]}"
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
$:.push File.dirname(__FILE__) + "/../lib"
|
13
|
+
require 'base'
|
14
|
+
require 'mixi'
|
15
|
+
module Miby
|
16
|
+
# Mibyの既定クラス。
|
17
|
+
class Miby
|
18
|
+
def initialize
|
19
|
+
@mixi = Mixi.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# mixiのページを取得します。成功すると Miby::Page が返ります。
|
23
|
+
# name:: ページ名
|
24
|
+
# values:: URLパラメータの配列
|
25
|
+
def get_page(name, *values)
|
26
|
+
begin
|
27
|
+
@mixi.__send__(name, *values)
|
28
|
+
rescue
|
29
|
+
$stderr.puts "ページ #{name} 取得中にエラーが発生しました。"
|
30
|
+
raise
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/lib/mixi.rb
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
$:.push File.dirname(__FILE__) + "/../lib"
|
2
|
+
require 'base'
|
3
|
+
require 'user'
|
4
|
+
require 'page'
|
5
|
+
require 'pagestruct'
|
6
|
+
|
7
|
+
module Miby
|
8
|
+
# mixiとのコネクションを行います。
|
9
|
+
# ユーザーの認証、ページデータの取得、日記・コメントの投稿ができます。
|
10
|
+
# ページの取得・投稿(get・post系)を行うメソッドの戻り値は Miby::Page のインスタンスです。
|
11
|
+
#
|
12
|
+
# == 使い方
|
13
|
+
# Mibyライブラリを読み込んで Miby::Mixiインスタンスを生成します。
|
14
|
+
# require 'miby'
|
15
|
+
# mixi = Miby::Mixi.new
|
16
|
+
# mixiに登録したメールアドレスとパスワードでログインします。
|
17
|
+
# 成功すればture、失敗した場合は例外が発生します。
|
18
|
+
# mixi.login("hoge@hogege.com", "hoga")
|
19
|
+
#
|
20
|
+
# マイミクの最新日記リストページを取得して、整形したデータの各アイテムの内容を表示するには以下のように実行します。
|
21
|
+
# ログインしていない場合は自動でログインします。
|
22
|
+
# pgae = mixi.friend_diary
|
23
|
+
# page.each do |item|
|
24
|
+
# puts %<#{item["title"]} #{item["name"]}>
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# == コマンド
|
28
|
+
# 取得したページの素の整形データを取得する。
|
29
|
+
# page.format_items
|
30
|
+
#
|
31
|
+
# 取得したページの整形データを配列に変換する。
|
32
|
+
# page.to_a
|
33
|
+
#
|
34
|
+
# 取得したページの Net::HTTPRequest#response を取得する。
|
35
|
+
# page.request
|
36
|
+
#
|
37
|
+
# == 利用できるページ
|
38
|
+
# 利用できるページには パブリックメソッドに定義されているものと、 Miby::PageStruct に定義されているものの2種類があります。
|
39
|
+
# パブリックメソッドのページは各メソッドの説明をご覧ください。
|
40
|
+
#
|
41
|
+
# Miby::PageStructは定義名で呼び出して利用することができます。
|
42
|
+
# # id:10 owner_id:1 の日記の本文を取得する
|
43
|
+
# mixi.view_diary_diary(10,1)
|
44
|
+
# 詳細は Miby::PageStruct を参照してください。
|
45
|
+
#
|
46
|
+
# == 引数
|
47
|
+
# 説明のない引数はmixiに渡すパラメータと同じです。
|
48
|
+
#
|
49
|
+
# email:: メールアドレス
|
50
|
+
# password:: ユーザーのパスワード
|
51
|
+
# id, diary_id:: 日記のID
|
52
|
+
# owner_id:: ユーザーのID(一部idを使うページがある)
|
53
|
+
# diary_title:: 日記タイトル
|
54
|
+
# diary_body:: 日記本文
|
55
|
+
# comment_body:: コメント本文
|
56
|
+
# submit:: hidden文字列(日記の投稿に必要)
|
57
|
+
#
|
58
|
+
# == 未実装の機能
|
59
|
+
# * メッセージ・動画・フォト・ミュージック・コミュニティー全般
|
60
|
+
# * 「前の日記へ」「次の日記へ」
|
61
|
+
class Mixi
|
62
|
+
include Base
|
63
|
+
|
64
|
+
# 未定義のメソッドはページ取得として実行する。
|
65
|
+
def method_missing(name, *values)
|
66
|
+
puts "try get page: #{name} (call from method missing)." if $VERBOSE
|
67
|
+
get_page(name, values)
|
68
|
+
end
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
@user = User.new
|
72
|
+
@page_struct = PageStruct.new
|
73
|
+
@logined = false
|
74
|
+
end
|
75
|
+
attr_reader :user
|
76
|
+
|
77
|
+
#--
|
78
|
+
# get >>
|
79
|
+
#++
|
80
|
+
# 日記の表示
|
81
|
+
def view_diary(id, owner_id)
|
82
|
+
diary = get_page "view_diary_diary", id, owner_id
|
83
|
+
comment = get_page "view_diary_comment" ,id, owner_id
|
84
|
+
diary.to_a + comment.to_a
|
85
|
+
end
|
86
|
+
|
87
|
+
# マイミク日記リスト
|
88
|
+
# page_count: ページ番号
|
89
|
+
def friend_diary(page_count = nil)
|
90
|
+
unless page_count.nil? or page_count.empty?
|
91
|
+
params = get_next_page_param("new_friend_diary_next_page_param", page_count)
|
92
|
+
end
|
93
|
+
get_page("new_friend_diary", params)#.format_items
|
94
|
+
end
|
95
|
+
|
96
|
+
#--
|
97
|
+
# post >>
|
98
|
+
#++
|
99
|
+
# 自分の日記を追加します。
|
100
|
+
def add_diary(id, owner_id)
|
101
|
+
get_page("add_diary", id, owner_id, "main")
|
102
|
+
end
|
103
|
+
|
104
|
+
#--
|
105
|
+
# controll >>
|
106
|
+
#++
|
107
|
+
def logined?
|
108
|
+
@logined == true or get_home? ? true : false
|
109
|
+
end
|
110
|
+
|
111
|
+
# email と password を使ってmixiにログインします。
|
112
|
+
# 失敗した場合は例外が発生します。
|
113
|
+
def login(email = nil, password = nil)
|
114
|
+
puts "login ..." if $VERBOSE
|
115
|
+
email ||= input_line("email"); password ||= input_line("passowrd")
|
116
|
+
page = Page.new("login", { "email" => email, "password" => password, "next_url" => "home.pl"})
|
117
|
+
|
118
|
+
if page.to_s == "refresh"
|
119
|
+
@user.set(page.response.get_fields('Set-Cookie'))
|
120
|
+
@logined = true
|
121
|
+
return true
|
122
|
+
else
|
123
|
+
raise "Login refuse. email or password"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
# << controll
|
127
|
+
|
128
|
+
private
|
129
|
+
#
|
130
|
+
def get_home?
|
131
|
+
return false unless @user.cookie?
|
132
|
+
page = Page.new("home_form", nil, @user.cookie)
|
133
|
+
page.to_s =~ /login.pl/ ? false : true
|
134
|
+
end
|
135
|
+
|
136
|
+
# name のMiby::Pageオブジェクトを取得する。
|
137
|
+
# name:: PageStructに定義された名前
|
138
|
+
# values:: URLに渡すパラメータ 配列かハッシュ。配列の場合は Miby::PageStructの定義順に配置する
|
139
|
+
def get_page(name, *values)
|
140
|
+
puts "get_page: #{name}" if $VERBOSE
|
141
|
+
login unless logined?
|
142
|
+
values.flatten!
|
143
|
+
list = values.first
|
144
|
+
list = create_param_value_list(@page_struct.find_by_name(name), values) unless list.kind_of? Hash
|
145
|
+
Page.new(name, list, @user.cookie)
|
146
|
+
end
|
147
|
+
|
148
|
+
# structのparamsとparams_optをvaluesからURLに渡すパラメータのリスト(Hash)を生成する。
|
149
|
+
# struct : PageStructオブジェクト
|
150
|
+
# values : 値の入った配列
|
151
|
+
def create_param_value_list(struct, values)
|
152
|
+
list = { }
|
153
|
+
keys = struct["params"].to_a + struct["params_opt"].to_a
|
154
|
+
keys.each_with_index do |key, i|
|
155
|
+
list.merge!({ key => values[i] })
|
156
|
+
end
|
157
|
+
list
|
158
|
+
end
|
159
|
+
|
160
|
+
# 次のページに移動するためのパラメータを取得する
|
161
|
+
def get_next_page_param(name, count)
|
162
|
+
params = { }
|
163
|
+
(count.to_i - 1).times do
|
164
|
+
items = get_page(name, params)
|
165
|
+
raise "データがありません" if items.empty?
|
166
|
+
# ページ毎の定義
|
167
|
+
case name
|
168
|
+
when "new_friend_diary_next_page_param"
|
169
|
+
items.each do |item|
|
170
|
+
params = item if item.has_key?("direction") and item["direction"] == "next"
|
171
|
+
end
|
172
|
+
else
|
173
|
+
params = items.first
|
174
|
+
end
|
175
|
+
end
|
176
|
+
params
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
data/lib/page.rb
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
$:.push File.dirname(__FILE__) + "/../lib"
|
2
|
+
require 'hpricot'
|
3
|
+
require 'base'
|
4
|
+
require 'http'
|
5
|
+
require 'pagestruct'
|
6
|
+
|
7
|
+
module Miby
|
8
|
+
# ページオブジェクトを作成します。
|
9
|
+
# ページオブジェクトは1つURLで表現できるページを、ルール(ページ整形情報)に従って整形データを作成したものです。
|
10
|
+
#
|
11
|
+
# == 生成
|
12
|
+
# Miby::Pagestructで定義されている定義名(name)とURLパラメータを使って生成します。
|
13
|
+
# 定義されていないページを取得しようとすると例外が発生します。
|
14
|
+
#
|
15
|
+
# マイミクの最新日記リストのMiby::Pageを得るには以下のようにします。
|
16
|
+
# Miby::Page.new("friend_diary", nil, Miby::User.new.cookie)
|
17
|
+
# URLにパラメータを渡す場合は以下のようにします。
|
18
|
+
# Miby::Page.new("view_diary", {"id" => "10000", "owner_id" => "10000" }, Miby::User.new.cookie)
|
19
|
+
#
|
20
|
+
# == アクセス
|
21
|
+
# * 生成したPageオブジェクトの整形されたデータにはパブリックメソッド(to_s, to_a, each, empty?)を使ってアクセスできます。
|
22
|
+
# * 取得したページ情報に直接アクセスするには Page#response を使います(Net::HTTPResponseを返します)。
|
23
|
+
class Page
|
24
|
+
include Enumerable
|
25
|
+
include Base
|
26
|
+
|
27
|
+
# name:: Miby::PageStructに定義されている名前
|
28
|
+
# params:: URLに渡すパラメータのハッシュ。Miby::PageStructのparams配列で定義されているものを指定する。
|
29
|
+
# cookie:: headerに渡すcookieの値。Miby::User.cookie で取得できる。
|
30
|
+
def initialize(name, params = nil, cookie = nil)
|
31
|
+
params ||= { }
|
32
|
+
@name, @params, @cookie = name, params, cookie
|
33
|
+
|
34
|
+
@struct = PageStruct.find(name)
|
35
|
+
@response = get_http_response(name, params, cookie, @struct)
|
36
|
+
@format_items = response_to_format_items(@response, @struct)
|
37
|
+
@option_items = response_to_option_items(@response, @struct)
|
38
|
+
end
|
39
|
+
attr_reader :name, :params, :cookie
|
40
|
+
# Page::Structから得たページ整形情報。Miby::Pageはこの情報を元にHTMLファイルをアイテム毎にフォーマットします。
|
41
|
+
attr_reader :struct
|
42
|
+
# 取得したページの Net::HTTPResponse を返します。
|
43
|
+
attr_reader :response
|
44
|
+
# 整形されたデータ。通常は各アイテム情報を入れた配列になります。
|
45
|
+
# 例:friend_diary(マイミクの最新日記リスト)を取得した場合は [{"name" => "名前", "title" => "今日の日記", "body" => "本文"} ...] のようになります。
|
46
|
+
# 実際どのようなデータが代入されるかは Miby::PageStruct の variables配列 によります。
|
47
|
+
# Miby::Pageのパブリックメソッドはすべてこの変数に対して動作します。
|
48
|
+
attr_reader :format_items
|
49
|
+
# 整形されたオプションデータ。
|
50
|
+
attr_reader :option_items
|
51
|
+
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
@format_items.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_a
|
58
|
+
@format_items.to_a
|
59
|
+
end
|
60
|
+
|
61
|
+
def empty?
|
62
|
+
return true if @format_items.nil?
|
63
|
+
@format_items.size == 0 ? true : false
|
64
|
+
end
|
65
|
+
|
66
|
+
def first
|
67
|
+
@format_items.first
|
68
|
+
end
|
69
|
+
|
70
|
+
def each
|
71
|
+
@format_items.each { |item| yield item }
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def get_http_response(name, params, cookie, struct)
|
76
|
+
path = File.join("/", struct["path"])
|
77
|
+
cookie = { 'Cookie' => cookie } unless cookie.nil?
|
78
|
+
uri_param = create_uri_param(struct, params)
|
79
|
+
puts "get_http_response: method:#{struct["method"]}, path: #{path}, cookie:#{cookie}" if $VERBOSE
|
80
|
+
p params if $VERBOSE
|
81
|
+
|
82
|
+
HTTP.new.connection do |http|
|
83
|
+
case struct["method"]
|
84
|
+
when 'post'
|
85
|
+
post_key = get_post_key(http.post(path, uri_param, cookie).body) # mixiの投稿は事前に post_id を取得して post_id を使って投稿する。
|
86
|
+
raise "not response found post_key" if post_key.nil?
|
87
|
+
uri_param.gsub!("&submit=main", "") # 日記投稿のsubmitを削除
|
88
|
+
http.post(path, uri_param + "&post_key=#{post_key.to_s.uri_encode}&submit=confirm", cookie) # 投稿にはpost_keyとsubmitが必要
|
89
|
+
else #get
|
90
|
+
http.get(path + uri_param, cookie)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# URIのパラメータ部分をstructとvaluesから生成します。
|
96
|
+
# struct:: ページ整形情報オブジェクト
|
97
|
+
# values:: パラメータとその値(ハッシュ)
|
98
|
+
def create_uri_param(struct, values = { })
|
99
|
+
param = ""
|
100
|
+
unless struct["params"].nil?
|
101
|
+
struct["params"].each do |key|
|
102
|
+
raise "No set require parameter : #{key}" if values[key].nil?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
values.each do |key,val|
|
106
|
+
param << "&#{key.to_s.uri_encode}=#{val.to_s.uri_encode}"
|
107
|
+
end
|
108
|
+
struct["method"] == "post" ? param.sub(/^&/,"") : "?" + param
|
109
|
+
end
|
110
|
+
|
111
|
+
#--
|
112
|
+
# <<< parse
|
113
|
+
#++
|
114
|
+
# HTMLを整形し、配列を返します。
|
115
|
+
# response:: Net::HTTPResponse のインスタンス
|
116
|
+
def response_to_format_items(response, struct)
|
117
|
+
raise "response failed. path:#{struct["path"]}, code:#{response.code}" unless response.code == "200"
|
118
|
+
elements = format_from_cssselector(response.body, struct["css_selectors"])
|
119
|
+
matchs = format_from_regexp(elements, struct["regexp"])
|
120
|
+
items = set_variables(matchs, struct["variables"])
|
121
|
+
end
|
122
|
+
def response_to_option_items(response, struct)
|
123
|
+
return false unless response.code == "200"
|
124
|
+
elements = format_from_cssselector(response.body, struct["css_selectors_opt"])
|
125
|
+
matchs = format_from_regexp(elements, struct["regexp_opt"])
|
126
|
+
items = set_variables(matchs, struct["variables_opt"])
|
127
|
+
end
|
128
|
+
|
129
|
+
# selectors:: CSS selector の配列
|
130
|
+
def format_from_cssselector(html, selectors = nil)
|
131
|
+
return html.to_a if selectors.nil?
|
132
|
+
elements = Hpricot(html.to_s.utf8)
|
133
|
+
selectors.each { |sel| elements = elements.search(sel) }
|
134
|
+
elements
|
135
|
+
end
|
136
|
+
|
137
|
+
# regexp:: 正規表現
|
138
|
+
def format_from_regexp(str, regexp = nil)
|
139
|
+
return [] if regexp.nil?
|
140
|
+
str.to_s.utf8.gsub("\n", "").gsub("\t","").scan(Regexp.new(regexp))
|
141
|
+
end
|
142
|
+
|
143
|
+
#--
|
144
|
+
# 配列の配列を配列のハッシュにする
|
145
|
+
#++
|
146
|
+
def set_variables(matchs, variables)
|
147
|
+
return matchs if variables.nil?
|
148
|
+
matchs.map do |value|
|
149
|
+
data_tmp = Hash.new
|
150
|
+
variables.each_with_index do |variable, i|
|
151
|
+
value[i] = body2str(value[i]) if variable == "body"
|
152
|
+
value[i] = date2time(value[i]) if variable == "date"
|
153
|
+
data_tmp.merge!({ variable => value[i] })
|
154
|
+
end
|
155
|
+
data_tmp
|
156
|
+
end
|
157
|
+
end
|
158
|
+
#--
|
159
|
+
# parse >>>
|
160
|
+
#++
|
161
|
+
|
162
|
+
# post_key の値を取得します。
|
163
|
+
def get_post_key(str)
|
164
|
+
str.to_s.gsub("\n","").match(/.*"post_key".*?value="(.*?)"/).to_a.values_at(1)
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
# mixiの時刻文字列をTimeオブジェクトに変換します。
|
169
|
+
def date2time(str)
|
170
|
+
str.match(/(\d{4})年(\d{1,2})月(\d{1,2})日\D*(\d{1,2}):(\d{1,2})/)
|
171
|
+
time = Time.mktime($1, $2, $3, $4, $5)
|
172
|
+
end
|
173
|
+
|
174
|
+
# HTMLの本文をプレーンテキストに変換します。
|
175
|
+
def body2str(body = "")
|
176
|
+
str = body.dup.gsub("\n", "")
|
177
|
+
str.gsub!("<br />", "\n")
|
178
|
+
str.gsub!(/<.*?>/, "") # 不要なタグは全削除
|
179
|
+
str
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|