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.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +21 -0
- data/Gemfile +2 -2
- data/README.md +476 -648
- data/Rakefile +6 -6
- data/bin/console +3 -4
- data/exe/kimurai +0 -1
- data/kimurai.gemspec +38 -37
- data/lib/kimurai/base/saver.rb +15 -19
- data/lib/kimurai/base/storage.rb +1 -1
- data/lib/kimurai/base.rb +38 -38
- data/lib/kimurai/base_helper.rb +5 -4
- data/lib/kimurai/browser_builder/mechanize_builder.rb +121 -119
- data/lib/kimurai/browser_builder/selenium_chrome_builder.rb +160 -152
- data/lib/kimurai/browser_builder/selenium_firefox_builder.rb +162 -160
- data/lib/kimurai/browser_builder.rb +1 -7
- data/lib/kimurai/capybara_configuration.rb +1 -1
- data/lib/kimurai/capybara_ext/driver/base.rb +50 -46
- data/lib/kimurai/capybara_ext/mechanize/driver.rb +51 -50
- data/lib/kimurai/capybara_ext/selenium/driver.rb +33 -29
- data/lib/kimurai/capybara_ext/session.rb +31 -38
- data/lib/kimurai/cli/generator.rb +15 -15
- data/lib/kimurai/cli.rb +49 -86
- data/lib/kimurai/core_ext/array.rb +2 -2
- data/lib/kimurai/core_ext/hash.rb +1 -1
- data/lib/kimurai/core_ext/numeric.rb +4 -4
- data/lib/kimurai/pipeline.rb +2 -1
- data/lib/kimurai/runner.rb +6 -6
- data/lib/kimurai/template/Gemfile +2 -2
- data/lib/kimurai/template/config/boot.rb +4 -4
- data/lib/kimurai/template/config/schedule.rb +15 -15
- data/lib/kimurai/template/spiders/application_spider.rb +8 -14
- data/lib/kimurai/version.rb +1 -1
- data/lib/kimurai.rb +7 -3
- metadata +58 -65
- data/.travis.yml +0 -5
- data/lib/kimurai/automation/deploy.yml +0 -54
- data/lib/kimurai/automation/setup/chromium_chromedriver.yml +0 -26
- data/lib/kimurai/automation/setup/firefox_geckodriver.yml +0 -20
- data/lib/kimurai/automation/setup/phantomjs.yml +0 -33
- data/lib/kimurai/automation/setup/ruby_environment.yml +0 -124
- data/lib/kimurai/automation/setup.yml +0 -44
- data/lib/kimurai/browser_builder/poltergeist_phantomjs_builder.rb +0 -175
- data/lib/kimurai/capybara_ext/poltergeist/driver.rb +0 -13
- data/lib/kimurai/cli/ansible_command_builder.rb +0 -71
- 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
|
|
8
|
-
|
|
9
|
-
class
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
module Kimurai
|
|
8
|
+
module BrowserBuilder
|
|
9
|
+
class SeleniumFirefoxBuilder
|
|
10
|
+
class << self
|
|
11
|
+
attr_accessor :virtual_display
|
|
12
|
+
end
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
attr_reader :logger, :spider
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
def initialize(config, spider:)
|
|
17
|
+
@config = config
|
|
18
|
+
@spider = spider
|
|
19
|
+
@logger = spider.logger
|
|
20
|
+
end
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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):
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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
|
-
|
|
114
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
@
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
157
|
-
@
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
195
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
module Capybara
|
|
4
|
+
module Driver
|
|
5
|
+
class Base
|
|
6
|
+
attr_accessor :visited
|
|
7
|
+
attr_writer :requests, :responses
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
def requests
|
|
10
|
+
@requests ||= 0
|
|
11
|
+
end
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
def responses
|
|
14
|
+
@responses ||= 0
|
|
15
|
+
end
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
def current_memory
|
|
18
|
+
driver_pid = pid
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
all = (get_descendant_processes(driver_pid) << driver_pid).uniq
|
|
21
|
+
all.map { |pid| get_process_memory(pid) }.sum
|
|
22
|
+
end
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
private
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
+
descendants[base].flatten - [base]
|
|
33
|
+
end
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
def headers=(headers)
|
|
19
|
+
browser.agent.request_headers = headers
|
|
20
|
+
end
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
def add_header(name, value)
|
|
23
|
+
browser.agent.request_headers[name] = value
|
|
24
|
+
end
|
|
22
25
|
|
|
23
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
cookie = Mechanize::Cookie.new(options.merge(path: '/'))
|
|
37
|
+
browser.agent.cookie_jar << cookie
|
|
38
|
+
end
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
def clear_cookies
|
|
47
|
+
browser.agent.cookie_jar.clear!
|
|
48
|
+
end
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
###
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
def quit
|
|
53
|
+
browser.agent.shutdown
|
|
54
|
+
end
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
###
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
def pid
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
def port
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
70
71
|
end
|
|
71
72
|
end
|