kimurai 1.4.0 → 2.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -0
  3. data/CHANGELOG.md +21 -0
  4. data/Gemfile +2 -2
  5. data/README.md +476 -648
  6. data/Rakefile +6 -6
  7. data/bin/console +3 -4
  8. data/exe/kimurai +0 -1
  9. data/kimurai.gemspec +38 -37
  10. data/lib/kimurai/base/saver.rb +15 -19
  11. data/lib/kimurai/base/storage.rb +1 -1
  12. data/lib/kimurai/base.rb +38 -38
  13. data/lib/kimurai/base_helper.rb +5 -4
  14. data/lib/kimurai/browser_builder/mechanize_builder.rb +121 -119
  15. data/lib/kimurai/browser_builder/selenium_chrome_builder.rb +160 -152
  16. data/lib/kimurai/browser_builder/selenium_firefox_builder.rb +162 -160
  17. data/lib/kimurai/browser_builder.rb +1 -7
  18. data/lib/kimurai/capybara_configuration.rb +1 -1
  19. data/lib/kimurai/capybara_ext/driver/base.rb +50 -46
  20. data/lib/kimurai/capybara_ext/mechanize/driver.rb +51 -50
  21. data/lib/kimurai/capybara_ext/selenium/driver.rb +33 -29
  22. data/lib/kimurai/capybara_ext/session.rb +31 -38
  23. data/lib/kimurai/cli/generator.rb +15 -15
  24. data/lib/kimurai/cli.rb +49 -86
  25. data/lib/kimurai/core_ext/array.rb +2 -2
  26. data/lib/kimurai/core_ext/hash.rb +1 -1
  27. data/lib/kimurai/core_ext/numeric.rb +4 -4
  28. data/lib/kimurai/pipeline.rb +2 -1
  29. data/lib/kimurai/runner.rb +6 -6
  30. data/lib/kimurai/template/Gemfile +2 -2
  31. data/lib/kimurai/template/config/boot.rb +4 -4
  32. data/lib/kimurai/template/config/schedule.rb +15 -15
  33. data/lib/kimurai/template/spiders/application_spider.rb +8 -14
  34. data/lib/kimurai/version.rb +1 -1
  35. data/lib/kimurai.rb +7 -3
  36. metadata +58 -65
  37. data/.travis.yml +0 -5
  38. data/lib/kimurai/automation/deploy.yml +0 -54
  39. data/lib/kimurai/automation/setup/chromium_chromedriver.yml +0 -26
  40. data/lib/kimurai/automation/setup/firefox_geckodriver.yml +0 -20
  41. data/lib/kimurai/automation/setup/phantomjs.yml +0 -33
  42. data/lib/kimurai/automation/setup/ruby_environment.yml +0 -124
  43. data/lib/kimurai/automation/setup.yml +0 -44
  44. data/lib/kimurai/browser_builder/poltergeist_phantomjs_builder.rb +0 -175
  45. data/lib/kimurai/capybara_ext/poltergeist/driver.rb +0 -13
  46. data/lib/kimurai/cli/ansible_command_builder.rb +0 -71
  47. data/lib/kimurai/template/config/automation.yml +0 -13
@@ -4,201 +4,203 @@ require_relative '../capybara_configuration'
4
4
  require_relative '../capybara_ext/selenium/driver'
5
5
  require_relative '../capybara_ext/session'
6
6
 
7
- module Kimurai::BrowserBuilder
8
- class SeleniumFirefoxBuilder
9
- class << self
10
- attr_accessor :virtual_display
11
- end
7
+ module Kimurai
8
+ module BrowserBuilder
9
+ class SeleniumFirefoxBuilder
10
+ class << self
11
+ attr_accessor :virtual_display
12
+ end
12
13
 
13
- attr_reader :logger, :spider
14
+ attr_reader :logger, :spider
14
15
 
15
- def initialize(config, spider:)
16
- @config = config
17
- @spider = spider
18
- @logger = spider.logger
19
- end
16
+ def initialize(config, spider:)
17
+ @config = config
18
+ @spider = spider
19
+ @logger = spider.logger
20
+ end
20
21
 
