bookmeter_scraper 0.1.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6c328c66bbd91ea36ee0471c01f4e16a69ffd347
4
- data.tar.gz: d1d5fde5a9d223c0aada00c670d1feed0b5e9c3a
3
+ metadata.gz: a8d0b08d6fe209f678ebda3c621b41412a575aef
4
+ data.tar.gz: 1d9db389c1c0ac92216c00e76f7a025327ed77c7
5
5
  SHA512:
6
- metadata.gz: 9a2c3a6149faa92850aca03c455bd5ccd95f8eddaee005e4befd4daa328c340e171df5018803f9feb0ebb0f7fdf630f91d9b9259c52fb358f5b3ccf5570595e7
7
- data.tar.gz: dcbf2db1efa63928b1c00a00d35af13ffba46345578c84b40b26a9b320ba69acd899c66c9319af5e15894a3d4e5ccc5fadbf64136fbbcbea804a0097f0729251
6
+ metadata.gz: 9df797a4925a93e8cb8a7f07e38bbd4b1288acadd27a2d0e32fd3e0161120a843dd3b2c5c184c7116e90bb6d8b52a2cacfc246a04f7ede74b6081359882f2d51
7
+ data.tar.gz: ba4d5f59e35034facda467d469a0f2ef3cfef10829f2e75a82af6a839233fe2ff0e588a9c1535db25bc48eb24a2d08fd81d614b67f1c92d66b2656b0603fc303
data/README.ja.md CHANGED
@@ -28,7 +28,16 @@ require 'bookmeter_scraper'
28
28
 
29
29
  ### ログイン
30
30
 
31
- 書籍情報、お気に入り / お気に入られユーザ情報を取得するには、`Bookmeter.log_in` でログインしておく必要があります。
31
+ 書籍情報、お気に入り / お気に入られユーザ情報を取得するには、`Bookmeter.log_in` または `Bookmeter#log_in` でログインしておく必要があります。
32
+
33
+ ログイン情報の入力には以下の 2 通りの方法があります。
34
+
35
+ 1. 引数として渡す
36
+ 2. `config.yml` へ記述しておく
37
+
38
+ #### 1. 引数として渡す
39
+
40
+ 以下のように `Bookmeter.log_in` へメールアドレスとパスワードを引数として渡すことで、ログインできます。
32
41
 
33
42
  ```ruby
34
43
  bookmeter = BookmeterScraper::Bookmeter.log_in('example@example.com', 'password')
@@ -42,6 +51,22 @@ bookmeter = BookmeterScraper::Bookmeter.new
42
51
  bookmeter.log_in('example@example.com', 'password')
43
52
  ```
44
53
 
54
+ #### 2. `config.yml` へ記述しておく
55
+
56
+ まず、以下のように YAML ファイル `config.yml` を記述し、Ruby スクリプトを実行する場所と同じディレクトリに置きます。
57
+
58
+ ```yml
59
+ mail: example@example.com
60
+ password: your_password
61
+ ```
62
+
63
+ 次に、引数なしで `Bookmeter.log_in` または `Bookmeter#log_in` を呼ぶと、`config.yml` からログイン情報を読みとり、ログインできます。
64
+
65
+ ```ruby
66
+ bookmeter = BookmeterScraper::Bookmeter.log_in
67
+ bookmeter.logged_in? # true
68
+ ```
69
+
45
70
  ### 書籍情報の取得
46
71
 
47
72
  以下の書籍情報
@@ -62,10 +87,17 @@ books = bookmeter.read_books # ログインユーザの「読んだ本」
62
87
  bookmeter.read_books('01010101') # 他のユーザの ID を指定して、そのユーザの「読んだ本」を取得
63
88
  ```
64
89
 
65
- 書籍情報は書名 `name` と読了日(初読了日と再読日の両方)の配列 `read_dates` を属性として持つ `Struct` の配列として取得できます。
90
+ 書籍情報は
91
+
92
+ - 書名 `name`
93
+ - 著者 `author`
94
+ - 読了日(初読了日と再読日の両方)の配列 `read_dates`
95
+
96
+ を属性として持つ `Struct` の配列として取得できます。
66
97
 
67
98
  ```ruby
