portal_scraper 2.0.1 → 2.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f511d4ae5d6568df6bc6960907a0964ecfb6c8f0c8d5850b5ad757a0ed35039
4
- data.tar.gz: 5edb4fdbd33676d7b03623a86815b0b865fd214d85e4cd6e34e7fe42fa67204b
3
+ metadata.gz: 0be4e772a2a12824b3b8758f9914f89fa1403100749ba81b4f6a73e036c21064
4
+ data.tar.gz: b1cd8df8f5e4427b53c2e86a498f9bb141175d8cd844e3b9df64125ce4e8cdc2
5
5
  SHA512:
6
- metadata.gz: 5df684726b58e1d8da72af7abd8b0395d36bc403f8d045ef0abbf628a8eee0aeebaa13f13ecbc9e80b9ff1dd088695eec92470dac707d5e5977dab1961196234
7
- data.tar.gz: d93c42d08e8f39ddacf8828060e91324f0ad1b42f1f131b381d43ba693bbba8d05c3d82e1c669736fc153d087b9f648ba1af8fab7936be25c70ee10d811c2708
6
+ metadata.gz: 9c1f8dca1fb37272f1f67da43b050d594b4ebb79d2ad377ca18bbae72909dd78095a15e634006197bc150e4720c9b78e2ee4ebb00799145c2de706daf0be0775
7
+ data.tar.gz: ddce7d5af7db47a15fdbc4b0abe118e3636f218497cb61ca7e3ba3197e3b539a2916661b4de84c5d6880b1a646e83b97d4635a43973f254df79bd194085a89d9
@@ -9,6 +9,7 @@ module PortalScraper
9
9
  attr_accessor :app_id, :secret
10
10
 
11
11
  CODE_TO_COUNTRY_MAPPING = JSON.parse(File.read(File.join(File.dirname(__FILE__), 'code_to_country.json')))
12
+ IS_POSTAL_CODE_DOM = JSON.parse(File.read(File.join(File.dirname(__FILE__), 'is_postal_code_dom.json')))
12
13
  MINIMUM_AMOUNT = 10
13
14
 
14
15
  def initialize(app_id = nil, secret = nil)
@@ -24,26 +25,36 @@ module PortalScraper
24
25
  user_page = app.post(url_for('/appRecherche.do'), { nom: '', prenom: '', chercher: 'Chercher' })
25
26
  loop do
26
27
  user_page.links_with(href: /appTiersDetail.do/).each do |link|
27
- account = link.click
28
- selected_row = nil
29
- selected_row_date = nil
30
-
31
- account.links_with(css: 'table#contrat td a').each do |row|
32
- row_date = parse_date(row.node.ancestors('tr').at('td[2]'))&.to_date
33
- if selected_row_date.nil? || selected_row_date < row_date
34
- selected_row_date = row_date
35
- selected_row = row
36
- end
28
+ account = link.click
29
+ selected_link = nil
30
+ opened_on, balance = nil, 0.to_d
31
+
32
+ account.links_with(css: 'table#contrat td a').each do |account_link|
33
+ row = account_link.node.ancestors('tr')
34
+ next unless row.at('td[1]').text.strip == 'Compte épargne rémunéré'
35
+
36
+ row_date = parse_date(row.at('td[2]'))
37
+ next unless opened_on.nil? || opened_on < row_date
38
+
39
+ selected_link = account_link
40
+ opened_on = row_date
41
+ balance = parse_number(row.at('td[5]'))
37
42
  end
38
43
 
