pixiv 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -0
- data/console_helper.rb +27 -5
- data/lib/pixiv.rb +19 -7
- data/lib/pixiv/bookmark_list.rb +21 -36
- data/lib/pixiv/client.rb +79 -38
- data/lib/pixiv/illust.rb +23 -3
- data/lib/pixiv/illust_list.rb +46 -0
- data/lib/pixiv/owned_illust_list.rb +58 -0
- data/lib/pixiv/page.rb +7 -6
- data/lib/pixiv/page_collection.rb +37 -16
- data/lib/pixiv/version.rb +1 -1
- data/lib/pixiv/work_list.rb +37 -0
- metadata +6 -8
data/README.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
A client library for [pixiv](http://www.pixiv.net/)
|
4
4
|
|
5
|
+
[![Build Status](https://secure.travis-ci.org/uasi/pixiv.png?branch=master)][travis]
|
6
|
+
[![Dependency Status](https://gemnasium.com/uasi/pixiv.png?travis)][gemnasium]
|
7
|
+
[![Code Climate](https://codeclimate.com/badge.png)][codeclimate]
|
8
|
+
|
9
|
+
[travis]: http://travis-ci.org/uasi/pixiv
|
10
|
+
[gemnasium]: https://gemnasium.com/uasi/pixiv
|
11
|
+
[codeclimate]: https://codeclimate.com/github/uasi/pixiv
|
12
|
+
|
5
13
|
## Important Note
|
6
14
|
|
7
15
|
The pixiv Guidelines [[en][Guidelines.en], [ja][Guidelines.ja]] prohibit to
|
data/console_helper.rb
CHANGED
@@ -16,23 +16,45 @@ def init
|
|
16
16
|
require 'bundler/setup'
|
17
17
|
Bundler.require
|
18
18
|
|
19
|
-
$pixiv = Pixiv.
|
19
|
+
$pixiv = Pixiv.client(id, password) do |agent|
|
20
20
|
agent.user_agent_alias = 'Mac Safari'
|
21
21
|
agent.set_proxy(*proxy) if proxy
|
22
22
|
end
|
23
23
|
|
24
24
|
Kernel.const_set(:P, $pixiv)
|
25
25
|
Kernel.const_set(:M, $pixiv.member)
|
26
|
+
Kernel.const_set(:WL, $pixiv.work_list)
|
27
|
+
Kernel.const_set(:BL, $pixiv.bookmark_list)
|
28
|
+
Kernel.const_set(:PBL, $pixiv.private_bookmark_list)
|
29
|
+
Kernel.const_set(:Ws, $pixiv.works)
|
30
|
+
Kernel.const_set(:Bs, $pixiv.bookmarks)
|
31
|
+
Kernel.const_set(:PBs, $pixiv.private_bookmarks)
|
32
|
+
end
|
33
|
+
|
34
|
+
def M(id)
|
35
|
+
$pixiv.member(id)
|
26
36
|
end
|
27
37
|
|
28
38
|
def I(id)
|
29
39
|
$pixiv.illust(id)
|
30
40
|
end
|
31
41
|
|
32
|
-
def
|
33
|
-
$pixiv.member
|
42
|
+
def WL(member, p = 1)
|
43
|
+
$pixiv.work_list(member, p)
|
44
|
+
end
|
45
|
+
|
46
|
+
def BL(member, p = 1)
|
47
|
+
$pixiv.bookmark_list(member, p)
|
48
|
+
end
|
49
|
+
|
50
|
+
def PBL(p = 1)
|
51
|
+
$pixiv.private_bookmark_list(p)
|
52
|
+
end
|
53
|
+
|
54
|
+
def Ws(member)
|
55
|
+
$pixiv.works(member)
|
34
56
|
end
|
35
57
|
|
36
|
-
def
|
37
|
-
$pixiv.
|
58
|
+
def Bs(member)
|
59
|
+
$pixiv.bookmarks(member)
|
38
60
|
end
|
data/lib/pixiv.rb
CHANGED
@@ -1,17 +1,29 @@
|
|
1
1
|
require 'mechanize'
|
2
|
-
require 'pixiv/error'
|
3
|
-
require 'pixiv/client'
|
4
|
-
require 'pixiv/page'
|
5
|
-
require 'pixiv/illust'
|
6
|
-
require 'pixiv/member'
|
7
|
-
require 'pixiv/page_collection'
|
8
|
-
require 'pixiv/bookmark_list'
|
9
2
|
|
10
3
|
module Pixiv
|
4
|
+
autoload :BookmarkList, 'pixiv/bookmark_list'
|
5
|
+
autoload :Client, 'pixiv/client'
|
6
|
+
autoload :Error, 'pixiv/error'
|
7
|
+
autoload :Illust, 'pixiv/illust'
|
8
|
+
autoload :IllustList, 'pixiv/illust_list'
|
9
|
+
autoload :Member, 'pixiv/member'
|
10
|
+
autoload :OwnedIllustList, 'pixiv/owned_illust_list'
|
11
|
+
autoload :Page, 'pixiv/page'
|
12
|
+
autoload :PageCollection, 'pixiv/page_collection'
|
13
|
+
autoload :PrivateBookmarkList, 'pixiv/bookmark_list'
|
14
|
+
autoload :WorkList, 'pixiv/work_list'
|
15
|
+
|
11
16
|
ROOT_URL = 'http://www.pixiv.net'
|
12
17
|
|
18
|
+
# @deprecated Use {.client} instead. Will be removed in 0.1.0.
|
13
19
|
# Delegates to {Pixiv::Client#initialize}
|
14
20
|
def self.new(*args, &block)
|
15
21
|
Pixiv::Client.new(*args, &block)
|
16
22
|
end
|
23
|
+
|
24
|
+
# See {Pixiv::Client#initialize}
|
25
|
+
# @return [Pixiv::Client]
|
26
|
+
def self.client(*args, &block)
|
27
|
+
Pixiv::Client.new(*args, &block)
|
28
|
+
end
|
17
29
|
end
|
data/lib/pixiv/bookmark_list.rb
CHANGED
@@ -1,50 +1,28 @@
|
|
1
1
|
module Pixiv
|
2
|
-
class BookmarkList <
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
# @param [Integer] member_id
|
7
|
-
# @param [Integer] page_num
|
8
|
-
# @return [String]
|
9
|
-
def self.url(member_id, page_num = 1)
|
10
|
-
"#{ROOT_URL}/bookmark.php?id=#{member_id}&rest=show&p=#{page_num}"
|
2
|
+
class BookmarkList < OwnedIllustList
|
3
|
+
# (see super.url)
|
4
|
+
def self.url(member_id, page = 1)
|
5
|
+
"#{ROOT_URL}/bookmark.php?id=#{member_id}&rest=show&p=#{page}"
|
11
6
|
end
|
12
7
|
|
13
8
|
# @return [Integer]
|
14
|
-
lazy_attr_reader(:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
lazy_attr_reader(:last?) { at!('li.pages-current').next_element.inner_text.to_i == 0 }
|
19
|
-
# @return [Integer]
|
20
|
-
lazy_attr_reader(:member_id) { doc.body.match(/pixiv\.context\.userId = '(\d+)'/).to_a[1].to_i }
|
21
|
-
# @return [Array<Integer>]
|
22
|
-
lazy_attr_reader(:illust_ids) { search!('li[id^="li_"] a[href^="member_illust.php?mode=medium"]').map {|n| n['href'].match(/illust_id=(\d+)$/).to_a[1].to_i } }
|
9
|
+
lazy_attr_reader(:total_count) {
|
10
|
+
node = at!('a[href="/bookmark.php?type=illust_all"]')
|
11
|
+
node.inner_text.match(/\d+/).to_s.to_i
|
12
|
+
}
|
23
13
|
# @return [Array<Hash{Symbol=>Object}, nil>]
|
24
|
-
lazy_attr_reader(:
|
25
|
-
search!('li[id^="li_"]').map {|
|
14
|
+
lazy_attr_reader(:page_hashes) {
|
15
|
+
search!('li[id^="li_"]').map {|n| hash_from_list_item(n) }
|
26
16
|
}
|
27
17
|
|
28
|
-
|
29
|
-
|
30
|
-
# @return [String]
|
31
|
-
def url; self.class.url(member_id, page_num) end
|
32
|
-
# @return [Boolean]
|
33
|
-
def first?; page_num == 1 end
|
34
|
-
# @return [String]
|
35
|
-
def next_url; last? ? nil : self.class.url(member_id, page_num + 1) end
|
36
|
-
# @return [String]
|
37
|
-
def prev_url; first? ? nil : self.class.url(member_id, page_num - 1) end
|
38
|
-
# @return [Class<Pixiv::Page>]
|
39
|
-
def page_class; Illust end
|
40
|
-
# @return [Array<String>]
|
41
|
-
def page_urls; illust_ids.map {|illust_id| Illust.url(illust_id) } end
|
18
|
+
# @deprecated Use {#total_count} instead.
|
19
|
+
alias bookmarks_count total_count
|
42
20
|
|
43
21
|
private
|
44
22
|
|
45
|
-
# @param [Nokogiri::
|
23
|
+
# @param [Nokogiri::XML::Node] node
|
46
24
|
# @return [Hash{Symbol=>Object}] illust_hash
|
47
|
-
def
|
25
|
+
def hash_from_list_item(node)
|
48
26
|
return nil if node.at('img[src*="limit_unknown_s.png"]')
|
49
27
|
member_node = node.at('a[href^="member_illust.php?id="]')
|
50
28
|
illust_node = node.at('a')
|
@@ -59,4 +37,11 @@ module Pixiv
|
|
59
37
|
}
|
60
38
|
end
|
61
39
|
end
|
40
|
+
|
41
|
+
class PrivateBookmarkList < BookmarkList
|
42
|
+
# (see super.url)
|
43
|
+
def self.url(member_id, page = 1)
|
44
|
+
"#{ROOT_URL}/bookmark.php?id=#{member_id}&rest=hide&p=#{page}"
|
45
|
+
end
|
46
|
+
end
|
62
47
|
end
|
data/lib/pixiv/client.rb
CHANGED
@@ -52,6 +52,14 @@ module Pixiv
|
|
52
52
|
@member_id = member_id_from_mypage(doc)
|
53
53
|
end
|
54
54
|
|
55
|
+
# @param [Integer] member_id
|
56
|
+
# @return [Pixiv::Member] member bound to +self+
|
57
|
+
def member(member_id = member_id)
|
58
|
+
attrs = {member_id: member_id}
|
59
|
+
member = Member.lazy_new(attrs) { agent.get(Member.url(member_id)) }
|
60
|
+
member.bind(self)
|
61
|
+
end
|
62
|
+
|
55
63
|
# @param [Integer] illust_id
|
56
64
|
# @return [Pixiv::Illust] illust bound to +self+
|
57
65
|
def illust(illust_id)
|
@@ -60,37 +68,60 @@ module Pixiv
|
|
60
68
|
illust.bind(self)
|
61
69
|
end
|
62
70
|
|
63
|
-
# @param [Integer]
|
64
|
-
# @
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
71
|
+
# @param [Pixiv::Member, Integer] member_or_id
|
72
|
+
# @param [Integer] page
|
73
|
+
# @return [Pixiv::WorkList] work list bound to +self+
|
74
|
+
def work_list(member_or_id = member_id, page = 1)
|
75
|
+
illust_list_with_class(WorkList, member_or_id, page)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param [Pixiv::Member, Integer] member_or_id
|
79
|
+
# @param [Integer] page
|
80
|
+
# @return [Pixiv::BookmarkList] bookmark list bound to +self+
|
81
|
+
def bookmark_list(member_or_id = member_id, page = 1)
|
82
|
+
illust_list_with_class(BookmarkList, member_or_id, page)
|
69
83
|
end
|
70
84
|
|
71
|
-
# @param [Pixiv::Member, Integer]
|
85
|
+
# @param [Pixiv::Member, Integer] member_or_id
|
72
86
|
# @param [Integer] page_num
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
|
85
|
-
def bookmarks(list_or_member, opts = {})
|
86
|
-
list = list_or_member.is_a?(BookmarkList) ? list_or_member
|
87
|
-
: bookmark_list(list_or_member)
|
87
|
+
# @return [Pixiv::PrivateBookmarkList] private bookmark list bound to +self+
|
88
|
+
def private_bookmark_list(member_or_id = member_id, page = 1)
|
89
|
+
illust_list_with_class(PrivateBookmarkList, member_or_id, page)
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param [Pixiv::IllustList] list
|
93
|
+
# @!macro [new] opts_and_return
|
94
|
+
# @param [Hash] opts
|
95
|
+
# @option opts [Boolean] :include_deleted (false)
|
96
|
+
# whether the returning enumerator yields deleted illust as +nil+ or not
|
97
|
+
# @return [Pixiv::PageCollection::Enumerator]
|
98
|
+
def illusts(list, opts = {})
|
88
99
|
PageCollection::Enumerator.new(self, list, !!opts[:include_deleted])
|
89
100
|
end
|
90
101
|
|
102
|
+
# @param [Pixiv::Member, Integer] member_or_id
|
103
|
+
# @param [Integer] page
|
104
|
+
# @!macro opts_and_return
|
105
|
+
def works(member_or_id = member_id, page = 1, opts = {})
|
106
|
+
illusts(work_list(member_or_id, page), opts)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @param [Pixiv::Member, Integer] member_or_id
|
110
|
+
# @param [Integer] page
|
111
|
+
# @!macro opts_and_return
|
112
|
+
def bookmarks(member_or_id = member_id, page = 1, opts = {})
|
113
|
+
illusts(bookmark_list(member_or_id, page), opts)
|
114
|
+
end
|
115
|
+
|
116
|
+
# @param [Integer] page
|
117
|
+
# @!macro opts_and_return
|
118
|
+
def private_bookmarks(page = 1, opts = {})
|
119
|
+
illusts(private_bookmark_list(member_id, page), opts)
|
120
|
+
end
|
121
|
+
|
91
122
|
# Downloads the image to +io_or_filename+
|
92
123
|
# @param [Pixiv::Illust] illust
|
93
|
-
# @param [#write, String, Array<String, Symbol, #call>] io_or_filename io or filename or pattern
|
124
|
+
# @param [#write, String, Array<String, Symbol, #call>] io_or_filename io or filename or pattern for {#filename_from_pattern}
|
94
125
|
# @param [Symbol] size image size (+:small+, +:medium+, or +:original+)
|
95
126
|
def download_illust(illust, io_or_filename, size = :original)
|
96
127
|
size = {:s => :small, :m => :medium, :o => :original}[size] || size
|
@@ -111,7 +142,7 @@ module Pixiv
|
|
111
142
|
|
112
143
|
# Downloads the images to +pattern+
|
113
144
|
# @param [Pixiv::Illust] illust the manga to download
|
114
|
-
# @param [Array<String, Symbol, #call>] pattern pattern
|
145
|
+
# @param [Array<String, Symbol, #call>] pattern pattern for {#filename_from_pattern}
|
115
146
|
# @note +illust#manga?+ must be +true+
|
116
147
|
# @todo Document +&block+
|
117
148
|
def download_manga(illust, pattern, &block)
|
@@ -129,20 +160,9 @@ module Pixiv
|
|
129
160
|
end
|
130
161
|
end
|
131
162
|
|
132
|
-
protected
|
133
|
-
|
134
|
-
def ensure_logged_in
|
135
|
-
doc = agent.get("#{ROOT_URL}/mypage.php")
|
136
|
-
raise Error::LoginFailed unless doc.body =~ /logout/
|
137
|
-
@member_id = member_id_from_mypage(doc)
|
138
|
-
end
|
139
|
-
|
140
|
-
def member_id_from_mypage(doc)
|
141
|
-
doc.at('.profile_area a')['href'].match(/(\d+)$/).to_a[1].to_i
|
142
|
-
end
|
143
|
-
|
144
163
|
# Generate filename from +pattern+ in context of +illust+ and +url+
|
145
164
|
#
|
165
|
+
# @api private
|
146
166
|
# @param [Array<String, Symbol, #call>] pattern
|
147
167
|
# @param [Pixiv::Illust] illust
|
148
168
|
# @param [String] url
|
@@ -153,7 +173,7 @@ module Pixiv
|
|
153
173
|
# the +pattern+ is concatenated as the returning +filename+.
|
154
174
|
#
|
155
175
|
# * +:image_name+ in the +pattern+ is replaced with the base name of the +url+
|
156
|
-
# * Any other symbol is replaced with the value of +illust.
|
176
|
+
# * Any other symbol is replaced with the value of +illust.send(the_symbol)+
|
157
177
|
# * +#call+-able object is replaced with the value of +the_object.call(illust)+
|
158
178
|
# * String is left as-is
|
159
179
|
def filename_from_pattern(pattern, illust, url)
|
@@ -164,12 +184,33 @@ module Pixiv
|
|
164
184
|
name += '.' + $1
|
165
185
|
end
|
166
186
|
name
|
167
|
-
elsif i.is_a?(Symbol) then illust.
|
187
|
+
elsif i.is_a?(Symbol) then illust.send(i)
|
168
188
|
elsif i.respond_to?(:call) then i.call(illust)
|
169
189
|
else i
|
170
190
|
end
|
171
191
|
}.join('')
|
172
192
|
end
|
193
|
+
|
194
|
+
protected
|
195
|
+
|
196
|
+
def illust_list_with_class(list_class, member_or_id, page)
|
197
|
+
it = member_or_id
|
198
|
+
id = it.is_a?(Member) ? it.member_id : it.to_i
|
199
|
+
attrs = {member_id: id} # Don't set page or it will prevent checking bounds.
|
200
|
+
list_class.lazy_new(attrs) {
|
201
|
+
agent.get(list_class.url(id, page))
|
202
|
+
}.bind(self)
|
203
|
+
end
|
204
|
+
|
205
|
+
def ensure_logged_in
|
206
|
+
doc = agent.get("#{ROOT_URL}/mypage.php")
|
207
|
+
raise Error::LoginFailed unless doc.body =~ /logout/
|
208
|
+
@member_id = member_id_from_mypage(doc)
|
209
|
+
end
|
210
|
+
|
211
|
+
def member_id_from_mypage(doc)
|
212
|
+
doc.at('.profile_area a')['href'].match(/\d+$/).to_s.to_i
|
213
|
+
end
|
173
214
|
end
|
174
215
|
|
175
216
|
# @private
|
data/lib/pixiv/illust.rb
CHANGED
@@ -32,10 +32,11 @@ module Pixiv
|
|
32
32
|
}
|
33
33
|
# @return [String]
|
34
34
|
lazy_attr_reader(:title) { at!('.work-info h1.title').inner_text }
|
35
|
-
# @return [Integer]
|
35
|
+
# @return [Integer, nil]
|
36
36
|
lazy_attr_reader(:num_pages) {
|
37
|
-
|
38
|
-
n
|
37
|
+
node = doc.at('//ul[@class="meta"]/li[2]')
|
38
|
+
n = node ? node.inner_text.match(/(\d+)P$/).to_a[1] : nil
|
39
|
+
n && n.to_i
|
39
40
|
}
|
40
41
|
# @return [Array<String>]
|
41
42
|
lazy_attr_reader(:tag_names) { search!('ul.tags a.text').map {|n| n.inner_text } }
|
@@ -71,4 +72,23 @@ module Pixiv
|
|
71
72
|
@image_url_components ||= small_image_url.match(%r{^(.+)_s(\.\w+(?:\?\d+)?)$}).to_a[1, 3]
|
72
73
|
end
|
73
74
|
end
|
75
|
+
|
76
|
+
module Illust::WithClient
|
77
|
+
include Page::WithClient
|
78
|
+
|
79
|
+
# @return [Pixiv::Member]
|
80
|
+
def member
|
81
|
+
client.member(member_id)
|
82
|
+
end
|
83
|
+
|
84
|
+
# (see Pixiv::Client#download_illust)
|
85
|
+
def download_illust(io_or_filename, size = :original)
|
86
|
+
client.download_illust(self, io_or_filename, size)
|
87
|
+
end
|
88
|
+
|
89
|
+
# (see Pixiv::Client#download_manga)
|
90
|
+
def download_manga(pattern, &block)
|
91
|
+
client.download_manga(self, pattern, &block)
|
92
|
+
end
|
93
|
+
end
|
74
94
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Pixiv
|
2
|
+
# @abstract
|
3
|
+
class IllustList < Page
|
4
|
+
include PageCollection
|
5
|
+
|
6
|
+
# @return [Integer]
|
7
|
+
attr_reader :page
|
8
|
+
# @return [Integer]
|
9
|
+
attr_reader :total_count
|
10
|
+
|
11
|
+
def page_class
|
12
|
+
Illust
|
13
|
+
end
|
14
|
+
|
15
|
+
# Don't just do `alias illust_hashes page_hashes`;
|
16
|
+
# the illust_hashes intends to call the page_hashes
|
17
|
+
# overridden in a subclass.
|
18
|
+
|
19
|
+
# An array of illust attrs extracted from doc
|
20
|
+
# @return [Array<{Symbol=>Object}, nil>]
|
21
|
+
def illust_hashes
|
22
|
+
page_hashes
|
23
|
+
end
|
24
|
+
|
25
|
+
# Ditto.
|
26
|
+
|
27
|
+
# URLs extracted from doc
|
28
|
+
# @return [Array<{Symbol=>Object}, nil>]
|
29
|
+
def illust_urls
|
30
|
+
page_urls
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module IllustList::WithClient
|
35
|
+
include Page::WithClient
|
36
|
+
include Enumerable
|
37
|
+
|
38
|
+
# @yieldparam [Illust] illust
|
39
|
+
def each
|
40
|
+
illust_hashes.each do |attrs|
|
41
|
+
url = attrs.delete(:url)
|
42
|
+
yield Illust.lazy_new(attrs) { client.agent.get(url) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Pixiv
|
2
|
+
# Illust list owned by a member
|
3
|
+
#
|
4
|
+
# @abstract
|
5
|
+
#
|
6
|
+
# Implements common methods for bookmark.php and member_illust.php.
|
7
|
+
class OwnedIllustList < IllustList
|
8
|
+
# Returns the URL for given +member_id+ and +page+
|
9
|
+
# @param [Integer] member_id
|
10
|
+
# @param [Integer] page
|
11
|
+
# @return [String]
|
12
|
+
def self.url(member_id, page = 1)
|
13
|
+
raise NotImplementError
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
lazy_attr_reader(:page) {
|
18
|
+
at!('li.pages-current').inner_text.to_i
|
19
|
+
}
|
20
|
+
# @return [Boolean]
|
21
|
+
lazy_attr_reader(:last?) {
|
22
|
+
at!('li.pages-current').next_element.inner_text.to_i == 0
|
23
|
+
}
|
24
|
+
# @return [Integer]
|
25
|
+
lazy_attr_reader(:member_id) {
|
26
|
+
doc.body.match(/pixiv\.context\.userId = '(\d+)'/).to_a[1].to_i
|
27
|
+
}
|
28
|
+
|
29
|
+
# @return [String]
|
30
|
+
def url
|
31
|
+
self.class.url(member_id, page)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Boolean]
|
35
|
+
def first?
|
36
|
+
page == 1
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [String]
|
40
|
+
def next_url
|
41
|
+
last? ? nil : self.class.url(member_id, page + 1)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [String]
|
45
|
+
def prev_url
|
46
|
+
first? ? nil : self.class.url(member_id, page - 1)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module OwnedIllustList::WithClient
|
51
|
+
include IllustList::WithClient
|
52
|
+
|
53
|
+
# @return [Pixiv::Member]
|
54
|
+
def member
|
55
|
+
client.member(member_id)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/pixiv/page.rb
CHANGED
@@ -2,13 +2,13 @@ module Pixiv
|
|
2
2
|
class Page
|
3
3
|
# A new Page
|
4
4
|
# @param [Hash{Symbol=>Object}] attrs
|
5
|
-
# @yieldreturn [Nokogiri::
|
5
|
+
# @yieldreturn [Nokogiri::XML::Document]
|
6
6
|
def self.lazy_new(attrs = {}, &doc_creator)
|
7
7
|
self.new(doc_creator, attrs)
|
8
8
|
end
|
9
9
|
|
10
10
|
# @overload initialize(doc, attrs = {})
|
11
|
-
# @param [Nokogiri::
|
11
|
+
# @param [Nokogiri::XML::Document] doc
|
12
12
|
# @param [Hash{Symbol=>Object}] attrs
|
13
13
|
# @overload initialize(doc_creator, attrs = {})
|
14
14
|
# @param [#call] doc_creator
|
@@ -27,10 +27,10 @@ module Pixiv
|
|
27
27
|
# @param [String, Symbol] attr_name
|
28
28
|
# @return [Boolean]
|
29
29
|
def fetched?(attr_name = :doc)
|
30
|
-
|
30
|
+
instance_variable_defined?(:"@#{attr_name}")
|
31
31
|
end
|
32
32
|
|
33
|
-
# @return [Nokogiri::
|
33
|
+
# @return [Nokogiri::XML::Document]
|
34
34
|
def doc
|
35
35
|
@doc ||= begin
|
36
36
|
doc = @doc_creator.call
|
@@ -50,6 +50,7 @@ module Pixiv
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# Bind +self+ to +client+
|
53
|
+
# @api private
|
53
54
|
# @return self
|
54
55
|
def bind(client)
|
55
56
|
if self.class.const_defined?(:WithClient)
|
@@ -98,14 +99,14 @@ module Pixiv
|
|
98
99
|
|
99
100
|
# +node.at(path)+ or raise error
|
100
101
|
# @param [String] path XPath or CSS path
|
101
|
-
# @return [Nokogiri::
|
102
|
+
# @return [Nokogiri::XML::Node]
|
102
103
|
def at!(path, node = doc)
|
103
104
|
node.at(path) or raise Error::NodeNotFound, "node for `#{path}` not found"
|
104
105
|
end
|
105
106
|
|
106
107
|
# +node.search(path) or raise error
|
107
108
|
# @param [String] path XPath or CSS path
|
108
|
-
# @return [Array<Nokogiri::
|
109
|
+
# @return [Array<Nokogiri::XML::Node>]
|
109
110
|
def search!(path, node = doc)
|
110
111
|
node.search(path) or raise Error::NodeNotFound, "node for `#{path}` not found"
|
111
112
|
end
|
@@ -1,31 +1,43 @@
|
|
1
1
|
module Pixiv
|
2
2
|
module PageCollection
|
3
3
|
def first?
|
4
|
-
|
4
|
+
next_url.nil?
|
5
5
|
end
|
6
6
|
|
7
7
|
def last?
|
8
|
-
|
8
|
+
prev_url.nil?
|
9
9
|
end
|
10
10
|
|
11
|
+
private
|
12
|
+
def not_implemented!
|
13
|
+
name = caller[0][/`([^']*)'/, 1]
|
14
|
+
raise NotImplementedError,
|
15
|
+
"unimplemented method `#{name}' for #{self}"
|
16
|
+
end
|
17
|
+
public
|
18
|
+
|
11
19
|
def next_url
|
12
|
-
|
20
|
+
not_implemented!
|
13
21
|
end
|
14
22
|
|
15
23
|
def prev_url
|
16
|
-
|
24
|
+
not_implemented!
|
17
25
|
end
|
18
26
|
|
19
27
|
def page_class
|
20
|
-
|
28
|
+
not_implemented!
|
29
|
+
end
|
30
|
+
|
31
|
+
def page_hashes
|
32
|
+
not_implemented!
|
21
33
|
end
|
22
34
|
|
23
35
|
def page_urls
|
24
|
-
|
36
|
+
page_hashes.map {|h| h[:url] }
|
25
37
|
end
|
26
38
|
|
27
|
-
def
|
28
|
-
|
39
|
+
def size
|
40
|
+
page_hashes.size
|
29
41
|
end
|
30
42
|
end
|
31
43
|
|
@@ -67,6 +79,23 @@ module Pixiv
|
|
67
79
|
end
|
68
80
|
end
|
69
81
|
|
82
|
+
def each_collection
|
83
|
+
collection = @collection
|
84
|
+
loop do
|
85
|
+
yield collection
|
86
|
+
next_url = collection.next_url or break
|
87
|
+
collection = collection.class.lazy_new { @client.agent.get(next_url) }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def count(*item)
|
92
|
+
if item.empty? && !block_given? && @collection.respond_to?(:total_count)
|
93
|
+
@collection.total_count
|
94
|
+
else
|
95
|
+
super
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
70
99
|
private
|
71
100
|
|
72
101
|
def pages_from_collection(collection)
|
@@ -77,13 +106,5 @@ module Pixiv
|
|
77
106
|
end
|
78
107
|
}
|
79
108
|
end
|
80
|
-
|
81
|
-
def each_collection(collection = @collection)
|
82
|
-
loop do
|
83
|
-
yield collection
|
84
|
-
break unless collection.next_url
|
85
|
-
collection = collection.class.new(@client.agent.get(collection.next_url))
|
86
|
-
end
|
87
|
-
end
|
88
109
|
end
|
89
110
|
end
|
data/lib/pixiv/version.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Pixiv
|
2
|
+
class WorkList < OwnedIllustList
|
3
|
+
# (see super.url)
|
4
|
+
def self.url(member_id, page = 1)
|
5
|
+
"#{ROOT_URL}/member_illust.php?id=#{member_id}&p=#{page}"
|
6
|
+
end
|
7
|
+
|
8
|
+
# @return [Integer]
|
9
|
+
lazy_attr_reader(:total_count) {
|
10
|
+
node = at!('.layout-cell .count-badge')
|
11
|
+
node.inner_text.match(/\d+/).to_s.to_i
|
12
|
+
}
|
13
|
+
# @return [Array<Hash{Symbol=>Object}, nil>]
|
14
|
+
lazy_attr_reader(:page_hashes) {
|
15
|
+
node = search!('.display_works li') \
|
16
|
+
.xpath('self::node()[not(starts-with(a[1]/@href, "/bookmark"))]')
|
17
|
+
node.map {|n| hash_from_list_item(n) }
|
18
|
+
}
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# @param [Nokogiri::XML::Node] node
|
23
|
+
# @return [Hash{Symbol=>Object}] illust_hash
|
24
|
+
def hash_from_list_item(node)
|
25
|
+
return nil if node.at('img[src*="limit_unknown_s.png"]')
|
26
|
+
illust_node = node.at('a')
|
27
|
+
illust_id = illust_node['href'].match(/illust_id=(\d+)/).to_a[1].to_i
|
28
|
+
{
|
29
|
+
url: Illust.url(illust_id),
|
30
|
+
illust_id: illust_id,
|
31
|
+
title: illust_node.inner_text,
|
32
|
+
member_id: member_id,
|
33
|
+
small_image_url: illust_node.at('img')['src'],
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pixiv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mechanize
|
@@ -94,10 +94,13 @@ files:
|
|
94
94
|
- lib/pixiv/client.rb
|
95
95
|
- lib/pixiv/error.rb
|
96
96
|
- lib/pixiv/illust.rb
|
97
|
+
- lib/pixiv/illust_list.rb
|
97
98
|
- lib/pixiv/member.rb
|
99
|
+
- lib/pixiv/owned_illust_list.rb
|
98
100
|
- lib/pixiv/page.rb
|
99
101
|
- lib/pixiv/page_collection.rb
|
100
102
|
- lib/pixiv/version.rb
|
103
|
+
- lib/pixiv/work_list.rb
|
101
104
|
- pixiv.gemspec
|
102
105
|
- spec/fixtures/empty.html
|
103
106
|
- spec/fixtures/illust_345.html
|
@@ -118,18 +121,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
118
121
|
- - ! '>='
|
119
122
|
- !ruby/object:Gem::Version
|
120
123
|
version: '0'
|
121
|
-
segments:
|
122
|
-
- 0
|
123
|
-
hash: -1798318064021145738
|
124
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
125
|
none: false
|
126
126
|
requirements:
|
127
127
|
- - ! '>='
|
128
128
|
- !ruby/object:Gem::Version
|
129
129
|
version: '0'
|
130
|
-
segments:
|
131
|
-
- 0
|
132
|
-
hash: -1798318064021145738
|
133
130
|
requirements: []
|
134
131
|
rubyforge_project:
|
135
132
|
rubygems_version: 1.8.24
|
@@ -144,3 +141,4 @@ test_files:
|
|
144
141
|
- spec/pixiv/member_spec.rb
|
145
142
|
- spec/pixiv/page_spec.rb
|
146
143
|
- spec/spec_helper.rb
|
144
|
+
has_rdoc:
|