68
99
  books[0].name
100
+ books[0].author
69
101
  books[0].read_dates
70
102
  ```
71
103
 
@@ -95,6 +127,7 @@ books = bookmeter.read_books_in(2016, 1, '01010101') # ID で指定した他
95
127
  ```ruby
96
128
  books = bookmeter.reading_books # ログインユーザの「読んでる本」を取得
97
129
  books[0].name
130
+ books[0].author
98
131
  books[0].read_dates # 読了日の Array は空
99
132
 
100
133
  bookmeter.tsundoku # ログインユーザの「積読本」を取得
data/README.md CHANGED
@@ -32,10 +32,19 @@ require 'bookmeter_scraper'
32
32
 
33
33
  ### Log in
34
34
 
35
- You need to log in Bookmeter to get books and followings / followers information by `Bookmeter.log_in`:
35
+ You need to log in Bookmeter to get books and followings / followers information by `Bookmeter.log_in` or `Bookmeter#log_in`.
36
+
37
+ There are 2 ways to input authentication information:
38
+
39
+ 1. Passing as arguments
40
+ 2. Writing out to `config.yml`
41
+
42
+ #### 1. Passing as arguments
43
+
44
+ You can log in Bookmeter by passing mail address and password to `Bookmeter.log_in`:
36
45
 
37
46
  ```ruby
38
- bookmeter = BookmeterScraper::Bookmeter.log_in('example@example.com', 'password')
47
+ bookmeter = BookmeterScraper::Bookmeter.log_in('example@example.com', 'your_password')
39
48
  bookmeter.logged_in? # true
40
49
  ```
41
50
 
@@ -46,6 +55,23 @@ bookmeter = BookmeterScraper::Bookmeter.new
46
55
  bookmeter.log_in('example@example.com', 'password')
47
56
  ```
48
57
 
58
+ #### 2. Writing out to `config.yml`
59
+
60
+ Create `config.yml` as followings and save it to the same directory as your Ruby script:
61
+
62
+ ```yml
63
+ mail: example@example.com
64
+ password: your_password
65
+ ```
66
+
67
+ Now you can log in Bookmeter by calling `Bookmeter.log_in` or `Bookmeter#log_in` with no arguments:
68
+
69
+ ```ruby
70
+ bookmeter = BookmeterScraper::Bookmeter.log_in
71
+ bookmeter.logged_in? # true
72
+ ```
73
+
74
+
49
75
  ### Get books information
50
76
 
51
77
  You can get books information:
@@ -18,11 +18,13 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.10"
22
- spec.add_development_dependency "rake", "~> 10.0"
23
- spec.add_development_dependency "rspec", "~> 3.4"
24
- spec.add_development_dependency "webmock", "~> 1.22"
21
+ spec.required_ruby_version = '>= 2.0'
25
22
 
26
- spec.add_dependency "yasuri", "~> 0.0"
27
- spec.add_dependency "mechanize", "~> 2.7"
23
+ spec.add_development_dependency "bundler"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "webmock"
27
+
28
+ spec.add_dependency "mechanize"
29
+ spec.add_dependency "yasuri"
28
30
  end
@@ -1,2 +1,3 @@
1
1
  require 'bookmeter_scraper/bookmeter'
2
+ require 'bookmeter_scraper/configuration'
2
3
  require 'bookmeter_scraper/version'
@@ -1,16 +1,39 @@
1
+ require 'forwardable'
1
2
  require 'mechanize'
2
3
  require 'yasuri'
3
4
 
4
5
  module BookmeterScraper
5
6
  class Bookmeter
7
+ DEFAULT_CONFIG_PATH = './config.yml'.freeze
8
+
6
9
  ROOT_URI = 'http://bookmeter.com'.freeze
7
10
  LOGIN_URI = "#{ROOT_URI}/login".freeze