21
- def build
22
- # Register driver
23
- Capybara.register_driver :selenium_firefox do |app|
24
- # Create driver options
25
- driver_options = Selenium::WebDriver::Firefox::Options.new
26
- driver_options.profile = Selenium::WebDriver::Firefox::Profile.new
27
- driver_options.profile["browser.link.open_newwindow"] = 3 # open windows in tabs
28
- driver_options.profile["media.peerconnection.enabled"] = false # disable web rtc
29
-
30
- # Proxy
31
- if proxy = @config[:proxy].presence
32
- proxy_string = (proxy.class == Proc ? proxy.call : proxy).strip
33
- ip, port, type, user, password = proxy_string.split(":")
34
-
35
- if user.nil? && password.nil?
36
- driver_options.profile["network.proxy.type"] = 1
37
- if type == "http"
38
- driver_options.profile["network.proxy.http"] = ip
39
- driver_options.profile["network.proxy.http_port"] = port.to_i
40
- driver_options.profile["network.proxy.ssl"] = ip
41
- driver_options.profile["network.proxy.ssl_port"] = port.to_i
42
-
43
- logger.debug "BrowserBuilder (selenium_firefox): enabled http proxy, ip: #{ip}, port: #{port}"
44
- elsif type == "socks5"
45
- driver_options.profile["network.proxy.socks"] = ip
46
- driver_options.profile["network.proxy.socks_port"] = port.to_i
47
- driver_options.profile["network.proxy.socks_version"] = 5
48
- driver_options.profile["network.proxy.socks_remote_dns"] = true
49
-
50
- logger.debug "BrowserBuilder (selenium_firefox): enabled socks5 proxy, ip: #{ip}, port: #{port}"
22
+ def build
23
+ # Register driver
24
+ Capybara.register_driver :selenium_firefox do |app|
25
+ # Create driver options
26
+ driver_options = Selenium::WebDriver::Firefox::Options.new
27
+ driver_options.profile = Selenium::WebDriver::Firefox::Profile.new
28
+ driver_options.profile['browser.link.open_newwindow'] = 3 # open windows in tabs
29
+ driver_options.profile['media.peerconnection.enabled'] = false # disable web rtc
30
+
31
+ # Proxy
32
+ if (proxy = @config[:proxy].presence)
33
+ proxy_string = (proxy.instance_of?(Proc) ? proxy.call : proxy).strip
34
+ ip, port, type, user, password = proxy_string.split(':')
35
+
36
+ if user.nil? && password.nil?
37
+ driver_options.profile['network.proxy.type'] = 1
38
+ if type == 'http'
39
+ driver_options.profile['network.proxy.http'] = ip
40
+ driver_options.profile['network.proxy.http_port'] = port.to_i
41
+ driver_options.profile['network.proxy.ssl'] = ip
42
+ driver_options.profile['network.proxy.ssl_port'] = port.to_i
43
+
44
+ logger.debug "BrowserBuilder (selenium_firefox): enabled http proxy, ip: #{ip}, port: #{port}"
45
+ elsif type == 'socks5'
46
+ driver_options.profile['network.proxy.socks'] = ip
47
+ driver_options.profile['network.proxy.socks_port'] = port.to_i
48
+ driver_options.profile['network.proxy.socks_version'] = 5
49
+ driver_options.profile['network.proxy.socks_remote_dns'] = true
50
+
51
+ logger.debug "BrowserBuilder (selenium_firefox): enabled socks5 proxy, ip: #{ip}, port: #{port}"
52
+ else
53
+ logger.error "BrowserBuilder (selenium_firefox): wrong type of proxy: #{type}, skipped"
54
+ end
51
55
  else
52
- logger.error "BrowserBuilder (selenium_firefox): wrong type of proxy: #{type}, skipped"
56
+ logger.error "BrowserBuilder (selenium_firefox): proxy with authentication doesn't supported by selenium, skipped"
53
57
  end
54
- else
55
- logger.error "BrowserBuilder (selenium_firefox): proxy with authentication doesn't supported by selenium, skipped"
56
58
  end
57
- end
58
59
 