39
- transfers = scrap_transfers(selected_row)
40
- balance = selected_row&.node&.ancestors('tr')&.at('td[4]')
41
- accounts_data[:accounts] << {
42
- client_ref: find_table_value(account, 'Identifiant tiers'),
43
- balance: balance.nil? ? "0".to_d : parse_number(balance),
44
- opened_on: selected_row_date.nil? ? parse_dates(account.search('table#contrat td'))&.max : selected_row_date.to_s,
45
- transfers: transfers,
44
+ next unless selected_link
45
+
46
+ transfers = scrap_transfers(selected_link)
47
+ account_data = {
48
+ client_ref: find_table_value(account, 'Identifiant tiers'),
49
+ balance: balance,
50
+ opened_on: opened_on,
51
+ transfers: transfers,
46
52
  }
53
+ if block_given?
54
+ yield(account_data)
55
+ else
56
+ accounts_data[:accounts] << account_data
57
+ end
47
58
  end
48
59
 
49
60
  break unless user_page.search('.pg_next').present?
@@ -63,7 +74,7 @@ module PortalScraper
63
74
  form['commune'] = user[:codeInsee]
64
75
  form['libCommune'] = user[:ville]
65
76
  else
66
- fill_commune(app, form, user[:codePostal], parse_city_name(user[:ville]), user[:pays] || user[:libNation])
77
+ fill_commune(app, form, user[:codePostal], parse_city_name(user[:ville]))
67
78
  end
68
79
  fill_address(form, user[:numeroVoie])
69
80
  fill_birth_place(form, user[:paysNaissance])
@@ -80,6 +91,8 @@ module PortalScraper
80
91
  end
81
92
  end
82
93
  nil
94
+ rescue => e
95
+ { error: e.message }
83
96
  end
84
97
 
85
98
  def create_proposition(client_ref)
@@ -143,14 +156,15 @@ module PortalScraper
143
156
  end
144
157
  end
145
158
 
146
- def fill_commune(app, form, postal_code, city, country_code)
159
+ def fill_commune(app, form, postal_code, city)
147
160
  app.post(url_for('/tiersCommunes.do'), { codPos: postal_code }).tap do |mappings|
148
- cities = mappings.search('td.t').map { |c| { code: c.parent.search('a.PL_LST').text.strip, name: c.text.strip } }
149
- matched_city = cities.find(-> { cities.first }) { |c| c[:name].include?(city) }
161
+ cities = mappings.search('td.t').map { |c| { code: c.parent.search('a.PL_LST').text.strip, name: c.text.strip } }
162
+ matched_city = cities.find(-> { cities.first }) { |c| c[:name].include?(city) }
163
+ raise "City '#{city}' and postcode '#{postal_code}' not found" unless matched_city
150
164
  form['commune'] = matched_city[:code]
151
165
  form['libCommune'] = matched_city[:name]
152
166
  end
153
- form['territoireRes'] = CODE_TO_COUNTRY_MAPPING.dig(country_code, 'category')
167
+ form['territoireRes'] = IS_POSTAL_CODE_DOM.dig(postal_code[0..2], 'category') || 0
154
168
  end
155
169
 
156
170
  def fill_address(form, address)
@@ -175,21 +189,17 @@ module PortalScraper
175
189
  PortalScraper.config
176
190
  end
177
191
 
178
- def scrap_transfers(selected_row)
179
- transfers = []
180
- transfers_page = selected_row&.click
181
- if transfers_page
182
- transfers_page.search('table#operation tbody tr').each do |row|
183
- transfers << {
184
- operation_date: parse_date(row.search('td[1]')),
185
- nature: row.search('td[2]').text.strip.gsub(/[\n,\t,'']/, ''),
186
- value_date: parse_date(row.search('td[3]')),
187
- debit: parse_number(row.search('td[4]')),
188
- credit: parse_number(row.search('td[5]')),
189
- }
190
- end
192
+ def scrap_transfers(account_link)
193
+ transfers_page = account_link.click
194
+ transfers_page.search('table#operation tbody tr').map do |transfer_row|
195
+ {
196
+ operation_date: parse_date(transfer_row.search('td[1]')),
197
+ nature: transfer_row.search('td[2]').text.strip.gsub(/[\n,\t,'']/, ''),
198
+ value_date: parse_date(transfer_row.search('td[3]')),
199
+ debit: parse_number(transfer_row.search('td[4]')),
200
+ credit: parse_number(transfer_row.search('td[5]')),
201
+ }
191
202
  end
192
- transfers
193
203
  end
194
204
  end
195
205
  end
@@ -0,0 +1 @@
1
+ {"971":{"name":"GUADELOUPE","category":1},"972":{"name":"MARTINIQUE","category":1},"973":{"name":"GUYANE FRANCAISE","category":1},"974":{"name":"REUNION","category":1}}
@@ -13,7 +13,7 @@ module PortalScraper
13
13
  end
14
14
 
15
15
  def parse_dates(node)
16
- node.text.strip.gsub(%r(\d{2}/\d{2}/\d{4}))
16
+ node.text.strip.gsub(%r(\d{2}/\d{2}/\d{4})).map { |d| Date.strptime(d, '%d/%m/%Y') }
17
17
  end
18
18
  end
19
19
  end
@@ -1,7 +1,7 @@
1
1
  module PortalScraper
2
2
  class Version
3
3
  MAJOR = 2
4
- MINOR = 0
4
+ MINOR = 2
5
5
  PATCH = 1
6
6
 
7
7
  def self.to_s
@@ -23,11 +23,11 @@ Gem::Specification.new do |spec|
23
23
  spec.required_ruby_version = '>= 2.5.3'
24
24
 
25
25
  spec.add_dependency 'mechanize', '~> 2.7'
26
- spec.add_dependency 'activesupport', '~> 5.2'
26
+ spec.add_dependency 'activesupport', '>= 5.2', '< 7.0'
27
27
 
28
28
  spec.add_development_dependency 'rspec', '~> 3.2'
29
29
  spec.add_development_dependency 'bundler', '~> 1.16'
30
- spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
31
31
  spec.add_development_dependency 'vcr'
32
32
  spec.add_development_dependency 'webmock'
33
33
  spec.add_development_dependency 'rubocop', '~> 0.67.2'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: portal_scraper
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Armand Mégrot
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-01-06 00:00:00.000000000 Z
12
+ date: 2020-05-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mechanize
@@ -29,16 +29,22 @@ dependencies:
29
29
  name: activesupport
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '5.2'
35
+ - - "<"
36
+ - !ruby/object:Gem::Version
37
+ version: '7.0'
35
38
  type: :runtime
36
39
  prerelease: false
37
40
  version_requirements: !ruby/object:Gem::Requirement
38
41
  requirements:
39
- - - "~>"
42
+ - - ">="
40
43
  - !ruby/object:Gem::Version
41
44
  version: '5.2'
45
+ - - "<"
46
+ - !ruby/object:Gem::Version
47
+ version: '7.0'
42
48
  - !ruby/object:Gem::Dependency
43
49
  name: rspec
44
50
  requirement: !ruby/object:Gem::Requirement
@@ -73,14 +79,14 @@ dependencies:
73
79
  requirements:
74
80
  - - "~>"
75
81
  - !ruby/object:Gem::Version
76
- version: '10.0'
82
+ version: '13.0'
77
83
  type: :development
78
84
  prerelease: false
79
85
  version_requirements: !ruby/object:Gem::Requirement
80
86
  requirements:
81
87
  - - "~>"
82
88
  - !ruby/object:Gem::Version
83
- version: '10.0'
89
+ version: '13.0'
84
90
  - !ruby/object:Gem::Dependency
85
91
  name: vcr
86
92
  requirement: !ruby/object:Gem::Requirement
@@ -148,6 +154,7 @@ files:
148
154
  - lib/portal_scraper.rb
149
155
  - lib/portal_scraper/accounts/client.rb
150
156
  - lib/portal_scraper/accounts/code_to_country.json
157
+ - lib/portal_scraper/accounts/is_postal_code_dom.json
151
158
  - lib/portal_scraper/bad_login_url.rb
152
159
  - lib/portal_scraper/bad_root_url.rb
153
160
  - lib/portal_scraper/parsing_helper.rb