8
11
 
9
12
  PROFILE_ATTRIBUTES = %i(name gender age blood_type job address url description first_day elapsed_days read_books_count read_pages_count reviews_count bookshelfs_count)
10
13
  Profile = Struct.new(*PROFILE_ATTRIBUTES)
11
14
 
12
- BOOK_ATTRIBUTES = %i(name read_dates)
15
+ BOOK_ATTRIBUTES = %i(name author read_dates)
13
16
  Book = Struct.new(*BOOK_ATTRIBUTES)
17
+ class Books
18
+ extend Forwardable
19
+
20
+ def_delegator :@books, :[]
21
+ def_delegator :@books, :[]=
22
+ def_delegator :@books, :<<
23
+ def_delegator :@books, :each
24
+ def_delegator :@books, :flatten!
25
+
26
+ def initialize; @books = []; end
27
+
28
+ def concat(books)
29
+ books.each do |book|
30
+ next if @books.any? { |b| b.name == book.name && b.author == book.author }
31
+ @books << book
32
+ end
33
+ end
34
+
35
+ def to_a; @books; end
36
+ end
14
37
 
15
38
  USER_ATTRIBUTES = %i(name id)
16
39
  User = Struct.new(*USER_ATTRIBUTES)
@@ -71,7 +94,7 @@ module BookmeterScraper
71
94
  "#{ROOT_URI}/u/#{user_id}/favorited_user"
72
95
  end
73
96
 
74
- def self.log_in(mail, password)
97
+ def self.log_in(mail = nil, password = nil)
75
98
  Bookmeter.new.tap do |bookmeter|
76
99
  bookmeter.log_in(mail, password)
77
100
  end
@@ -81,22 +104,26 @@ module BookmeterScraper
81
104
  def initialize(agent = nil)
82
105
  @agent = agent.nil? ? Bookmeter.new_agent : agent
83
106
  @logged_in = false
107
+ @log_in_user_id = nil
108
+ @book_pages = {}
84
109
  end
85
110
 
86
- def log_in(mail, password)
111
+ def log_in(mail = nil, password = nil)
87
112
  raise BookmeterError if @agent.nil?
88
113
 
89
- next_page = nil
114
+ config = Configuration.new(DEFAULT_CONFIG_PATH) if mail.nil? && password.nil?
115
+
116
+ page_after_submitting_form = nil
90
117
  page = @agent.get(LOGIN_URI) do |page|
91
- next_page = page.form_with(action: '/login') do |form|
92
- form.field_with(name: 'mail').value = mail
93
- form.field_with(name: 'password').value = password
118
+ page_after_submitting_form = page.form_with(action: '/login') do |form|
119
+ form.field_with(name: 'mail').value = config ? config.mail : mail
120
+ form.field_with(name: 'password').value = config ? config.password : password.to_s
94
121
  end.submit
95
122
  end
96
- @logged_in = next_page.uri.to_s == ROOT_URI + '/'
123
+ @logged_in = page_after_submitting_form.uri.to_s == ROOT_URI + '/'
97
124
  return unless logged_in?
98
125
 
99
- mypage = next_page.link_with(text: 'マイページ').click
126
+ mypage = page_after_submitting_form.link_with(text: 'マイページ').click
100
127
  @log_in_user_id = extract_user_id(mypage)
101
128
  end
102
129
 
@@ -124,32 +151,32 @@ module BookmeterScraper
124
151
  def read_books(user_id = @log_in_user_id)
125
152
  books = get_books(user_id, :read_books_uri)
126
153
  books.each { |b| yield b } if block_given?
127
- books
154
+ books.to_a
128
155
  end
129
156
 
130
157
  def read_books_in(year, month, user_id = @log_in_user_id)
131
158
  date = Time.local(year, month)
132
159
  books = get_read_books(user_id, date)
133
160
  books.each { |b| yield b } if block_given?
134
- books
161
+ books.to_a
135
162
  end
136
163
 
137
164
  def reading_books(user_id = @log_in_user_id)
138
165
  books = get_books(user_id, :reading_books_uri)
139
166
  books.each { |b| yield b } if block_given?
140
- books
167
+ books.to_a
141
168
  end
142
169
 
143
170
  def tsundoku(user_id = @log_in_user_id)
144
171
  books = get_books(user_id, :tsundoku_uri)
145
172
  books.each { |b| yield b } if block_given?
146
- books
173
+ books.to_a
147
174
  end
148
175
 
149
176
  def wish_list(user_id = @log_in_user_id)
150
177
  books = get_books(user_id, :wish_list_uri)
151
178
  books.each { |b| yield b } if block_given?
152
- books
179
+ books.to_a
153
180
  end
154
181
 
155
182
  def followings(user_id = @log_in_user_id)
@@ -164,7 +191,9 @@ module BookmeterScraper
164
191
 
165
192
  def self.new_agent
166
193
  agent = Mechanize.new do |a|
167
- a.user_agent_alias = 'Mac Safari'
194
+ a.user_agent_alias = Mechanize::AGENT_ALIASES.keys.reject do |ua_alias|
195
+ %w(Android iPad iPhone Mechanize).include?(ua_alias)
196
+ end.sample
168
197
  end
169
198
  end
170
199
 
@@ -173,7 +202,7 @@ module BookmeterScraper
173
202
  end
174
203
 
175
204
  def get_books(user_id, uri_method)
176
- books = []
205
+ books = Books.new
177
206
  scraped_pages = scrape_book_pages(user_id, uri_method)
178
207
  scraped_pages.each do |page|
179
208
  books << get_book_structs(page)
@@ -183,7 +212,7 @@ module BookmeterScraper
183
212
  end
184
213
 
185
214
  def get_read_books(user_id, target_ym)
186
- result = []
215
+ result = Books.new
187
216
  scrape_book_pages(user_id, :read_books_uri).each do |page|
188
217
  first_book_date = get_read_date(page['book_1_link'])
189
218
  last_book_date = get_last_book_date(page)
@@ -217,7 +246,7 @@ module BookmeterScraper
217
246
  end
218
247
 
219
248
  def get_target_books(target_ym, page)
220
- target_books = []
249
+ target_books = Books.new
221
250
 
222
251
  1.upto(NUM_BOOKS_PER_PAGE) do |i|
223
252
  next if page["book_#{i}_link"].empty?
@@ -245,7 +274,8 @@ module BookmeterScraper
245
274
  end
246
275
  end
247
276
  book_name = get_book_name(page["book_#{i}_link"])
248
- book = Book.new(book_name, read_dates)
277
+ book_author = get_book_author(page["book_#{i}_link"])
278
+ book = Book.new(book_name, book_author, read_dates)
249
279
  target_books << book
250
280
  end
251
281
 
@@ -282,28 +312,35 @@ module BookmeterScraper
282
312
  books_root.inject(@agent, books_page)
283
313
  end
284
314
 
285
- def get_book_name(book_link)
286
- @agent.get(ROOT_URI + book_link).search('#title').text
315
+ def get_book_page(book_uri)
316
+ @book_pages[book_uri] = @agent.get(ROOT_URI + book_uri) unless @book_pages[book_uri]
317
+ @book_pages[book_uri]
318
+ end
319
+
320
+ def get_book_name(book_uri)
321
+ get_book_page(book_uri).search('#title').text
322
+ end
323
+
324
+ def get_book_author(book_uri)
325
+ get_book_page(book_uri).search('#author_name').text
287
326
  end
288
327
 
289
- def get_read_date(book_link)
290
- book_page = @agent.get(ROOT_URI + book_link)
328
+ def get_read_date(book_uri)
291
329
  book_date = Yasuri.struct_date '//*[@id="book_edit_area"]/form[1]/div[2]' do
292
330
  text_year '//*[@id="read_date_y"]/option[1]', truncate: /\d+/, proc: :to_i