59
- if proxy_bypass_list = @config[:proxy_bypass_list].presence
60
- if proxy
61
- driver_options.profile["network.proxy.no_proxies_on"] = proxy_bypass_list.join(", ")
62
- logger.debug "BrowserBuilder (selenium_firefox): enabled proxy_bypass_list"
63
- else
64
- logger.error "BrowserBuilder (selenium_firefox): provide `proxy` to set proxy_bypass_list, skipped"
60
+ if (proxy_bypass_list = @config[:proxy_bypass_list].presence)
61
+ if proxy
62
+ driver_options.profile['network.proxy.no_proxies_on'] = proxy_bypass_list.join(', ')
63
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled proxy_bypass_list'
64
+ else
65
+ logger.error 'BrowserBuilder (selenium_firefox): provide `proxy` to set proxy_bypass_list, skipped'
66
+ end
65
67
  end
66
- end
67
68
 
68
- # SSL
69
- if @config[:ignore_ssl_errors].present?
70
- driver_options.profile.secure_ssl = false
71
- driver_options.profile.assume_untrusted_certificate_issuer = true
72
- logger.debug "BrowserBuilder (selenium_firefox): enabled ignore_ssl_errors"
73
- end
69
+ # SSL
70
+ if @config[:ignore_ssl_errors].present?
71
+ driver_options.profile.secure_ssl = false
72
+ driver_options.profile.assume_untrusted_certificate_issuer = true
73
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled ignore_ssl_errors'
74
+ end
74
75
 
75
- # Disable images
76
- if @config[:disable_images].present?
77
- driver_options.profile["permissions.default.image"] = 2
78
- logger.debug "BrowserBuilder (selenium_firefox): enabled disable_images"
79
- end
76
+ # Disable images
77
+ if @config[:disable_images].present?
78
+ driver_options.profile['permissions.default.image'] = 2
79
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled disable_images'
80
+ end
80
81
 
81
- # Headers
82
- if @config[:headers].present?
83
- logger.warn "BrowserBuilder: (selenium_firefox): custom headers doesn't supported by selenium, skipped"
84
- end
82
+ # Headers
83
+ if @config[:headers].present?
84
+ logger.warn "BrowserBuilder: (selenium_firefox): custom headers doesn't supported by selenium, skipped"
85
+ end
85
86
 
86
- if user_agent = @config[:user_agent].presence
87
- user_agent_string = (user_agent.class == Proc ? user_agent.call : user_agent).strip
88
- driver_options.profile["general.useragent.override"] = user_agent_string
89
- logger.debug "BrowserBuilder (selenium_firefox): enabled custom user_agent"
90
- end
87
+ if (user_agent = @config[:user_agent].presence)
88
+ user_agent_string = (user_agent.instance_of?(Proc) ? user_agent.call : user_agent).strip
89
+ driver_options.profile['general.useragent.override'] = user_agent_string
90
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled custom user_agent'
91
+ end
91
92
 
92
- # Headless mode
93
- if ENV["HEADLESS"] != "false"
94
- if @config[:headless_mode] == :virtual_display
95
- if Gem::Platform.local.os == "linux"
96
- unless self.class.virtual_display
97
- require 'headless'
98
- self.class.virtual_display = Headless.new(reuse: true, destroy_at_exit: false)
99
- self.class.virtual_display.start
93
+ # Headless mode
94
+ if ENV['HEADLESS'] != 'false'
95
+ if @config[:headless_mode] == :virtual_display
96
+ if Gem::Platform.local.os == 'linux'
97
+ unless self.class.virtual_display
98
+ require 'headless'
99
+ self.class.virtual_display = Headless.new(reuse: true, destroy_at_exit: false)
100
+ self.class.virtual_display.start
101
+ end
102
+
103
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled virtual_display headless_mode'
104
+ else
105
+ logger.error 'BrowserBuilder (selenium_firefox): virtual_display headless_mode works only ' \
106
+ 'on Linux platform. Browser will run in normal mode. Set `native` mode instead.'
100
107
  end
101
-
102
- logger.debug "BrowserBuilder (selenium_firefox): enabled virtual_display headless_mode"
103
108
  else
104
- logger.error "BrowserBuilder (selenium_firefox): virtual_display headless_mode works only " \
105
- "on Linux platform. Browser will run in normal mode. Set `native` mode instead."
109
+ driver_options.args << '--headless'
110
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled native headless_mode'
106
111
  end
107
- else
108
- driver_options.args << "--headless"
109
- logger.debug "BrowserBuilder (selenium_firefox): enabled native headless_mode"
110
112
  end
