fech-search 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 90335ce5578a65937b78fef37e814bf8e44e1eeb
4
- data.tar.gz: 6af0151ace9bece2b377c8599f8017a729482113
3
+ metadata.gz: dd2966cc82225142ba65490ea702ce5a2c43b024
4
+ data.tar.gz: 2ba7b2ae6ff2fcf40d325684b9e44a78ce540ced
5
5
  SHA512:
6
- metadata.gz: 7a60a65bc1673108369a12296c25b6de2327adc7c120444ad5896cdd3e8077f3bc4aa977bd6a6f3d28d2922b2d4928e17dedbfb7c07e038a72d449d8b51da9f9
7
- data.tar.gz: ea87f7e55dc46809b444dd158ab72a523c535a2dce4cadbba04b577f58d7ca9d4191c1923c6bf9f25d0d2a0e521720f9f8c5ef1d0ae7d5fc4c17d3dccab23e31
6
+ metadata.gz: 563565fb0c897400bcd8973a9e38184e63d63a7f9eed3f65a4688864636bbd8a9eae18c34716b5ac92eda6f77e525d52c9614a1a60b3fbe78ed62d03ab097c1a
7
+ data.tar.gz: 92a475a7072ad9ecc0f448daf9d05807da4594fc82e404eb3494582528dfc10a72d634ec37f34d4df246655c4b5adf0745828a607e01c9d991a5f1bc3c875339
@@ -16,6 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.version = Fech::Search::VERSION
17
17
 
18
18
  gem.add_dependency "fech", "~> 1.6.2"
19
+ gem.add_dependency "nokogiri", "1.6.6.2"
19
20
 
20
21
  gem.add_development_dependency "rspec", "~> 2.13.0"
21
22
  end
@@ -1,4 +1,5 @@
1
1
  require 'net/http'
2
+ require 'nokogiri'
2
3
 
3
4
  module Fech
4
5
 
@@ -11,6 +12,7 @@ module Fech
11
12
  def initialize(search_params={})
12
13
  @search_params = validate_params(make_params(search_params))
13
14
  @search_url = 'http://query.nictusa.com/cgi-bin/dcdev/forms/'
15
+ @search_url = 'http://docquery.fec.gov/cgi-bin/forms/'
14
16
  @response = search
15
17
  end
16
18
 
@@ -63,66 +65,21 @@ module Fech
63
65
  # results if called directly, or will yield the results one
64
66
  # by one if a block is passed.
65
67
  def results(&block)
66
- if @search_params['date'] != ''
67
- results_from_date_search(&block)
68
- else
69
- results_from_nondate_search(&block)
70
- end
71
- end
72
-
73
- # Parse the results from a search that does not include a date.
74
- # Will return an array of results if called directly, or will
75
- # yield the results one by one if a block is passed.
76
- def results_from_nondate_search(&block)
68
+ lines = body.split("\n")
69
+ parsing = false
70
+ committee = nil
77
71
  parsed_results = []
78
- regex = /<DT>(.*?)<P/m
79
- match = body.match regex
80
- return [] if match.nil?
81
- content = match[1]
82
- committee_sections = content.split(/<DT>/)
83
- committee_sections.each do |section|
84
- data = parse_committee_section(section)
85
- data.each do |result|
86
- search_result = SearchResult.new(result)
87
-
88
- if block_given?
89
- yield search_result
90
- else
91
- parsed_results << search_result
92
- end
72
+ lines.each do |line|
73
+ if line.match(/^<TABLE style='border:0;'>$/)
74
+ parsing = true
93
75
  end
94
- end
95
- block_given? ? nil : parsed_results
96
- end
97
-
98
- # For results of a search that does not include a date, parse
99
- # the section giving information on the committee that submitted
100
- # the filing.
101
- # @param [String] section
102
- def parse_committee_section(section)
103
- data = []
104
- section.gsub!(/^<BR>/, '')
105
- rows = section.split(/\n/)
106
- committee_data = parse_committee_row(rows.first)
107
- rows[1..-1].each do |row|
108
- data << committee_data.merge(parse_filing_row(row))
109
- end
110
- data
111
- end
112
-
113
- # Parse the results from a search that includes a date.
114
- # Will return an array of results if called directly, or will
115
- # yield the results one by one if a block is passed.
116
- def results_from_date_search(&block)
117
- parsed_results = []
118
- dl = body.match(/<DL>(.*?)<BR><P/m)[0]
119
- rows = dl.split('<DT>')[1..-1].map { |row| row.split("\n") }
120
- rows.each do |committee, *filings|
121
- committee = parse_committee_row(committee)
122
- filings.each do |filing|
123
- next if filing == "<BR><P"
124
- data = committee.merge(parse_filing_row(filing))
125
- search_result = SearchResult.new(data)
76
+ next unless parsing
77
+ if line.match(/<td colspan='8'>/)
78
+ committee = parse_committee_line(line)
79
+ end
80
+ if line.match(/>FEC-\d+</)
81
+ merged = parse_filing_line(line).merge(committee)
82
+ search_result = SearchResult.new(merged)
126
83
  if block_given?
