brfipe 0.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d25af6364acb0195abff8a550e61bb8802ba07ab
4
+ data.tar.gz: 140ad256104e3b0f3e2c7c51851ab02556b4eac9
5
+ SHA512:
6
+ metadata.gz: 9619a57b0f3db5e7ae3de4ccda1c7688bd0c7d265556c48f97563e6c670473fc0bf75fbd5763c34ded680156e0146940af36fa2b1db90e204a0a41320124f0c6
7
+ data.tar.gz: f9146d9be5c9facb506493159777fb4cd7284ac24833e993bb64a0e0cb4f35e161fb093a961406a376119701f518bad489a552fd8efbdb15da4523761173c807
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ brfipe
2
+ ======
3
+
4
+ brfipe é uma gem que tem como objetivo realizar consultas no site da fipe (fundação instituto de pesquisas econômicas) na seção de "Preço Médio de Veículos".
data/brfipe.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ #encoding: UTF-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require "brfipe/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "brfipe"
8
+ s.version = Brfipe::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Rodrigo Batista da Silva"]
11
+ s.email = ["rbsilva.ti@gmail.com"]
12
+ s.homepage = "https://github.com/rbsilva/brfipe"
13
+ s.summary = "Gem para consultas no site da fipe."
14
+ s.description = "brfipe é uma gem que tem como objetivo realizar consultas no site da fipe (fundação instituto de pesquisas econômicas) na seção de \"Preço Médio de Veículos\"."
15
+
16
+ s.rubyforge_project = "brfipe"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
20
+
21
+ s.add_development_dependency "rspec"
22
+ end
@@ -0,0 +1,342 @@
1
+ # encoding: UTF-8
2
+ class Fipe
3
+ require 'socket'
4
+ require 'open-uri'
5
+ require 'bigdecimal'
6
+
7
+ # Domínio e página de consulta de preços de veículos
8
+ DOMAIN = 'fipe.org.br'
9
+ URL = '/web/indices/veiculos/default.aspx?'
10
+
11
+ # Constantes com os parâmetros necessários para obter os dados do site da fipe.
12
+ CARRO = 'p=51'
13
+ MOTO = 'v=m&p=52'
14
+ CAMINHAO = 'v=c&p=53'
15
+
16
+ # Tentativas de acesso ao site
17
+ TENTATIVAS = 3
18
+
19
+ def self.busca_por_codigo(argumentos={})
20
+ raise Exception.new('Tabela deve ser preenchida') if !argumentos[:tabela]
21
+ tabela = argumentos[:tabela]
22
+
23
+ raise Exception.new('Codigo fipe deve ser preenchido') if !argumentos[:codigo_fipe]
24
+ codigo_fipe = argumentos[:codigo_fipe]
25
+
26
+ raise Exception.new('Ano/Modelo deve ser preenchido') if !argumentos[:ano_modelo]
27
+ ano_modelo = argumentos[:ano_modelo]
28
+
29
+ veiculo = argumentos[:veiculo] ? argumentos[:veiculo] : CARRO
30
+
31
+ pagina_de_pesquisa = read_page("http://www.#{DOMAIN}#{URL}#{veiculo}")
32
+
33
+ view_state = catch_view_state(pagina_de_pesquisa)
34
+ event_validation = catch_event_validation(pagina_de_pesquisa)
35
+
36
+ data = []
37
+ data << ["__EVENTARGUMENT", ""]
38
+ data << ["ddlTabelaReferencia", tabela]
39
+ data << ["btnCodFipe", "Pesquisar"]
40
+ data << ["ddlMarca", '0']
41
+ data << ["ddlModelo", '0']
42
+ data << ["txtCodFipe", codigo_fipe]
43
+ data << ["__EVENTVALIDATION", event_validation]
44
+ data << ["__VIEWSTATE", view_state]
45
+
46
+ page = get_data(data, veiculo)
47
+
48
+ view_state = catch_view_state(page)
49
+ event_validation = catch_event_validation(page)
50
+
51
+ data = []
52
+ data << ["__EVENTARGUMENT", ""]
53
+ data << ["ddlTabelaReferencia", tabela]
54
+ data << ["ddlAnoValor", ano_modelo]
55
+ data << ["txtCodFipe", codigo_fipe]
56
+ data << ["__EVENTTARGET", "ddlAnoValor"]
57
+ data << ["ScriptManager1", "updAnoValor|ddlAnoValor"]
58
+ data << ["__EVENTVALIDATION", event_validation]
59
+ data << ["__VIEWSTATE", view_state]
60
+
61
+ page = get_data(data, veiculo)
62
+
63
+ { :preco => extrai_preco(page), :marca => extrai_marca(page), :modelo => extrai_modelo(page), :ano_modelo => extrai_ano_modelo(page), :mes_referencia => extrai_mes_referencia(page) }
64
+ end
65
+
66
+ def self.busca(argumentos={})
67
+ tabela = argumentos[:tabela] ? argumentos[:tabela] : nil
68
+
69
+ # Marca, modelo e ano_modelo quando não informados devem ser '0'
70
+ marca = argumentos[:marca] ? argumentos[:marca] : '0'
71
+ modelo = argumentos[:modelo] ? argumentos[:modelo] : '0'
72
+ ano_modelo = argumentos[:ano_modelo] ? argumentos[:ano_modelo] : '0'
73
+
74
+ veiculo = argumentos[:veiculo] ? argumentos[:veiculo] : CARRO
75
+
76
+ # Verifica se é uma chamada interna da própria função
77
+ interno = argumentos[:interno] ? argumentos[:interno] : false
78
+
79
+ pagina_de_pesquisa = read_page("http://www.#{DOMAIN}#{URL}#{veiculo}")
80
+
81
+ view_state = catch_view_state(pagina_de_pesquisa)
82
+ event_validation = catch_event_validation(pagina_de_pesquisa)
83
+
84
+ data = []
85
+ data << ["__EVENTARGUMENT", ""]
86
+ data << ["ddlTabelaReferencia", tabela]
87
+ data << ["ddlMarca", marca]
88
+ data << ["ddlAnoValor", ano_modelo]
89
+ data << ["ddlModelo", modelo]
90
+
91
+ if !tabela then
92
+ { :atual => extrai_atual(pagina_de_pesquisa), :tabelas => extrai_tabelas(pagina_de_pesquisa) }
93
+ elsif marca == '0' then
94
+ data << ["__EVENTVALIDATION", event_validation]
95
+ data << ["__VIEWSTATE", view_state]
96
+ data << ["ScriptManager1", "ScriptManager1|ddlTabelaReferencia"]
97
+ data << ["__EVENTTARGET", "ddlTabelaReferencia"]
98
+
99
+ page = get_data(data, veiculo)
100
+
101
+ view_state = catch_view_state(page)
102
+ event_validation = catch_event_validation(page)
103
+
104
+ resposta = { :marcas => extrai_marcas(page), :view_state => view_state, :event_validation => event_validation }
105
+
106
+ if interno
107
+ resposta
108
+ else
109
+ resposta.delete(:view_state)
110
+ resposta.delete(:event_validation)
111
+ resposta
112
+ end
113
+
114
+ elsif modelo == '0' then
115
+ result = busca(:tabela => tabela, :veiculo => veiculo, :interno => true)
116
+
117
+ view_state = result[:view_state]
118
+ event_validation = result[:event_validation]
119
+
120
+ data << ["__EVENTVALIDATION", event_validation]
121
+ data << ["__VIEWSTATE", view_state]
122
+ data << ["ScriptManager1", "ScriptManager1|ddlMarca"]
123
+ data << ["__EVENTTARGET", "ddlMarca"]
124
+
125
+ page = get_data(data, veiculo)
126
+
127
+ view_state = catch_view_state(page)
128
+ event_validation = catch_event_validation(page)
129
+
130
+ resposta = { :modelos => extrai_modelos(page), :view_state => view_state, :event_validation => event_validation }
131
+
132
+ if interno
133
+ resposta
134
+ else
135
+ resposta.delete(:view_state)
136
+ resposta.delete(:event_validation)
137
+ resposta
138
+ end
139
+
140
+ elsif ano_modelo == '0' then
141
+ result = busca(:tabela => tabela, :marca => marca, :veiculo => veiculo, :interno => true)
142
+
143
+ view_state = result[:view_state]
144
+ event_validation = result[:event_validation]
145
+
146
+ data << ["__EVENTVALIDATION", event_validation]
147
+ data << ["__VIEWSTATE", view_state]
148
+ data << ["ScriptManager1", "updModelo|ddlModelo"]
149
+ data << ["__EVENTTARGET", "ddlModelo"]
150
+
151
+ page = get_data(data, veiculo)
152
+
153
+ view_state = catch_view_state(page)
154
+ event_validation = catch_event_validation(page)
155
+
156
+ resposta = { :anos_modelos => extrai_anos_modelos(page), :view_state => view_state, :event_validation => event_validation }
157
+
158
+ if interno
159
+ resposta
160
+ else
161
+ resposta.delete(:view_state)
162
+ resposta.delete(:event_validation)
163
+ resposta
164
+ end
165
+
166
+ else
167
+ result = busca(:tabela => tabela, :marca => marca, :modelo => modelo, :veiculo => veiculo, :interno => true)
168
+
169
+ view_state = result[:view_state]
170
+ event_validation = result[:event_validation]
171
+
172
+ data << ["__EVENTVALIDATION", event_validation]
173
+ data << ["__VIEWSTATE", view_state]
174
+ data << ["ScriptManager1", "updAnoValor|ddlAnoValor"]
175
+ data << ["__EVENTTARGET", "ddlAnoValor"]
176
+
177
+ page = get_data(data, veiculo)
178
+
179
+ extrai_preco(page)
180
+ end
181
+ end
182
+
183
+ private
184
+ def self.read_page(url)
185
+ tries = 0
186
+ begin
187
+ source = open(url).read
188
+ rescue
189
+ tries += 1
190
+ if tries <= TENTATIVAS
191
+ warn "Tentativa: #{tries}"
192
+ retry
193
+ else
194
+ raise
195
+ end
196
+ end
197
+ end
198
+
199
+ def self.get(host, port, path, data)
200
+ tries = 0
201
+ begin
202
+ sdata = URI::encode_www_form(data)
203
+
204
+ s = TCPSocket.open(host, port)
205
+ s.write("POST " + path + " HTTP/1.1\r\n")
206
+ s.write("Host: " + host + "\r\n")
207
+ s.write("Content-type: application/x-www-form-urlencoded\r\n")
208
+ s.write("Content-length: " + sdata.length.to_s + "\r\n")
209
+ s.write("Connection: close\r\n\r\n")
210
+ s.write(sdata + "\r\n\r\n")
211
+ s.flush
212
+ response = ''
213
+ while line = s.gets
214
+ response += line
215
+ end
216
+ s.close
217
+ response
218
+ rescue
219
+ tries += 1
220
+ if tries <= TENTATIVAS
221
+ warn "Tentativa: #{tries}"
222
+ retry
223
+ else
224
+ raise
225
+ end
226
+ end
227
+ end
228
+
229
+ def self.get_data(data, veiculo)
230
+ get(DOMAIN, 80, "#{URL}#{veiculo}", data)
231
+ end
232
+
233
+ def self.catch_view_state(lines)
234
+ view_state = ''
235
+ lines.split("\r\n").each do |line|
236
+ if line.match(/.*id=\"__VIEWSTATE\".*/) then
237
+ view_state = line.scan(/.*value="(.*)".*/).last.first
238
+ break
239
+ end
240
+ end
241
+ view_state
242
+ end
243
+
244
+ def self.catch_event_validation(lines)
245
+ event_validation = ''
246
+ lines.split("\r\n").each do |line|
247
+ if line.match(/.*id=\"__EVENTVALIDATION\".*/) then
248
+ event_validation = line.scan(/.*value="(.*)".*/).last.first
249
+ break
250
+ end
251
+ end
252
+ event_validation
253
+ end
254
+
255
+ # Extratores
256
+
257
+ def self.regex_html_tag(tag)
258
+ /^(.*)(<.*#{tag}(>|.*>))(.*)(<.*#{tag}(>|.*>))(.*)$/
259
+ end
260
+
261
+ def self.extrai_atual(html)
262
+ html.scan(/value=\"(.*)\">Atual<\/option>/).last.first
263
+ end
264
+
265
+ def self.extrai_tabelas(html)
266
+ returning = {}
267
+ extract(html, "Atual", regex_html_tag("option"), /.*<\/select>.*/) do |result|
268
+ code = result.scan(/\"(.*)\"/).last.first
269
+ name = result.scan(/>(.*)<\//).last.first
270
+ returning.store(code, name)
271
+ end
272
+ returning
273
+ end
274
+
275
+ def self.extrai_marcas(html)
276
+ returning = {}
277
+ extract(html, "Selecione uma marca", regex_html_tag("option"), /.*<\/select>.*/) do |result|
278
+ code = result.scan(/\"(.*)\"/).last.first
279
+ name = result.scan(/>(.*)<\//).last.first
280
+ returning.store(code, name)
281
+ end
282
+ returning
283
+ end
284
+
285
+ def self.extrai_modelos(html)
286
+ returning = {}
287
+ extract(html, "Selecione um modelo", regex_html_tag("option"), /.*<\/select>.*/) do |result|
288
+ code = result.scan(/\"(.*)\"/).last.first
289
+ name = result.scan(/>(.*)<\//).last.first
290
+ returning.store(code, name)
291
+ end
292
+ returning
293
+ end
294
+
295
+ def self.extrai_anos_modelos(html)
296
+ returning = {}
297
+ extract(html, "Selecione um ano modelo", regex_html_tag("option"), /.*<\/select>.*/) do |result|
298
+ code = result.scan(/\"(.*)\"/).last.first
299
+ name = result.scan(/>(.*)<\//).last.first
300
+ returning.store(code, name)
301
+ end
302
+ returning
303
+ end
304
+
305
+ def self.extrai_mes_referencia(html)
306
+ html.scan(/.*id=\"lblReferencia\".*>(.*)<\/span>/).last.first.strip
307
+ end
308
+
309
+ def self.extrai_ano_modelo(html)
310
+ html.scan(/.*id=\"lblAnoModelo\".*>(.*)<\/span>/).last.first.strip
311
+ end
312
+
313
+ def self.extrai_modelo(html)
314
+ html.scan(/.*id=\"lblModelo\".*>(.*)<\/span>/).last.first.strip
315
+ end
316
+
317
+ def self.extrai_marca(html)
318
+ html.scan(/.*id=\"lblMarca\".*>(.*)<\/span>/).last.first.strip
319
+ end
320
+
321
+ def self.extrai_preco(html)
322
+ returning = ''
323
+ extract(html, "Ano Modelo", /.*id=\"lblValor\".*/, /^$/) do |result|
324
+ price = result.scan(/R\$(.*)<\/span>/).last.first
325
+ price = price.gsub /\./, ''
326
+ returning = price.gsub /,/, '.'
327
+ end
328
+ BigDecimal.new(returning.strip)
329
+ end
330
+
331
+ def self.extract(html, key, beginning, finish)
332
+ results = html[html.index(key)..-1].split("\r\n");
333
+ results.each do | result|
334
+ if result.strip.match(beginning) then
335
+ yield result
336
+ end
337
+ if result.match(finish) then
338
+ break
339
+ end
340
+ end
341
+ end
342
+ end
@@ -0,0 +1,3 @@
1
+ module Brfipe
2
+ VERSION = "0.0.0"
3
+ end
data/lib/brfipe.rb ADDED
@@ -0,0 +1 @@
1
+ require 'brfipe/fipe'
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brfipe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Rodrigo Batista da Silva
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2013-05-10 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - &id002
20
+ - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ type: :development
24
+ version_requirements: *id001
25
+ description: "brfipe \xC3\xA9 uma gem que tem como objetivo realizar consultas no site da fipe (funda\xC3\xA7\xC3\xA3o instituto de pesquisas econ\xC3\xB4micas) na se\xC3\xA7\xC3\xA3o de \"Pre\xC3\xA7o M\xC3\xA9dio de Ve\xC3\xADculos\"."
26
+ email:
27
+ - rbsilva.ti@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - .gitignore
36
+ - README.md
37
+ - brfipe.gemspec
38
+ - lib/brfipe.rb
39
+ - lib/brfipe/fipe.rb
40
+ - lib/brfipe/version.rb
41
+ homepage: https://github.com/rbsilva/brfipe
42
+ licenses: []
43
+
44
+ metadata: {}
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - *id002
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - *id002
57
+ requirements: []
58
+
59
+ rubyforge_project: brfipe
60
+ rubygems_version: 2.0.3
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: Gem para consultas no site da fipe.
64
+ test_files: []
65
+