113
+
114
+ Capybara::Selenium::Driver.new(app, browser: :firefox, options: driver_options)
111
115
  end
112
116
 
113
- Capybara::Selenium::Driver.new(app, browser: :firefox, options: driver_options)
114
- end
117
+ # Create browser instance (Capybara session)
118
+ @browser = Capybara::Session.new(:selenium_firefox)
119
+ @browser.spider = spider
120
+ logger.debug 'BrowserBuilder (selenium_firefox): created browser instance'
115
121
 
116
- # Create browser instance (Capybara session)
117
- @browser = Capybara::Session.new(:selenium_firefox)
118
- @browser.spider = spider
119
- logger.debug "BrowserBuilder (selenium_firefox): created browser instance"
122
+ if @config[:extensions].present?
123
+ logger.error 'BrowserBuilder (selenium_firefox): `extensions` option not supported by Selenium, skipped'
124
+ end
120
125
 
121
- if @config[:extensions].present?
122
- logger.error "BrowserBuilder (selenium_firefox): `extensions` option not supported by Selenium, skipped"
123
- end
126
+ # Window size
127
+ if (size = @config[:window_size].presence)
128
+ @browser.current_window.resize_to(*size)
129
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled window_size'
130
+ end
124
131
 
125
- # Window size
126
- if size = @config[:window_size].presence
127
- @browser.current_window.resize_to(*size)
128
- logger.debug "BrowserBuilder (selenium_firefox): enabled window_size"
129
- end
132
+ # Cookies
133
+ if (cookies = @config[:cookies].presence)
134
+ @browser.config.cookies = cookies
135
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled custom cookies'
136
+ end
130
137
 
131
- # Cookies
132
- if cookies = @config[:cookies].presence
133
- @browser.config.cookies = cookies
134
- logger.debug "BrowserBuilder (selenium_firefox): enabled custom cookies"
135
- end
138
+ # Browser instance options
139
+ # skip_request_errors
140
+ if (skip_errors = @config[:skip_request_errors].presence)
141
+ @browser.config.skip_request_errors = skip_errors
142
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled skip_request_errors'
143
+ end
136
144
 
137
- # Browser instance options
138
- # skip_request_errors
139
- if skip_errors = @config[:skip_request_errors].presence
140
- @browser.config.skip_request_errors = skip_errors
141
- logger.debug "BrowserBuilder (selenium_firefox): enabled skip_request_errors"
142
- end
145
+ # retry_request_errors
146
+ if (retry_errors = @config[:retry_request_errors].presence)
147
+ @browser.config.retry_request_errors = retry_errors
148
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled retry_request_errors'
149
+ end
143
150
 
144
- # retry_request_errors
145
- if retry_errors = @config[:retry_request_errors].presence
146
- @browser.config.retry_request_errors = retry_errors
147
- logger.debug "BrowserBuilder (selenium_firefox): enabled retry_request_errors"
148
- end
151
+ # restart_if
152
+ if (requests_limit = @config.dig(:restart_if, :requests_limit).presence)
153
+ @browser.config.restart_if[:requests_limit] = requests_limit
154
+ logger.debug "BrowserBuilder (selenium_firefox): enabled restart_if.requests_limit >= #{requests_limit}"
155
+ end
149
156
 
150
- # restart_if
151
- if requests_limit = @config.dig(:restart_if, :requests_limit).presence
152
- @browser.config.restart_if[:requests_limit] = requests_limit
153
- logger.debug "BrowserBuilder (selenium_firefox): enabled restart_if.requests_limit >= #{requests_limit}"
154
- end
157
+ if (memory_limit = @config.dig(:restart_if, :memory_limit).presence)
158
+ @browser.config.restart_if[:memory_limit] = memory_limit
159
+ logger.debug "BrowserBuilder (selenium_firefox): enabled restart_if.memory_limit >= #{memory_limit}"
160
+ end
155
161
 
156
- if memory_limit = @config.dig(:restart_if, :memory_limit).presence
157
- @browser.config.restart_if[:memory_limit] = memory_limit
158
- logger.debug "BrowserBuilder (selenium_firefox): enabled restart_if.memory_limit >= #{memory_limit}"
159
- end
162
+ # before_request clear_cookies
163
+ if @config.dig(:before_request, :clear_cookies)
164
+ @browser.config.before_request[:clear_cookies] = true
165
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled before_request.clear_cookies'
166
+ end
160
167
 