127
84
  yield search_result
128
85
  else
@@ -130,55 +87,21 @@ module Fech
130
87
  end
131
88
  end
132
89
  end
133
- block_given? ? nil : parsed_results
90
+ parsed_results
134
91
  end
135
92
 
136
- # For results of a search that includes a date, parse
137
- # the portion of the results with information on the
138
- # committee that submitted the filing.
139
- # @param [String] row
140
- # @return [Hash] the committee name and ID
141
- def parse_committee_row(row)
142
- regex = /
143
- '>
144
- (.*?)
145
- \s-\s
146
- (C\d{8})
147
- /x
148
- match = row.match regex
149
- {:committee_name => match[1], :committee_id => match[2]}
93
+ # Parse a line that contains committee information
94
+ def parse_committee_line(line)
95
+ match = line.match(/<A.*?>(?<name>.*?) - (?<id>C\d{8})<\/A/)
96
+ {:committee_name => match['name'], :committee_id => match['id']}
150
97
  end
151
98
 
152
- # Parse a result row with information on the filing itself.
153
- # @param [String] row
154
- # @return [Hash] the filing ID, form type, period, date filed, description
155
- # and, optionally, the filing that amended this filing.
156
- def parse_filing_row(row)
157
- regex = /
158
- FEC-(\d+)
159
- \s
160
- Form
161
- \s
162
- (F.*?)
163
- \s\s-\s
164
- (period\s([-\/\d]+),\s)?
165
- filed
166
- \s
167
- ([\/\d]+)
168
- \s
169
- (-\s
170
- (.*?)
171
- ($|<BR>.*?FEC-(\d+))
172
- )?
173
- /x
174
- match = row.match regex
175
- {:filing_id => match[1],
176
- :form_type => match[2],
177
- :period => match[4],
178
- :date_filed => match[5],
179
- :description => match[7],
180
- :amended_by => match[9]
181
- }
99
+ # Parse a line that contains a filing
100
+ def parse_filing_line(line)
101
+ doc = Nokogiri::HTML(line)
102
+ cells = doc.css("td").map(&:text)
103
+ fields = [:form_type, :filing_id, :amended_by, :from, :to, :date_filed, :description]
104
+ Hash[fields.zip(cells)]
182
105
  end
183
106
 
184
107
  end
@@ -11,26 +11,30 @@ module Fech
11
11
 
12
12
  @committee_name = attrs[:committee_name]
13
13
  @committee_id = attrs[:committee_id]
14
- @filing_id = attrs[:filing_id]
14
+ @filing_id = attrs[:filing_id].sub(/FEC-/, '').to_i
15
15
  @form_type = attrs[:form_type]
16
- @period = parse_period(attrs[:period])
16
+ @period = parse_period(attrs[:from], attrs[:to])
17
17
  @date_filed = Date.strptime(attrs[:date_filed], @date_format)
18
18
  @description = attrs[:description]
19
19
  @amended_by = attrs[:amended_by]
20
20
  end
21
21
 
22
- # Parse the string representing a filing period.
22
+ # Parse the strings representing a filing period.
23
23
  # @param [String] period a string representing a filing period
24
24
  # @return [Hash, nil] a hash representing the start and end
25
25
  # of a filing period.
26
- def parse_period(period)
27
- return if period.nil?
28
- from, to = period.split('-')
26
+ def parse_period(from, to)
27
+ return unless valid_date(from.to_s) && valid_date(to.to_s)
29
28
  from = Date.strptime(from, @date_format)
30
29
  to = Date.strptime(to, @date_format)
31
30
  {:from => from, :to => to}
32
31
  end
33
32
 
33
+ # Check whether a date string is valid
34
+ def valid_date(s)
35
+ s.match(/\d\d?\/\d\d?\/\d{4}/)
36
+ end
37
+
34
38
  # The Fech filing object for this search result
35
39
  # @return [Fech::Filing]
36
40
  def filing(opts={})
@@ -1,5 +1,5 @@
1
1
  module Fech
2
2
  class Search
3
- VERSION = "0.0.2"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -15,10 +15,10 @@ describe Fech::SearchResult do
15
15
 
16
16
  it "should have valid dates for period" do
17
17
  from = @committee_result.period[:from]
18
- from.class.should == Date
18
+ expect(from.class).to eq(Date)
19
19
  to = @committee_result.period[:to]
20
- to.class.should == Date
21
- to.should >= from
20
+ expect(to.class).to eq(Date)
21
+ expect(to).to be >= from
22
22
  end
23
23
 
24
24
  end
