fech-search 0.0.2 → 0.1.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 +4 -4
- data/fech-search.gemspec +1 -0
- data/lib/fech-search/search.rb +26 -103
- data/lib/fech-search/search_result.rb +10 -6
- data/lib/fech-search/version.rb +1 -1
- data/spec/search_result_spec.rb +7 -7
- data/spec/search_spec.rb +8 -8
- metadata +24 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd2966cc82225142ba65490ea702ce5a2c43b024
|
4
|
+
data.tar.gz: 2ba7b2ae6ff2fcf40d325684b9e44a78ce540ced
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 563565fb0c897400bcd8973a9e38184e63d63a7f9eed3f65a4688864636bbd8a9eae18c34716b5ac92eda6f77e525d52c9614a1a60b3fbe78ed62d03ab097c1a
|
7
|
+
data.tar.gz: 92a475a7072ad9ecc0f448daf9d05807da4594fc82e404eb3494582528dfc10a72d634ec37f34d4df246655c4b5adf0745828a607e01c9d991a5f1bc3c875339
|
data/fech-search.gemspec
CHANGED
data/lib/fech-search/search.rb
CHANGED
@@ -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
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
-
|
90
|
+
parsed_results
|
134
91
|
end
|
135
92
|
|
136
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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[:
|
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
|
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(
|
27
|
-
return
|
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={})
|
data/lib/fech-search/version.rb
CHANGED
data/spec/search_result_spec.rb
CHANGED
@@ -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.
|
18
|
+
expect(from.class).to eq(Date)
|
19
19
|
to = @committee_result.period[:to]
|
20
|
-
to.class.
|
21
|
-
to.
|
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.
|
30
|
-
@committee_result.filing.class.
|
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.
|
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.
|
40
|
+
expect(filing.download_dir).to eq("/tmp")
|
41
41
|
end
|
42
42
|
|
43
43
|
end
|
data/spec/search_spec.rb
CHANGED
@@ -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
|
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
|
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.
|
34
|
-
search.results[0].class.
|
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.
|
40
|
-
search.results[0].class.
|
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.
|
46
|
-
search.results[0].class.
|
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
|
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:
|
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.
|
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:
|