161
- # before_request clear_cookies
162
- if @config.dig(:before_request, :clear_cookies)
163
- @browser.config.before_request[:clear_cookies] = true
164
- logger.debug "BrowserBuilder (selenium_firefox): enabled before_request.clear_cookies"
165
- end
168
+ # before_request clear_and_set_cookies
169
+ if @config.dig(:before_request, :clear_and_set_cookies)
170
+ if (cookies = @config[:cookies].presence)
171
+ @browser.config.cookies = cookies
172
+ @browser.config.before_request[:clear_and_set_cookies] = true
173
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled before_request.clear_and_set_cookies'
174
+ else
175
+ logger.error 'BrowserBuilder (selenium_firefox): cookies should be present to enable before_request.clear_and_set_cookies, skipped'
176
+ end
177
+ end
166
178
 
167
- # before_request clear_and_set_cookies
168
- if @config.dig(:before_request, :clear_and_set_cookies)
169
- if cookies = @config[:cookies].presence
170
- @browser.config.cookies = cookies
171
- @browser.config.before_request[:clear_and_set_cookies] = true
172
- logger.debug "BrowserBuilder (selenium_firefox): enabled before_request.clear_and_set_cookies"
173
- else
174
- logger.error "BrowserBuilder (selenium_firefox): cookies should be present to enable before_request.clear_and_set_cookies, skipped"
179
+ # before_request change_user_agent
180
+ if @config.dig(:before_request, :change_user_agent)
181
+ logger.error 'BrowserBuilder (selenium_firefox): before_request.change_user_agent option not supported by Selenium, skipped'
175
182
  end
176
- end
177
183
 
178
- # before_request change_user_agent
179
- if @config.dig(:before_request, :change_user_agent)
180
- logger.error "BrowserBuilder (selenium_firefox): before_request.change_user_agent option not supported by Selenium, skipped"
181
- end
184
+ # before_request change_proxy
185
+ if @config.dig(:before_request, :change_proxy)
186
+ logger.error 'BrowserBuilder (selenium_firefox): before_request.change_proxy option not supported by Selenium, skipped'
187
+ end
182
188
 
183
- # before_request change_proxy
184
- if @config.dig(:before_request, :change_proxy)
185
- logger.error "BrowserBuilder (selenium_firefox): before_request.change_proxy option not supported by Selenium, skipped"
186
- end
189
+ # before_request delay
190
+ if (delay = @config.dig(:before_request, :delay).presence)
191
+ @browser.config.before_request[:delay] = delay
192
+ logger.debug 'BrowserBuilder (selenium_firefox): enabled before_request.delay'
193
+ end
187
194
 
188
- # before_request delay
189
- if delay = @config.dig(:before_request, :delay).presence
190
- @browser.config.before_request[:delay] = delay
191
- logger.debug "BrowserBuilder (selenium_firefox): enabled before_request.delay"
192
- end
195
+ # encoding
196
+ if (encoding = @config[:encoding])
197
+ @browser.config.encoding = encoding
198
+ logger.debug "BrowserBuilder (selenium_firefox): enabled encoding: #{encoding}"
199
+ end
193
200
 
194
- # encoding
195
- if encoding = @config[:encoding]
196
- @browser.config.encoding = encoding
197
- logger.debug "BrowserBuilder (selenium_firefox): enabled encoding: #{encoding}"
201
+ # return Capybara session instance
202
+ @browser
198
203
  end
199
-
200
- # return Capybara session instance
201
- @browser
202
204
  end
203
205
  end
204
206
  end
@@ -1,15 +1,9 @@
1
1
  module Kimurai
2
2
  module BrowserBuilder
3
3
  def self.build(engine, config = {}, spider:)
4
- if config[:browser].present?
5
- raise "++++++ BrowserBuilder: browser option is depricated. Now all sub-options inside " \
6
- "`browser` should be placed right into `@config` hash, without `browser` parent key.\n" \
7
- "See more here: https://github.com/vifreefly/kimuraframework/blob/master/CHANGELOG.md#breaking-changes-110 ++++++"
8
- end
9
-
10
4
  begin