@@ -26,18 +26,18 @@ describe Fech::SearchResult do
26
26
  context "filing" do
27
27
 
28
28
  it "should make filing accessible" do
29
- @date_result.filing.class.should == Fech::Filing
30
- @committee_result.filing.class.should == Fech::Filing
29
+ expect(@date_result.filing.class).to eq(Fech::Filing)
30
+ expect(@committee_result.filing.class).to eq(Fech::Filing)
31
31
  end
32
32
 
33
33
  it "should create filing object for correct filing" do
34
34
  filing = @committee_result.filing
35
- filing.filing_id.should == @committee_result.filing_id
35
+ expect(filing.filing_id).to eq(@committee_result.filing_id)
36
36
  end
37
37
 
38
38
  it "should pass arguments to Fech::Filing#new" do
39
39
  filing = @date_result.filing(:download_dir => "/tmp")
40
- filing.download_dir.should == "/tmp"
40
+ expect(filing.download_dir).to eq("/tmp")
41
41
  end
42
42
 
43
43
  end
@@ -17,11 +17,11 @@ describe Fech::Search do
17
17
  end
18
18
 
19
19
  it "should not raise an error if :committee_id is given by itself" do
20
- expect { Fech::Search.new(:committee_id => "C00431171") }.to_not raise_error(ArgumentError)
20
+ expect { Fech::Search.new(:committee_id => "C00431171") }.to_not raise_error
21
21
  end
22
22
 
23
23
  it "should not raise an error if :form_type is given with another parameter" do
24
- expect { Fech::Search.new(:form_type => "F3", :date => Date.new(2013, 5, 29)) }.to_not raise_error(ArgumentError)
24
+ expect { Fech::Search.new(:form_type => "F3", :date => Date.new(2013, 5, 29)) }.to_not raise_error
25
25
  end
26
26
 
27
27
  end
@@ -30,20 +30,20 @@ describe Fech::Search do
30
30
 
31
31
  it "should return an array of results from committee search" do
32
32
  search = Fech::Search.new(:committee_id => "C00431171")
33
- search.results.class.should == Array
34
- search.results[0].class.should == Fech::SearchResult
33
+ expect(search.results.class).to eq(Array)
34
+ expect(search.results[0].class).to eq(Fech::SearchResult)
35
35
  end
36
36
 
37
37
  it "should return an array of results from date search" do
38
38
  search = Fech::Search.new(:date => Date.new(2013, 5, 29))
39
- search.results.class.should == Array
40
- search.results[0].class.should == Fech::SearchResult
39
+ expect(search.results.class).to eq(Array)
40
+ expect(search.results[0].class).to eq(Fech::SearchResult)
41
41
  end
42
42
 
43
43
  it "should return an array of results from date and report_type search" do
44
44
  search = Fech::Search.new(:date => Date.new(2013, 5, 29), :report_type => "M4")
45
- search.results.class.should == Array
46
- search.results[0].class.should == Fech::SearchResult
45
+ expect(search.results.class).to eq(Array)
46
+ expect(search.results[0].class).to eq(Fech::SearchResult)
47
47
  end
48
48
 
49
49
  end
metadata CHANGED
@@ -1,41 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fech-search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Bycoffe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-22 00:00:00.000000000 Z
11
+ date: 2015-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fech
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.6.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.6.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.6.6.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.6.6.2
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - ~>
45
+ - - "~>"
32
46
  - !ruby/object:Gem::Version
33
47
  version: 2.13.0
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - ~>
52
+ - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: 2.13.0
41
55
  description: A Fech plugin for searching electronic FEC filings
@@ -45,7 +59,7 @@ executables: []
45
59
  extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
48
- - .gitignore
62
+ - ".gitignore"
49
63
  - Gemfile
50
64
  - Gemfile.lock
51
65
  - LICENSE
@@ -67,17 +81,17 @@ require_paths:
67
81
  - lib
68
82
  required_ruby_version: !ruby/object:Gem::Requirement
69
83
  requirements:
70
- - - ! '>='
84
+ - - ">="
71
85
  - !ruby/object:Gem::Version
72
86
  version: '0'
73
87
  required_rubygems_version: !ruby/object:Gem::Requirement
74
88
  requirements:
75
- - - ! '>='
89
+ - - ">="
76
90
  - !ruby/object:Gem::Version
77
91
  version: '0'
78
92
  requirements: []
79
93
  rubyforge_project:
80
- rubygems_version: 2.0.3
94
+ rubygems_version: 2.2.2
81
95
  signing_key:
82
96
  specification_version: 4
83
97
  summary: Fech-Search provides an interface for searching for electronic filings submitted
@@ -85,4 +99,3 @@ summary: Fech-Search provides an interface for searching for electronic filings
85
99
  test_files:
86
100
  - spec/search_result_spec.rb
87
101
  - spec/search_spec.rb
88
- has_rdoc: