anvisa-bot 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/FLUXO_SITE_ANVISA.txt +38 -0
- data/README.textile +64 -0
- data/Rakefile +53 -0
- data/bin/anvisa-bot +35 -0
- data/lib/anvisa_bot.rb +31 -0
- data/lib/anvisa_browser.rb +101 -0
- data/lib/anvisa_parser.rb +90 -0
- metadata +89 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
===Fluxo para pesquisa por num. de registro no site da Anvisa===
|
2
|
+
|
3
|
+
POST rconsulta_produto_internet.asp
|
4
|
+
|
5
|
+
CO_TIPO_PRODUTO=8
|
6
|
+
Area=Cosmético
|
7
|
+
Processo=
|
8
|
+
Produto=
|
9
|
+
Registro=
|
10
|
+
CNPJ=
|
11
|
+
NO_EMPRESA=
|
12
|
+
|
13
|
+
-recebo o html de produtos.
|
14
|
+
-extrair os links e executar:
|
15
|
+
|
16
|
+
POST rconsulta_produto_detalhe.asp
|
17
|
+
|
18
|
+
CO_PRODUTO=var_codigo
|
19
|
+
NO_EMPRESA=var_empresa
|
20
|
+
NU_CNPJ=var_cnpj
|
21
|
+
REGISTRO=var_registro
|
22
|
+
|
23
|
+
NU_PROCESSO=
|
24
|
+
NO_PRODUTO=
|
25
|
+
NU_REGISTRO=
|
26
|
+
NU_AUTORIZACAO=
|
27
|
+
|
28
|
+
CO_TIPO_PRODUTO=8
|
29
|
+
hdnpgAtual=1
|
30
|
+
hdnmodo=
|
31
|
+
PROCESSO=
|
32
|
+
PRODUTO=
|
33
|
+
EMPRESA=
|
34
|
+
CNPJ=
|
35
|
+
|
36
|
+
-recebe o html de detalhe do produto
|
37
|
+
-extrair as informacoes e retornar
|
38
|
+
|
data/README.textile
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
h1. anvisa-bot
|
2
|
+
|
3
|
+
anvisa-bot é uma API Ruby para consultar Produtos para Saúde Registrados.
|
4
|
+
|
5
|
+
Até o momento, somente a busca por registro anvisa foi implementada.
|
6
|
+
Esta API faz requests e parse no HTML do site da anvisa para fornecer informações sobre produtos.
|
7
|
+
|
8
|
+
Site da Anvisa:
|
9
|
+
|
10
|
+
http://www.anvisa.gov.br/scriptsweb/correlato/correlato.htm
|
11
|
+
|
12
|
+
h2. Instalação
|
13
|
+
|
14
|
+
@sudo gem install rogerleite-anvisa-bot -s http://gems.github.com@
|
15
|
+
|
16
|
+
h2. Usando como executável
|
17
|
+
|
18
|
+
$ anvisa-bot "numero_registro_anvisa" <br>
|
19
|
+
Por exemplo:
|
20
|
+
@anvisa-bot 10008530225@
|
21
|
+
|
22
|
+
h2. Usando a API Ruby
|
23
|
+
|
24
|
+
<pre>
|
25
|
+
require "rubygems"
|
26
|
+
require "anvisa_bot"
|
27
|
+
|
28
|
+
produto = AnvisaBot.consulta_produto_por_registro(10247530027)
|
29
|
+
|
30
|
+
puts produto.empresa
|
31
|
+
puts produto.cnpj
|
32
|
+
puts produto.autorizacao
|
33
|
+
puts produto.nome
|
34
|
+
puts produto.modelo
|
35
|
+
puts produto.registro
|
36
|
+
puts produto.processo
|
37
|
+
puts produto.origem
|
38
|
+
puts produto.vencimento_registro
|
39
|
+
</pre>
|
40
|
+
|
41
|
+
h2. LICENSE:
|
42
|
+
|
43
|
+
(The MIT License)
|
44
|
+
|
45
|
+
Copyright (c) 2008 FIX
|
46
|
+
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
48
|
+
a copy of this software and associated documentation files (the
|
49
|
+
'Software'), to deal in the Software without restriction, including
|
50
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
51
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
52
|
+
permit persons to whom the Software is furnished to do so, subject to
|
53
|
+
the following conditions:
|
54
|
+
|
55
|
+
The above copyright notice and this permission notice shall be
|
56
|
+
included in all copies or substantial portions of the Software.
|
57
|
+
|
58
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
59
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
60
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
61
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
62
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
63
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
64
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubygems/specification'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'spec/rake/spectask'
|
6
|
+
|
7
|
+
GEM = "anvisa-bot"
|
8
|
+
GEM_VERSION = "0.2.3"
|
9
|
+
SUMMARY = "Pesquisa de produtos para saúde registrados"
|
10
|
+
AUTHOR = "Roger Leite"
|
11
|
+
EMAIL = "roger.barreto@gmail.com"
|
12
|
+
HOMEPAGE = "http://github.com/rogerleite/anvisa-bot"
|
13
|
+
|
14
|
+
|
15
|
+
spec = Gem::Specification.new do |s|
|
16
|
+
s.name = GEM
|
17
|
+
s.version = GEM_VERSION
|
18
|
+
s.platform = Gem::Platform::RUBY
|
19
|
+
s.summary = SUMMARY
|
20
|
+
s.require_paths = ['bin', 'lib']
|
21
|
+
s.files = FileList['bin/*.rb', 'lib/**/*.rb', '[A-Z]*'].to_a
|
22
|
+
s.executables = ["anvisa-bot"]
|
23
|
+
|
24
|
+
s.author = AUTHOR
|
25
|
+
s.email = EMAIL
|
26
|
+
s.homepage = HOMEPAGE
|
27
|
+
|
28
|
+
s.rubyforge_project = GEM # GitHub bug, gem isn't being build when this miss
|
29
|
+
|
30
|
+
s.add_dependency(%q<hpricot>, [">= 0.8.1"])
|
31
|
+
end
|
32
|
+
|
33
|
+
Spec::Rake::SpecTask.new do |t|
|
34
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
35
|
+
t.spec_opts = %w(-fs --color)
|
36
|
+
end
|
37
|
+
|
38
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
39
|
+
pkg.gem_spec = spec
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Install the gem locally"
|
43
|
+
task :install => [:package] do
|
44
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Create a gemspec file"
|
48
|
+
task :make_spec do
|
49
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
50
|
+
file.puts spec.to_ruby
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
data/bin/anvisa-bot
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Exemplo de comando:
|
4
|
+
# ruby bin/anvisa-bot.rb 10008530225
|
5
|
+
# exemplos de registros anvisa:
|
6
|
+
# - 10008530225
|
7
|
+
# - 10247530027
|
8
|
+
# - 80175510005
|
9
|
+
|
10
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../lib")
|
11
|
+
|
12
|
+
require "anvisa_bot"
|
13
|
+
|
14
|
+
args = ARGV.dup
|
15
|
+
ARGV.clear
|
16
|
+
|
17
|
+
puts "usage: anvisa-bot <registro_anvisa>"
|
18
|
+
|
19
|
+
numero_registro = args[0]
|
20
|
+
produto = AnvisaBot.consulta_produto_por_registro(numero_registro)
|
21
|
+
|
22
|
+
puts produto.to_yaml
|
23
|
+
|
24
|
+
=begin
|
25
|
+
puts <<HTML
|
26
|
+
<html>
|
27
|
+
<body>
|
28
|
+
<div>
|
29
|
+
<p>empresa: #{produto.empresa}</p><br>
|
30
|
+
<p>modelo: #{produto.modelo}</p>
|
31
|
+
</div>
|
32
|
+
</body>
|
33
|
+
</html>
|
34
|
+
HTML
|
35
|
+
=end
|
data/lib/anvisa_bot.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "anvisa_browser"
|
2
|
+
require "anvisa_parser"
|
3
|
+
|
4
|
+
class AnvisaBot
|
5
|
+
|
6
|
+
#veja o fluxo de "navegacao" do bot no arquivo fluxo_site_anvisa.txt
|
7
|
+
def self.consulta_produto_por_registro(numero_registro)
|
8
|
+
begin
|
9
|
+
anvisa_browser = create_anvisa_browser
|
10
|
+
plain_html = anvisa_browser.consulta_produto_por_registro(numero_registro)
|
11
|
+
|
12
|
+
#puts "ZZZ ... ~10 segs"
|
13
|
+
#sleep( rand(10) ) #para não chamar atencao do server
|
14
|
+
|
15
|
+
links = AnvisaParser.find_links_produtos(plain_html)
|
16
|
+
return Produto.new({:not_found => true}) if links.empty?
|
17
|
+
|
18
|
+
plain_html = anvisa_browser.consulta_produto_detalhe(numero_registro, links.first)
|
19
|
+
AnvisaParser.extract_produto(plain_html)
|
20
|
+
rescue => ex
|
21
|
+
Produto.new({:error => ex})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
#usado para injetar stubs ao rodar specs
|
26
|
+
def self.create_anvisa_browser
|
27
|
+
AnvisaBrowser.new
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
class AnvisaBrowser
|
5
|
+
|
6
|
+
ANVISA_URL = 'http://www7.anvisa.gov.br/datavisa/Consulta_Produto_correlato/'
|
7
|
+
USER_AGENT = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.13) Gecko/2009080315 Ubuntu/9.04 (jaunty) Firefox/3.0.13"
|
8
|
+
DEBUG_REQ = false
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :default_headers
|
12
|
+
end
|
13
|
+
self.default_headers = {
|
14
|
+
'User-Agent' => USER_AGENT,
|
15
|
+
'Accept' => 'text/html',
|
16
|
+
'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'
|
17
|
+
}
|
18
|
+
|
19
|
+
def consulta_produto_por_registro(numero_registro)
|
20
|
+
plain_url = "#{ANVISA_URL}rconsulta_produto_internet.asp"
|
21
|
+
params = {
|
22
|
+
:CO_TIPO_PRODUTO => '8', :Area => 'Cosmético', :Processo => '',
|
23
|
+
:Produto => '', :CNPJ => '', :NO_EMPRESA => '',
|
24
|
+
:Registro => numero_registro
|
25
|
+
}
|
26
|
+
|
27
|
+
user_headers = {
|
28
|
+
'Referer' => 'http://www7.anvisa.gov.br/datavisa/Consulta_Produto_correlato/consulta_correlato.asp'
|
29
|
+
}
|
30
|
+
|
31
|
+
simple_post(plain_url, params, user_headers)
|
32
|
+
end
|
33
|
+
|
34
|
+
def consulta_produto_detalhe(numero_registro, link_produto)
|
35
|
+
plain_url = "#{ANVISA_URL}rconsulta_produto_detalhe.asp"
|
36
|
+
params = {
|
37
|
+
:CO_PRODUTO => link_produto.codigo,
|
38
|
+
:NO_EMPRESA => link_produto.empresa,
|
39
|
+
:NU_CNPJ => link_produto.cnpj,
|
40
|
+
:REGISTRO => numero_registro,
|
41
|
+
:NU_PROCESSO => '',
|
42
|
+
:NO_PRODUTO => '',
|
43
|
+
:NU_REGISTRO => '',
|
44
|
+
:NU_AUTORIZACAO => '',
|
45
|
+
:CO_TIPO_PRODUTO => '8',
|
46
|
+
:hdnpgAtual => '1',
|
47
|
+
:hdnmodo => '',
|
48
|
+
:PROCESSO => '',
|
49
|
+
:PRODUTO => '',
|
50
|
+
:EMPRESA => '',
|
51
|
+
:CNPJ => ''
|
52
|
+
}
|
53
|
+
|
54
|
+
user_headers = {
|
55
|
+
'Referer' => 'http://www7.anvisa.gov.br/datavisa/Consulta_Produto_correlato/consulta_correlato.asp'
|
56
|
+
}
|
57
|
+
|
58
|
+
simple_post(plain_url, params, user_headers)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
# Faz um post simples e retorna o "plain html" da pagina.
|
63
|
+
# fonte: http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html
|
64
|
+
def simple_post(plain_url, params, user_headers)
|
65
|
+
url = URI.parse(plain_url)
|
66
|
+
|
67
|
+
headers = self.class.default_headers.merge(user_headers)
|
68
|
+
|
69
|
+
req = Net::HTTP::Post.new(url.path, headers)
|
70
|
+
req.set_form_data(params)
|
71
|
+
|
72
|
+
if DEBUG_REQ
|
73
|
+
puts "=== Debug Http Request"
|
74
|
+
puts "url => #{url}"
|
75
|
+
puts "body => #{req.body}"
|
76
|
+
puts "=== Fim Debug Http Request"
|
77
|
+
end
|
78
|
+
|
79
|
+
res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
|
80
|
+
case res
|
81
|
+
when Net::HTTPSuccess, Net::HTTPRedirection
|
82
|
+
# OK
|
83
|
+
else
|
84
|
+
res.error!
|
85
|
+
end
|
86
|
+
|
87
|
+
plain_html = res.body
|
88
|
+
if DEBUG_REQ
|
89
|
+
puts "=== Debug Http Response Body"
|
90
|
+
puts plain_html
|
91
|
+
puts "=== Fim Debug Http Response Body"
|
92
|
+
end
|
93
|
+
plain_html
|
94
|
+
end
|
95
|
+
|
96
|
+
def make_headers(user_headers)
|
97
|
+
self.class.default_headers.merge(user_headers)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "hpricot"
|
3
|
+
|
4
|
+
class AnvisaParser
|
5
|
+
|
6
|
+
DEBUG = false
|
7
|
+
|
8
|
+
def self.find_links_produtos(plain_html)
|
9
|
+
html = Hpricot(plain_html)
|
10
|
+
links = []
|
11
|
+
html.search('a[@href*="ver_detalhes"]').each do |link|
|
12
|
+
#link['href'] returns:
|
13
|
+
#javascript:ver_detalhes('302629','LABORAT%C3%93RIOS%20B.%20BRAUN%20S/A','31673254000102');
|
14
|
+
params = link['href'].scan(/'([^']*)'/) #ER, pega os valores que estão dentro das ''
|
15
|
+
links << LinkProduto.new(params[0].to_s, params[1].to_s, params[2].to_s)
|
16
|
+
end
|
17
|
+
links
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.extract_produto(plain_html)
|
21
|
+
|
22
|
+
html = Hpricot(plain_html)
|
23
|
+
|
24
|
+
table = html.at("table.formulario")
|
25
|
+
#devido a html errado da anvisa (ln 106 e 116), subo dois niveis e ignoro o primeiro td
|
26
|
+
table = table.parent.parent.parent
|
27
|
+
|
28
|
+
values = []
|
29
|
+
ignore_first = true
|
30
|
+
table.search("td").each do |td|
|
31
|
+
if ignore_first
|
32
|
+
ignore_first = false
|
33
|
+
next
|
34
|
+
end
|
35
|
+
if DEBUG
|
36
|
+
puts '=== td.inner_html ==='
|
37
|
+
puts td.inner_html
|
38
|
+
end
|
39
|
+
value = td.inner_html
|
40
|
+
value.gsub!(/ /, ' ') #substitui o espaco do html por espaco
|
41
|
+
value.strip! #remove espacos adicionais
|
42
|
+
value.gsub!(/(<br>|<br\s\/>)/, "\n")
|
43
|
+
value.gsub!(/<[^>]*>/, '') #remove qualquer tag restante
|
44
|
+
values << value
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
Produto.new(:empresa => values[0], :cnpj => values[1], :autorizacao => values[2],
|
49
|
+
:nome => values[3], :modelo => values[4], :registro => values[5],
|
50
|
+
:processo => values[6], :origem => values[7], :vencimento_registro => values[8])
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
class LinkProduto
|
56
|
+
|
57
|
+
attr_accessor :codigo, :empresa, :cnpj
|
58
|
+
|
59
|
+
def initialize(codigo, empresa, cnpj)
|
60
|
+
@codigo = codigo
|
61
|
+
@empresa = empresa
|
62
|
+
@cnpj = cnpj
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class Produto
|
68
|
+
|
69
|
+
attr_accessor :empresa, :cnpj, :autorizacao,
|
70
|
+
:nome, :modelo, :registro,
|
71
|
+
:processo,:origem, :vencimento_registro,
|
72
|
+
:error, :not_found
|
73
|
+
|
74
|
+
def initialize(args)
|
75
|
+
raise ArgumentError("Args have to be a Hash with attributes") unless args.is_a?(Hash)
|
76
|
+
args.each do |att, value|
|
77
|
+
self.send("#{att}=", value)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def error?
|
82
|
+
!!error
|
83
|
+
end
|
84
|
+
|
85
|
+
def not_found?
|
86
|
+
!!not_found
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: anvisa-bot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 17
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Roger Leite
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-06-16 00:00:00 -03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: hpricot
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 61
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 8
|
33
|
+
- 1
|
34
|
+
version: 0.8.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description:
|
38
|
+
email: roger.barreto@gmail.com
|
39
|
+
executables:
|
40
|
+
- anvisa-bot
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- lib/anvisa_bot.rb
|
47
|
+
- lib/anvisa_parser.rb
|
48
|
+
- lib/anvisa_browser.rb
|
49
|
+
- Rakefile
|
50
|
+
- FLUXO_SITE_ANVISA.txt
|
51
|
+
- README.textile
|
52
|
+
- bin/anvisa-bot
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/rogerleite/anvisa-bot
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- bin
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project: anvisa-bot
|
84
|
+
rubygems_version: 1.4.1
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: "Pesquisa de produtos para sa\xC3\xBAde registrados"
|
88
|
+
test_files: []
|
89
|
+
|