11
5
  require "kimurai/browser_builder/#{engine}_builder"
12
- rescue LoadError => e
6
+ rescue LoadError
13
7
  end
14
8
 
15
9
  builder_class_name = "#{engine}_builder".classify
@@ -3,7 +3,7 @@ require 'capybara'
3
3
  Capybara.configure do |config|
4
4
  config.run_server = false
5
5
  config.default_selector = :xpath
6
- config.save_path = "tmp"
6
+ config.save_path = 'tmp'
7
7
  config.default_max_wait_time = 10
8
8
  config.ignore_hidden_elements = false
9
9
  config.threadsafe = true
@@ -1,62 +1,66 @@
1
1
  require 'pathname'
2
2
 
3
- class Capybara::Driver::Base
4
- attr_accessor :visited
5
- attr_writer :requests, :responses
3
+ module Capybara
4
+ module Driver
5
+ class Base
6
+ attr_accessor :visited
7
+ attr_writer :requests, :responses
6
8
 
7
- def requests
8
- @requests ||= 0
9
- end
9
+ def requests
10
+ @requests ||= 0
11
+ end
10
12
 
11
- def responses
12
- @responses ||= 0
13
- end
13
+ def responses
14
+ @responses ||= 0
15
+ end
14
16
 
15
- def current_memory
16
- driver_pid = pid
17
+ def current_memory
18
+ driver_pid = pid
17
19
 
18
- all = (get_descendant_processes(driver_pid) << driver_pid).uniq
19
- all.map { |pid| get_process_memory(pid) }.sum
20
- end
20
+ all = (get_descendant_processes(driver_pid) << driver_pid).uniq
21
+ all.map { |pid| get_process_memory(pid) }.sum
22
+ end
21
23
 
22
- private
24
+ private
23
25
 
24
- def get_descendant_processes(base)
25
- descendants = Hash.new { |ht, k| ht[k] = [k] }
26
- Hash[*`ps -eo pid,ppid`.scan(/\d+/).map(&:to_i)].each do |pid, ppid|
27
- descendants[ppid] << descendants[pid]
28
- end
26
+ def get_descendant_processes(base)
27
+ descendants = Hash.new { |ht, k| ht[k] = [k] }
28
+ Hash[*`ps -eo pid,ppid`.scan(/\d+/).map(&:to_i)].each do |pid, ppid|
29
+ descendants[ppid] << descendants[pid]
30
+ end
29
31
 
30
- descendants[base].flatten - [base]
31
- end
32
+ descendants[base].flatten - [base]
33
+ end
32
34
 
33
- # https://github.com/schneems/get_process_mem
34
- # Note: for Linux takes PSS (not RSS) memory (I think PSS better fits in this case)
35
- def get_process_memory(pid)
36
- case @platform ||= Gem::Platform.local.os
37
- when "linux"
38
- begin
39
- file = Pathname.new "/proc/#{pid}/smaps"
40
- return 0 unless file.exist?
41
-
42
- lines = file.each_line.select { |line| line.match(/^Pss/) }
43
- return 0 if lines.empty?
44
-
45
- lines.reduce(0) do |sum, line|
46
- line.match(/(?<value>(\d*\.{0,1}\d+))\s+(?<unit>\w\w)/) do |m|
47
- sum += m[:value].to_i
48
- end
35
+ # https://github.com/schneems/get_process_mem
36
+ # Note: for Linux takes PSS (not RSS) memory (I think PSS better fits in this case)
37
+ def get_process_memory(pid)
38
+ case @platform ||= Gem::Platform.local.os
39
+ when 'linux'
40
+ begin
41
+ file = Pathname.new "/proc/#{pid}/smaps"
42
+ return 0 unless file.exist?
49
43
 
50
- sum
44
+ lines = file.each_line.select { |line| line.match(/^Pss/) }
45
+ return 0 if lines.empty?
46
+
47
+ lines.reduce(0) do |sum, line|
48
+ line.match(/(?<value>(\d*\.{0,1}\d+))\s+(?<unit>\w\w)/) do |m|
49
+ sum += m[:value].to_i
50
+ end
51
+
52
+ sum
53
+ end
54
+ rescue Errno::EACCES
55
+ 0
56
+ end
57
+ when 'darwin'
58
+ mem = `ps -o rss= -p #{pid}`.strip
59
+ mem.empty? ? 0 : mem.to_i
60
+ else
61
+ raise "Can't check process memory, wrong type of platform: #{@platform}"
51
62
  end