293
331
  text_month '//*[@id="read_date_m"]/option[1]', truncate: /\d+/, proc: :to_i
294
332
  text_day '//*[@id="read_date_d"]/option[1]', truncate: /\d+/, proc: :to_i
295
333
  end
296
- book_date.inject(@agent, book_page)
334
+ book_date.inject(@agent, get_book_page(book_uri))
297
335
  end
298
336
 
299
- def get_reread_date(book_link)
300
- book_page = @agent.get(ROOT_URI + book_link)
337
+ def get_reread_date(book_uri)
301
338
  book_reread_date = Yasuri.struct_reread_date '//*[@id="book_edit_area"]/div/form[1]/div[2]' do
302
339
  text_reread_year '//div[@class="reread_box"]/form[1]/div[2]/select[1]/option[1]', truncate: /\d+/, proc: :to_i
303
340
  text_reread_month '//div[@class="reread_box"]/form[1]/div[2]/select[2]/option[1]', truncate: /\d+/, proc: :to_i
304
341
  text_reread_day '//div[@class="reread_box"]/form[1]/div[2]/select[3]/option[1]', truncate: /\d+/, proc: :to_i
305
342
  end
306
- book_reread_date.inject(@agent, book_page)
343
+ book_reread_date.inject(@agent, get_book_page(book_uri))
307
344
  end
308
345
 
309
346
  def get_book_structs(page)
@@ -329,7 +366,8 @@ module BookmeterScraper
329
366
  end
330
367
 
331
368
  book_name = get_book_name(page["book_#{i}_link"])
332
- book = Book.new(book_name, read_dates)
369
+ book_author = get_book_author(page["book_#{i}_link"])
370
+ book = Book.new(book_name, book_author, read_dates)
333
371
  books << book
334
372
  end
335
373
 
@@ -0,0 +1,19 @@
1
+ require 'yaml'
2
+
3
+ module BookmeterScraper
4
+ class Configuration
5
+ attr_reader :mail, :password
6
+
7
+ def initialize(config_file)
8
+ config = YAML.load_file(config_file)
9
+ unless config.has_key?('mail') && config.has_key?('password')
10
+ raise ConfigurationError, "#{config_file}: Invalid configuration file"
11
+ end
12
+
13
+ @mail = config['mail']
14
+ @password = config['password']
15
+ end
16
+ end
17
+
18
+ class ConfigurationError < StandardError; end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module BookmeterScraper
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,99 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bookmeter_scraper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kohei Yamamoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-02-26 00:00:00.000000000 Z
11
+ date: 2016-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '3.4'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '3.4'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: webmock
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.22'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.22'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: yasuri
70
+ name: mechanize
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '0.0'
75
+ version: '0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '0.0'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: mechanize
84
+ name: yasuri
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '2.7'
89
+ version: '0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '2.7'
96
+ version: '0'
97
97
  description: Bookmeter scraping library
98
98
  email:
99
99
  - kymmt90@gmail.com
@@ -116,6 +116,7 @@ files:
116
116
  - exe/bookmeter_scraper
117
117
  - lib/bookmeter_scraper.rb
118
118
  - lib/bookmeter_scraper/bookmeter.rb
119
+ - lib/bookmeter_scraper/configuration.rb
119
120
  - lib/bookmeter_scraper/version.rb
120
121
  homepage: https://github.com/kymmt90/bookmeter_scraper
121
122
  licenses:
@@ -129,7 +130,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
130
  requirements:
130
131
  - - ">="
131
132
  - !ruby/object:Gem::Version
132
- version: '0'
133
+ version: '2.0'
133
134
  required_rubygems_version: !ruby/object:Gem::Requirement
134
135
  requirements:
135
136
  - - ">="
@@ -137,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
138
  version: '0'
138
139
  requirements: []
139
140
  rubyforge_project:
140
- rubygems_version: 2.5.1
141
+ rubygems_version: 2.4.5.1
141
142
  signing_key:
142
143
  specification_version: 4
143
144
  summary: Bookmeter scraping library