ferrumwizard 0.1.4 → 0.2.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
- checksums.yaml.gz.sig +0 -0
- data/lib/ferrumwizard.rb +161 -83
- data.tar.gz.sig +0 -0
- metadata +36 -36
- metadata.gz.sig +4 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4b012bc3e8cb9b91311c91eecef6b816cae7bc3d179dc037ac0011373e1d54d2
|
|
4
|
+
data.tar.gz: f0421333194ed8b204ea87beab02314a44f978bbafa28809622b89d1db26bd4f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b96dd21840cbed0d1253f4795ddf4a4cf36250d5d3736b918c70c7c48ef63d4e8ba31592395cce6de691049a076f41186337a92643e3e1748e122f58edc51905
|
|
7
|
+
data.tar.gz: 39d7c5cc96e6900db1bbfa668ba9b972d49f09147d0fc5b079c34fd40e7235bb256a1713c1bf5725a16c0087dca959d5df8b12b7f10e093891478bf0a33f53f2
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/lib/ferrumwizard.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# file: ferrumwizard.rb
|
|
4
4
|
|
|
5
|
+
require 'yaml'
|
|
5
6
|
require 'rexle'
|
|
6
7
|
require 'ferrum'
|
|
7
8
|
|
|
@@ -10,25 +11,58 @@ class FerrumWizard
|
|
|
10
11
|
|
|
11
12
|
attr_reader :browser, :links, :radio, :buttons, :js_methods
|
|
12
13
|
|
|
13
|
-
def initialize(url, headless: true, timeout: 10, debug: false)
|
|
14
|
+
def initialize(url=nil, headless: true, timeout: 10, debug: false)
|
|
14
15
|
|
|
15
16
|
@url, @debug = url, debug
|
|
16
17
|
@browser = Ferrum::Browser.new headless: headless, timeout: timeout
|
|
17
18
|
sleep 3
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
if url
|
|
20
21
|
@browser.goto(@url)
|
|
21
22
|
@browser.network.wait_for_idle
|
|
22
|
-
sleep 4
|
|
23
|
+
sleep 4
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
def inspect()
|
|
27
28
|
"#<FerrumWizard>"
|
|
28
29
|
end
|
|
29
|
-
|
|
30
|
+
|
|
31
|
+
# Intended to load all the cookies for a user to login automatically
|
|
32
|
+
#
|
|
33
|
+
# Follow these steps to load the cookies file:
|
|
34
|
+
#
|
|
35
|
+
# 1. launch the Ferrum browser
|
|
36
|
+
# fw = FerrumWizard.new( headless: false, debug: false)
|
|
37
|
+
#
|
|
38
|
+
# 2. load the cookies before you visit the website
|
|
39
|
+
# fw.load_cookies('/tmp/indeed2.txt')
|
|
40
|
+
#
|
|
41
|
+
# 3. visit the website
|
|
42
|
+
# url='https://somewebsite.com'
|
|
43
|
+
# fw.browser.goto(url)
|
|
44
|
+
#
|
|
45
|
+
def load_cookies(filepath)
|
|
46
|
+
|
|
47
|
+
rawcookies = YAML.load(File.read(filepath))
|
|
48
|
+
|
|
49
|
+
rawcookies.each do |h|
|
|
50
|
+
|
|
51
|
+
if @debug then
|
|
52
|
+
puts 'name: ' + h['name']
|
|
53
|
+
puts 'h: ' + h.inspect
|
|
54
|
+
sleep 0.7
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
browser.cookies.set(name: h['name'], value: h['value'],
|
|
58
|
+
domain: h['domain'], expires: h['expires'],
|
|
59
|
+
httponly: h['httpOnly'])
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
30
64
|
def login(usernamex=nil, passwordx=nil, username: usernamex, password: passwordx)
|
|
31
|
-
|
|
65
|
+
|
|
32
66
|
puts 'username: ' + username.inspect if @debug
|
|
33
67
|
|
|
34
68
|
# search for the username input box
|
|
@@ -36,23 +70,33 @@ class FerrumWizard
|
|
|
36
70
|
puts 'e_username: ' + e_username.inspect if @debug
|
|
37
71
|
sleep 1
|
|
38
72
|
# search for the password input box
|
|
39
|
-
|
|
73
|
+
found = @browser.at_xpath('//input[@type="password"]')
|
|
74
|
+
|
|
75
|
+
e_password = if found then
|
|
76
|
+
found
|
|
77
|
+
else
|
|
78
|
+
@browser.xpath('//input').find {|x| x.property(:id) =~ /password/i}
|
|
79
|
+
end
|
|
80
|
+
|
|
40
81
|
sleep 1
|
|
41
|
-
|
|
82
|
+
|
|
42
83
|
if username and e_username then
|
|
43
84
|
puts 'entering the username' if @debug
|
|
44
|
-
e_username.focus.type(username)
|
|
85
|
+
e_username.focus.type(username)
|
|
45
86
|
sleep 1
|
|
46
87
|
end
|
|
47
|
-
|
|
88
|
+
|
|
48
89
|
e_password.focus.type(password, :Enter) if e_password
|
|
49
|
-
|
|
90
|
+
|
|
50
91
|
after_login()
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# login2 is used for websites where the user is presented with the username
|
|
96
|
+
# input box on the first page and the password input box on the next page.
|
|
97
|
+
#
|
|
54
98
|
def login2(usernamex=nil, passwordx=nil, username: usernamex, password: passwordx)
|
|
55
|
-
|
|
99
|
+
|
|
56
100
|
puts 'username: ' + username.inspect if @debug
|
|
57
101
|
|
|
58
102
|
# search for the username input box
|
|
@@ -60,70 +104,104 @@ class FerrumWizard
|
|
|
60
104
|
puts 'e_username: ' + e_username.inspect if @debug
|
|
61
105
|
sleep 1
|
|
62
106
|
# search for the password input box
|
|
63
|
-
|
|
107
|
+
|
|
64
108
|
if username and e_username then
|
|
65
109
|
puts 'entering the username' if @debug
|
|
66
|
-
e_username.focus.type(username, :Enter)
|
|
110
|
+
e_username.focus.type(username, :Enter)
|
|
67
111
|
sleep 2
|
|
68
112
|
end
|
|
69
113
|
|
|
70
|
-
e_password =
|
|
114
|
+
e_password = @browser.at_xpath('//input[@type="password"]')
|
|
71
115
|
sleep 1
|
|
72
|
-
|
|
116
|
+
|
|
73
117
|
e_password.focus.type(password, :Enter) if e_password
|
|
74
|
-
|
|
118
|
+
|
|
75
119
|
after_login()
|
|
76
120
|
|
|
77
|
-
|
|
78
|
-
end
|
|
79
|
-
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
|
|
80
124
|
def quit
|
|
81
125
|
@browser.quit
|
|
82
126
|
end
|
|
83
|
-
|
|
127
|
+
|
|
84
128
|
def scan_page()
|
|
85
|
-
|
|
86
|
-
@doc = Rexle.new @browser.body
|
|
129
|
+
|
|
130
|
+
@doc = Rexle.new @browser.body
|
|
87
131
|
fetch_links()
|
|
88
|
-
scan_form_elements()
|
|
132
|
+
scan_form_elements()
|
|
89
133
|
scan_js_links()
|
|
90
|
-
|
|
134
|
+
@browser.mouse.scroll_to(0, 800)
|
|
135
|
+
self
|
|
91
136
|
end
|
|
92
|
-
|
|
137
|
+
|
|
138
|
+
# Saves all cookies for a given website into a YAML file
|
|
139
|
+
# see also load_cookies()
|
|
140
|
+
#
|
|
141
|
+
# To use this method follow these steps:
|
|
142
|
+
#
|
|
143
|
+
# 1. launch the web browser through Ferrum
|
|
144
|
+
# fw = FerrumWizard.new(url, headless: false, debug: false)
|
|
145
|
+
#
|
|
146
|
+
# 2. go to the browser and login using your credentials
|
|
147
|
+
# fw.save_cookies(filepath)
|
|
148
|
+
#
|
|
149
|
+
# 3. exit the IRB session
|
|
150
|
+
#
|
|
151
|
+
def save_cookies(filepath=Tempfile.new('ferrum').path)
|
|
152
|
+
|
|
153
|
+
rawcookies = @browser.cookies.all.keys.map do |key|
|
|
154
|
+
|
|
155
|
+
if @debug then
|
|
156
|
+
puts 'key: ' + key.inspect
|
|
157
|
+
sleep 0.5
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
s = @browser.cookies[key].inspect
|
|
161
|
+
a = s.scan(/"([^"]+)"=\>/)
|
|
162
|
+
s2 = s[/(?<=@attributes=).*(?=>)/]
|
|
163
|
+
eval(s2)
|
|
164
|
+
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
File.write filepath, rawcookies.to_yaml
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
|
|
93
171
|
def submit(h)
|
|
94
172
|
|
|
95
173
|
e = nil
|
|
96
|
-
|
|
174
|
+
|
|
97
175
|
h.each do |key, value|
|
|
98
|
-
e = @browser.xpath('//input').find {|x| x.attribute('name') == key.to_s}
|
|
99
|
-
e.focus.type(value)
|
|
176
|
+
e = @browser.xpath('//input').find {|x| x.attribute('name') == key.to_s}
|
|
177
|
+
e.focus.type(value)
|
|
100
178
|
end
|
|
101
|
-
|
|
102
|
-
e.focus.type('', :Enter)
|
|
103
|
-
|
|
104
|
-
sleep 4
|
|
179
|
+
|
|
180
|
+
e.focus.type('', :Enter)
|
|
181
|
+
|
|
182
|
+
sleep 4
|
|
105
183
|
scan_page()
|
|
106
|
-
|
|
184
|
+
|
|
107
185
|
end
|
|
108
186
|
|
|
109
187
|
def to_rb()
|
|
110
188
|
end
|
|
111
|
-
|
|
189
|
+
|
|
112
190
|
private
|
|
113
|
-
|
|
191
|
+
|
|
114
192
|
def after_login()
|
|
115
|
-
|
|
116
|
-
@browser.network.wait_for_idle
|
|
193
|
+
|
|
194
|
+
@browser.network.wait_for_idle
|
|
117
195
|
sleep 4
|
|
118
196
|
scan_page()
|
|
119
|
-
|
|
197
|
+
|
|
120
198
|
@browser.base_url = File.dirname(@browser.url)
|
|
121
199
|
@browser.mouse.scroll_to(0, 800)
|
|
122
200
|
self
|
|
123
|
-
|
|
201
|
+
|
|
124
202
|
end
|
|
125
|
-
|
|
126
|
-
|
|
203
|
+
|
|
204
|
+
|
|
127
205
|
def fetch_buttons()
|
|
128
206
|
|
|
129
207
|
a2 = @browser.xpath('//input[@type="button"]')
|
|
@@ -139,24 +217,24 @@ class FerrumWizard
|
|
|
139
217
|
buttons = @buttons
|
|
140
218
|
|
|
141
219
|
names.each do |name|
|
|
142
|
-
|
|
220
|
+
|
|
143
221
|
define_singleton_method name.to_sym do
|
|
144
222
|
buttons[name].click
|
|
145
223
|
@browser.network.wait_for_idle
|
|
146
224
|
sleep = 1
|
|
147
225
|
self
|
|
148
226
|
end
|
|
149
|
-
|
|
227
|
+
|
|
150
228
|
end
|
|
151
229
|
|
|
152
230
|
end
|
|
153
|
-
|
|
231
|
+
|
|
154
232
|
def fetch_links()
|
|
155
|
-
|
|
233
|
+
|
|
156
234
|
all_links = @doc.root.xpath('//a[@href]')
|
|
157
|
-
|
|
235
|
+
|
|
158
236
|
all_links.each do |x|
|
|
159
|
-
|
|
237
|
+
|
|
160
238
|
if x.plaintext.empty? then
|
|
161
239
|
x.text = x.attributes[:href].sub(/\.\w+$/,'')[/([^\/]+)$/].split(/[_]|(?=[A-Z])/).join(' ')
|
|
162
240
|
else
|
|
@@ -164,74 +242,74 @@ class FerrumWizard
|
|
|
164
242
|
end
|
|
165
243
|
|
|
166
244
|
end
|
|
167
|
-
|
|
245
|
+
|
|
168
246
|
valid_links = all_links.reject do |x|
|
|
169
|
-
|
|
247
|
+
|
|
170
248
|
puts 'x: ' + x.inspect if @debug
|
|
171
249
|
r = (x.attributes[:target] == '_blank')
|
|
172
250
|
|
|
173
251
|
puts 'r: ' + r.inspect if @debug
|
|
174
252
|
r
|
|
175
|
-
|
|
253
|
+
|
|
176
254
|
end
|
|
177
|
-
|
|
255
|
+
|
|
178
256
|
indices = valid_links.map {|x| all_links.index x}
|
|
179
257
|
|
|
180
258
|
active_links = @browser.xpath('//a[@href]')
|
|
181
259
|
valid_active_links = indices.map {|n| active_links[n]}
|
|
182
|
-
|
|
183
260
|
|
|
184
|
-
|
|
261
|
+
|
|
262
|
+
@links = valid_active_links.flat_map.with_index do |x, i|
|
|
185
263
|
|
|
186
264
|
a = valid_links[i].text.split(/\W+/).map {|label| [label, x]}
|
|
187
265
|
a << [valid_links[i].text, x]
|
|
188
|
-
|
|
266
|
+
|
|
189
267
|
puts 'a: ' + a.inspect if @debug
|
|
190
268
|
a + a.map {|x2, obj| [x2.downcase, obj]}
|
|
191
|
-
|
|
269
|
+
|
|
192
270
|
end.to_h
|
|
193
|
-
|
|
271
|
+
|
|
194
272
|
names = @links.keys.map(&:downcase).uniq.select {|x| x =~ /^[\w ]+$/}
|
|
195
273
|
links = @links
|
|
196
|
-
|
|
274
|
+
|
|
197
275
|
names.each do |name|
|
|
198
|
-
|
|
276
|
+
|
|
199
277
|
define_singleton_method name.gsub(/ +/,'_').to_sym do
|
|
200
|
-
|
|
278
|
+
|
|
201
279
|
links[name].click
|
|
202
280
|
@browser.network.wait_for_idle
|
|
203
|
-
|
|
281
|
+
|
|
204
282
|
sleep 1
|
|
205
283
|
scan_page()
|
|
206
284
|
self
|
|
207
|
-
|
|
285
|
+
|
|
208
286
|
end
|
|
209
|
-
|
|
287
|
+
|
|
210
288
|
end
|
|
211
|
-
|
|
289
|
+
|
|
212
290
|
end
|
|
213
291
|
|
|
214
292
|
def scan_form_elements()
|
|
215
|
-
|
|
293
|
+
|
|
216
294
|
# find radio buttons
|
|
217
|
-
|
|
295
|
+
|
|
218
296
|
a = @browser.xpath('//input[@type="radio"]')
|
|
219
297
|
h = a.group_by {|x| x.attribute('name')}
|
|
220
298
|
@radio = h.values
|
|
221
299
|
define_singleton_method(:on) { @radio[0][0].click; self }
|
|
222
300
|
define_singleton_method(:off) { @radio[0][1].click; self }
|
|
223
|
-
|
|
301
|
+
|
|
224
302
|
fetch_buttons()
|
|
225
|
-
|
|
303
|
+
|
|
226
304
|
end
|
|
227
|
-
|
|
305
|
+
|
|
228
306
|
def scan_js_links()
|
|
229
|
-
|
|
307
|
+
|
|
230
308
|
@js_methods = {}
|
|
231
309
|
b = @browser
|
|
232
|
-
|
|
310
|
+
|
|
233
311
|
b.xpath('//a').select {|x| x.attribute('href') =~ /^javascript/}.each do |e|
|
|
234
|
-
|
|
312
|
+
|
|
235
313
|
|
|
236
314
|
s = e.attribute('href')[/(?<=^javascript:)[^\(]+/]
|
|
237
315
|
puts 's: ' + s.inspect if @debug
|
|
@@ -241,17 +319,17 @@ class FerrumWizard
|
|
|
241
319
|
a << [s.split(/\W+|(?=[A-Z])/).join('_').downcase, s]
|
|
242
320
|
#@js_methods[s] = a
|
|
243
321
|
|
|
244
|
-
a.concat a.map {|x, name| [x.downcase, name] }
|
|
322
|
+
a.concat a.map {|x, name| [x.downcase, name] }
|
|
245
323
|
|
|
246
324
|
puts 'a: ' + a.inspect if @debug
|
|
247
325
|
|
|
248
326
|
a.uniq.select {|x, _| x =~ /^[a-z0-9_]+$/}.each do |x, name|
|
|
249
|
-
|
|
327
|
+
|
|
250
328
|
if @debug then
|
|
251
329
|
puts 'x: ' + x.inspect
|
|
252
330
|
puts 'name: ' + name.inspect
|
|
253
331
|
end
|
|
254
|
-
|
|
332
|
+
|
|
255
333
|
define_singleton_method(x.to_sym) do |*args|
|
|
256
334
|
#args = raw_args.map {|x| x[/^[0-9]+$/] ? x.to_i : x}
|
|
257
335
|
js_method = "%s(%s)" % [name, args.map(&:inspect).join(', ')]
|
|
@@ -260,9 +338,9 @@ class FerrumWizard
|
|
|
260
338
|
sleep 4
|
|
261
339
|
self.scan_page()
|
|
262
340
|
end
|
|
263
|
-
|
|
341
|
+
|
|
264
342
|
end
|
|
265
|
-
|
|
343
|
+
|
|
266
344
|
end
|
|
267
345
|
end
|
|
268
346
|
|
|
@@ -271,7 +349,7 @@ class FerrumWizard
|
|
|
271
349
|
puts 'method_missing: ' + method_name.inspect if @debug
|
|
272
350
|
node = @browser.at_css '.' + method_name.to_s
|
|
273
351
|
node.text if node
|
|
274
|
-
|
|
275
|
-
end
|
|
276
|
-
|
|
352
|
+
|
|
353
|
+
end
|
|
354
|
+
|
|
277
355
|
end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ferrumwizard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Robertson
|
|
@@ -11,31 +11,31 @@ cert_chain:
|
|
|
11
11
|
- |
|
|
12
12
|
-----BEGIN CERTIFICATE-----
|
|
13
13
|
MIIEXjCCAsagAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMSowKAYDVQQDDCFnZW1t
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
YXN0ZXIvREM9amFtZXNyb2JlcnRzb24vREM9ZXUwHhcNMjIwMzMwMTI1ODU1WhcN
|
|
15
|
+
MjMwMzMwMTI1ODU1WjAsMSowKAYDVQQDDCFnZW1tYXN0ZXIvREM9amFtZXNyb2Jl
|
|
16
|
+
cnRzb24vREM9ZXUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDROL32
|
|
17
|
+
3LQKGcDR6x6XFa1US/Vq98DVnMeZHCSKdf471I4gJIOA7sQnrQTB6IZKTxb94Wjr
|
|
18
|
+
OSeGzlJpVq6pa7ltxvb9T7YQVVRrXYMC+u0gD9ukolnkpV/4Rh2/IIMxSNKncoZB
|
|
19
|
+
LKPseizGKlli4gs134gAu3wuWdCC7/UWPG/XyocdJC8tLtf/zi4JuRJTojKqYLOp
|
|
20
|
+
KsP9jHPmGVr81cW8HePmhQ/+LiYlKDE4Fwj4yl16XqhF7/5YOz9e5LOHsMUEord4
|
|
21
|
+
JscQ3GnhMfEXGJpwqCwNEpM3xAwcHp2DDdrwtT36ujSfnTJ3UpUIQUKVehA2i9rm
|
|
22
|
+
uDcDTr1PATGcOMPpExvLZu3a9uC81mj9z+axH5mWQ7jZ92sze79oAQTsMiMyBavJ
|
|
23
|
+
djSpnVBo71PFk8QekgIVVBIzG0iN5zoNUrSthvL/xUWXM6ea015HEDCCIEL417ID
|
|
24
|
+
humVWZyzKf7ITCdZWcxTgTgFfuPMctcICT5u7va+FrycYpdtt8kXvtD3VnkCAwEA
|
|
25
|
+
AaOBijCBhzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUDipvmNU2
|
|
26
|
+
WydgAK8QPGb0vhhoGl0wJgYDVR0RBB8wHYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0
|
|
27
27
|
c29uLmV1MCYGA1UdEgQfMB2BG2dlbW1hc3RlckBqYW1lc3JvYmVydHNvbi5ldTAN
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
BgkqhkiG9w0BAQsFAAOCAYEAHqRvm6iqjJ+bpEzSSgVmOMOMcgIoN6px1LMVAOmY
|
|
29
|
+
BJpF5F0fJr99thc1EYZJoRTwEcXJYhCTqKg+3xhNKpCzk2qHsaLKYEygPeBpyJOg
|
|
30
|
+
LyfHLrj98QLPYyFzqhWsqZAAAGC9WSF/kBJazpuotU2ec/Xw/e3NPopedV/Zvuhs
|
|
31
|
+
+/OKZWwRez/hg97ckaCYAp/7OdrVhJvR87MaQnN52Uk8OQbuPSyUNQUJ044HWHtu
|
|
32
|
+
lEJjsDetEFhNB69j3wAIMjMEZao29/dZhALbUDp+9ewK7uYbrX9Bo68NX+H+XcCZ
|
|
33
|
+
VFrdrjkyJUOHwSmvjYXN1V0Yz8kVVFU7E+Q4RHL8yAwBv+ynd927HtZVjs+455Pc
|
|
34
|
+
z+9gNpBQVr6LLXLJgJF2pTaIoYhgG6pcoMQHGVoxWdKzvOcl0h1epeJSp/aynX/r
|
|
35
|
+
FK+cyrQNA9DLJYJuz6uO7Z+gXZWjwAO38LUwF01w49asSv/5ZH2HH/EauX5xWpe+
|
|
36
|
+
ry6lYQlb8j50Iys5elAy1p0i
|
|
37
37
|
-----END CERTIFICATE-----
|
|
38
|
-
date:
|
|
38
|
+
date: 2022-03-30 00:00:00.000000000 Z
|
|
39
39
|
dependencies:
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: rexle
|
|
@@ -46,7 +46,7 @@ dependencies:
|
|
|
46
46
|
version: '1.5'
|
|
47
47
|
- - ">="
|
|
48
48
|
- !ruby/object:Gem::Version
|
|
49
|
-
version: 1.5.
|
|
49
|
+
version: 1.5.14
|
|
50
50
|
type: :runtime
|
|
51
51
|
prerelease: false
|
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -56,29 +56,29 @@ dependencies:
|
|
|
56
56
|
version: '1.5'
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: 1.5.
|
|
59
|
+
version: 1.5.14
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
61
|
name: ferrum
|
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
|
63
63
|
requirements:
|
|
64
|
-
- - ">="
|
|
65
|
-
- !ruby/object:Gem::Version
|
|
66
|
-
version: 0.9.0
|
|
67
64
|
- - "~>"
|
|
68
65
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: '0.
|
|
66
|
+
version: '0.11'
|
|
67
|
+
- - ">="
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '0.11'
|
|
70
70
|
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
73
73
|
requirements:
|
|
74
|
-
- - ">="
|
|
75
|
-
- !ruby/object:Gem::Version
|
|
76
|
-
version: 0.9.0
|
|
77
74
|
- - "~>"
|
|
78
75
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: '0.
|
|
76
|
+
version: '0.11'
|
|
77
|
+
- - ">="
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '0.11'
|
|
80
80
|
description:
|
|
81
|
-
email:
|
|
81
|
+
email: digital.robertson@gmail.com
|
|
82
82
|
executables: []
|
|
83
83
|
extensions: []
|
|
84
84
|
extra_rdoc_files: []
|
|
@@ -103,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
103
103
|
- !ruby/object:Gem::Version
|
|
104
104
|
version: '0'
|
|
105
105
|
requirements: []
|
|
106
|
-
rubygems_version: 3.
|
|
106
|
+
rubygems_version: 3.2.22
|
|
107
107
|
signing_key:
|
|
108
108
|
specification_version: 4
|
|
109
109
|
summary: Makes web scraping easier using the Ferrum gem.
|
metadata.gz.sig
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
�w�
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
�L]Ѩ�D#��IKSs^�QE��G3�h��3L0���Q�!�<ʛx�r��R���:�X:b@+��%3;�]x�+��f/L��D�hv͙�P��c��i��#l�ْ��x�_�4QwUל^���}Y؍�A�"g�b�F�Mr��N?N#�52��w�̳V��c\^�X�<=�����
|
|
1
|
+
�in��woȾ�t�58�w�B�'�??
|
|
2
|
+
U�щ�
|
|
3
|
+
1�k�<�(�
|
|
4
|
+
�`�V�q0��@�� Q �/�b�@��o����� f�Z�F���[Q��*�*�M�7��퉰N3?��q��R� f)���9�W\�
|