52
- rescue Errno::EACCES
53
- 0
54
63
  end
55
- when "darwin"
56
- mem = `ps -o rss= -p #{pid}`.strip
57
- mem.empty? ? 0 : mem.to_i
58
- else
59
- raise "Can't check process memory, wrong type of platform: #{@platform}"
60
64
  end
61
65
  end
62
66
  end
@@ -1,71 +1,72 @@
1
1
  require 'mechanize'
2
2
  require_relative '../driver/base'
3
3
 
4
- class Capybara::Mechanize::Driver
5
- # Extend capybara-mechnize to support Poltergeist-like methods
6
- # https://www.rubydoc.info/gems/poltergeist/Capybara/Poltergeist/Driver
4
+ module Capybara
5
+ module Mechanize
6
+ class Driver
7
+ def set_proxy(ip, port, _type, user = nil, password = nil)
8
+ # type is always "http", "socks" is not supported (yet)
9
+ browser.agent.set_proxy(ip, port, user, password)
10
+ end
7
11
 
8
- def set_proxy(ip, port, type, user = nil, password = nil)
9
- # type is always "http", "socks" is not supported (yet)
10
- browser.agent.set_proxy(ip, port, user, password)
11
- end
12
+ ###
12
13
 
13
- ###
14
+ def headers
15
+ browser.agent.request_headers
16
+ end
14
17
 
15
- def headers
16
- browser.agent.request_headers
17
- end
18
+ def headers=(headers)
19
+ browser.agent.request_headers = headers
20
+ end
18
21
 
19
- def headers=(headers)
20
- browser.agent.request_headers = headers
21
- end
22
+ def add_header(name, value)
23
+ browser.agent.request_headers[name] = value
24
+ end
22
25
 
23
- def add_header(name, value)
24
- browser.agent.request_headers[name] = value
25
- end
26
+ ###
26
27
 
27
- ###
28
+ def get_cookies
29
+ browser.agent.cookies
30
+ end
28
31
 
29
- def get_cookies
30
- browser.agent.cookies
31
- end
32
-
33
- def set_cookie(name, value, options = {})
34
- options[:name] ||= name
35
- options[:value] ||= value
32
+ def set_cookie(name, value, options = {})
33
+ options[:name] ||= name
34
+ options[:value] ||= value
36
35
 
37
- cookie = Mechanize::Cookie.new(options.merge path: "/")
38
- browser.agent.cookie_jar << cookie
39
- end
36
+ cookie = Mechanize::Cookie.new(options.merge(path: '/'))
37
+ browser.agent.cookie_jar << cookie
38
+ end
40
39
 
41
- def set_cookies(cookies)
42
- cookies.each do |cookie|
43
- set_cookie(cookie[:name], cookie[:value], cookie)
44
- end
45
- end
40
+ def set_cookies(cookies)
41
+ cookies.each do |cookie|
42
+ set_cookie(cookie[:name], cookie[:value], cookie)
43
+ end
44
+ end
46
45
 
47
- def clear_cookies
48
- browser.agent.cookie_jar.clear!
49
- end
46
+ def clear_cookies
47
+ browser.agent.cookie_jar.clear!
48
+ end
50
49
 
51
- ###
50
+ ###
52
51
 
53
- def quit
54
- browser.agent.shutdown
55
- end
52
+ def quit
53
+ browser.agent.shutdown
54
+ end
56
55
 
57
- ###
56
+ ###
58
57
 
59
- # Reset parent method `current_memory` for mechanize (we can't measure memory of Mechanize driver)
60
- def current_memory
61
- nil
62
- end
58
+ # Reset parent method `current_memory` for mechanize (we can't measure memory of Mechanize driver)
59
+ def current_memory
60
+ nil
61
+ end
63
62
 
64
- def pid
65
- nil
66
- end
63
+ def pid
64
+ nil
65
+ end
67
66
 
68
- def port
69
- nil
67
+ def port
68
+ nil
69
+ end
70
+ end
70
71
  end
71
72
  end