Class: Alexandria::BookProviders::BarnesAndNobleProvider
Constant Summary
collapse
- SITE =
'http://www.barnesandnoble.com'
- BASE_ISBN_SEARCH_URL =
'http://www.barnesandnoble.com/s/%s'
- BASE_SEARCH_URL =
'http://search.barnesandnoble.com/booksearch' \
'/results.asp?%s=%s'
Instance Attribute Summary
#fullname, #name, #prefs
Instance Method Summary
collapse
Methods included from Logging
included, #log
#html_to_doc, #text_of
#<=>, abstract?, #abstract?, #action_name, #enabled, #reinitialize, #remove, #toggle_enabled, #transport, unabstract, #variable_name
Constructor Details
47
48
49
50
51
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 47
def initialize
super('BarnesAndNoble', 'BarnesAndNoble')
@agent = nil
prefs.read
end
|
Instance Method Details
#agent ⇒ Object
53
54
55
56
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 53
def agent
@agent ||= Alexandria::WWWAgent.new
@agent
end
|
#create_search_uri(search_type, search_term) ⇒ Object
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 101
def create_search_uri(search_type, search_term)
(search_type_code = {
SEARCH_BY_AUTHORS => 'ATH',
SEARCH_BY_TITLE => 'TTL',
SEARCH_BY_KEYWORD => 'WRD' }[search_type]) || ''
if search_type == SEARCH_BY_ISBN
BASE_ISBN_SEARCH_URL % Library.canonicalise_ean(search_term) else
search_term_encoded = CGI.escape(search_term)
format(BASE_SEARCH_URL, search_type_code, search_term_encoded)
end
end
|
#fetch_redirectly(uri_str, limit = 5) ⇒ Object
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 58
def fetch_redirectly(uri_str, limit = 5)
raise NoResultsError, 'HTTP redirect too deep' if limit.zero?
if limit < 10
sleep 0.1
log.debug { "Redirectly :: #{uri_str}" }
else
log.debug { "Fetching :: #{uri_str}" }
end
response = agent.get(uri_str)
log.debug { response.inspect }
case response
when Net::HTTPSuccess then response
when Net::HTTPRedirection then
redirect = URI.parse response['Location']
redirect = URI.parse(uri_str) + redirect if redirect.relative?
fetch_redirectly(redirect.to_s, (limit - 1))
else
response.error!
end
end
|
#get_book_from_search_result(result) ⇒ Object
115
116
117
118
119
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 115
def get_book_from_search_result(result)
log.debug { "Fetching book from #{result[:url]}" }
html_data = transport.get_response(URI.parse(result[:url]))
parse_result_data(html_data.body)
end
|
#parse_result_data(html, _search_isbn = nil, _recursing = false) ⇒ Object
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 147
def parse_result_data(html, _search_isbn = nil, _recursing = false)
doc = html_to_doc(html)
begin
book_data = {}
dl = (doc / 'dl').first
dts = dl.children_of_type('dt')
dts.each do |dt|
value = dt.next_sibling.inner_text
case dt.inner_text
when /ISBN-13/
book_data[:isbn] = Library.canonicalise_ean(value)
when /Publisher/
book_data[:publisher] = value
when /Publication data/
value =~ /\d{2}.\d{2}.(\d{4})/
year = Regexp.last_match[1]
book_data[:publisher] = year
end
end
meta = doc / 'meta'
meta.each do |it|
attrs = it.attributes
property = attrs['property']
next unless property
case property
when 'og:title'
book_data[:title] = attrs['content']
when 'og:image'
book_data[:image_url] = attrs['content']
end
end
author_links = doc / 'span.contributors a'
authors = author_links.map(&:inner_text)
book_data[:authors] = authors
book_data[:binding] = ''
selected_format = (doc / '#availableFormats li.selected a.tabTitle').first
book_data[:binding] = selected_format.inner_text if selected_format
book = Book.new(book_data[:title], book_data[:authors],
book_data[:isbn], book_data[:publisher],
book_data[:publication_year],
book_data[:binding])
return [book, book_data[:image_url]]
rescue => ex
raise ex if ex.instance_of? NoResultsError
trace = ex.backtrace.join("\n> ")
log.warn {
'Failed parsing search results for BarnesAndNoble ' \
"#{ex.message} #{trace}"
}
raise NoResultsError
end
end
|
#parse_search_result_data(html) ⇒ Object
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 121
def parse_search_result_data(html)
doc = html_to_doc(html)
book_search_results = []
begin
result_divs = doc / 'div[@class*="book-container"]'
result_divs.each do |div|
result = {}
= div % 'h2'
title_links = / 'a'
result[:title] = title_links.first.inner_text
result[:url] = title_links.first['href']
book_search_results << result
end
rescue => ex
trace = ex.backtrace.join("\n> ")
log.warn {
'Failed parsing search results for Barnes & Noble ' \
"#{ex.message} #{trace}"
}
end
book_search_results
end
|
#search(criterion, type) ⇒ Object
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 79
def search(criterion, type)
req = create_search_uri(type, criterion)
puts "Requesting #{req}" if $DEBUG
html_data = fetch_redirectly(req)
if type == SEARCH_BY_ISBN
parse_result_data(html_data.body, criterion)
else
results = parse_search_result_data(html_data.body)
raise NoResultsError if results.empty?
results.map { |result| get_book_from_search_result(result) }
end
end
|
#url(book) ⇒ Object
94
95
96
97
98
99
|
# File 'lib/alexandria/book_providers/barnes_and_noble.rb', line 94
def url(book)
create_search_uri(SEARCH_BY_ISBN, book.isbn)
rescue => ex
log.warn { "Cannot create url for book #{book}; #{ex.message}" }
nil
end
|