pincers 0.6.0 → 0.7.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/lib/pincers/chenso/backend.rb +162 -0
- data/lib/pincers/chenso/browsing_context.rb +76 -0
- data/lib/pincers/chenso/browsing_manager.rb +67 -0
- data/lib/pincers/chenso/factory.rb +27 -0
- data/lib/pincers/chenso/html_form_request.rb +7 -0
- data/lib/pincers/chenso/html_page_request.rb +27 -0
- data/lib/pincers/{backend/base.rb → core/base_backend.rb} +18 -8
- data/lib/pincers/{factories/base.rb → core/base_factory.rb} +2 -2
- data/lib/pincers/core/helpers/form.rb +106 -0
- data/lib/pincers/core/{query.rb → helpers/query.rb} +3 -4
- data/lib/pincers/core/replicas/form.rb +43 -0
- data/lib/pincers/core/replicas/link.rb +18 -0
- data/lib/pincers/core/root_context.rb +25 -6
- data/lib/pincers/core/search_context.rb +24 -3
- data/lib/pincers/errors.rb +4 -1
- data/lib/pincers/extension/labs.rb +3 -0
- data/lib/pincers/factory.rb +9 -4
- data/lib/pincers/http/base_document.rb +20 -0
- data/lib/pincers/http/client.rb +134 -0
- data/lib/pincers/{support → http}/cookie.rb +1 -1
- data/lib/pincers/{support → http}/cookie_jar.rb +4 -3
- data/lib/pincers/http/errors.rb +26 -0
- data/lib/pincers/http/request.rb +62 -0
- data/lib/pincers/http/response_document.rb +24 -0
- data/lib/pincers/http/session.rb +99 -0
- data/lib/pincers/http/utils.rb +43 -0
- data/lib/pincers/nokogiri/backend.rb +151 -0
- data/lib/pincers/{factories/nokogiri.rb → nokogiri/factory.rb} +5 -5
- data/lib/pincers/version.rb +1 -1
- data/lib/pincers/{backend/webdriver.rb → webdriver/backend.rb} +22 -31
- data/lib/pincers/{factories/webdriver.rb → webdriver/factory.rb} +5 -5
- data/lib/pincers/webdriver/http_document.rb +23 -0
- metadata +42 -13
- data/lib/pincers/backend/nokogiri.rb +0 -66
- data/lib/pincers/core/download.rb +0 -14
- data/lib/pincers/support/http_client.rb +0 -123
data/lib/pincers/version.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'selenium-webdriver'
|
2
|
+
require 'pincers/core/base_backend'
|
3
|
+
require 'pincers/http/client'
|
4
|
+
require 'pincers/webdriver/http_document'
|
5
5
|
|
6
|
-
module Pincers::
|
7
|
-
|
8
|
-
class Webdriver < Base
|
6
|
+
module Pincers::Webdriver
|
7
|
+
class Backend < Pincers::Core::BaseBackend
|
9
8
|
|
10
9
|
DOM_PROPERTIES = [:selected, :disabled, :checked, :value, :required]
|
11
10
|
|
12
|
-
|
11
|
+
attr_reader :driver
|
12
|
+
|
13
|
+
alias :document :driver
|
13
14
|
|
14
15
|
def initialize(_driver)
|
15
|
-
|
16
|
+
@driver = _driver
|
16
17
|
end
|
17
18
|
|
18
19
|
def javascript_enabled?
|
@@ -143,6 +144,11 @@ module Pincers::Backend
|
|
143
144
|
actions.drag_and_drop(_element, _on).perform
|
144
145
|
end
|
145
146
|
|
147
|
+
def submit_form(_element)
|
148
|
+
_element = ensure_element _element
|
149
|
+
_element.submit
|
150
|
+
end
|
151
|
+
|
146
152
|
def switch_to_frame(_element)
|
147
153
|
driver.switch_to.frame _element
|
148
154
|
end
|
@@ -151,10 +157,13 @@ module Pincers::Backend
|
|
151
157
|
driver.switch_to.default_content
|
152
158
|
end
|
153
159
|
|
154
|
-
def
|
155
|
-
|
156
|
-
|
157
|
-
|
160
|
+
def as_http_client
|
161
|
+
session = Pincers::Http::Session.new
|
162
|
+
session.headers['User-Agent'] = user_agent
|
163
|
+
session.proxy = proxy_address
|
164
|
+
driver.manage.all_cookies.each { |c| session.cookie_jar.set c }
|
165
|
+
|
166
|
+
Pincers::Http::Client.new session, HttpDocument.new(self)
|
158
167
|
end
|
159
168
|
|
160
169
|
private
|
@@ -200,16 +209,6 @@ module Pincers::Backend
|
|
200
209
|
_element
|
201
210
|
end
|
202
211
|
|
203
|
-
def as_http_client
|
204
|
-
Pincers::Support::HttpClient.new({
|
205
|
-
proxy: proxy_address,
|
206
|
-
cookies: cookie_jar,
|
207
|
-
headers: {
|
208
|
-
'User-Agent' => user_agent
|
209
|
-
}
|
210
|
-
})
|
211
|
-
end
|
212
|
-
|
213
212
|
def user_agent
|
214
213
|
driver.execute_script("return navigator.userAgent;")
|
215
214
|
end
|
@@ -218,13 +217,5 @@ module Pincers::Backend
|
|
218
217
|
proxy = driver.capabilities.proxy
|
219
218
|
proxy.nil? ? nil : (proxy.http || proxy.ssl)
|
220
219
|
end
|
221
|
-
|
222
|
-
def cookie_jar
|
223
|
-
jar = Pincers::Support::CookieJar.new
|
224
|
-
driver.manage.all_cookies.each { |c| jar.set c }
|
225
|
-
jar
|
226
|
-
end
|
227
|
-
|
228
220
|
end
|
229
|
-
|
230
221
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'pincers/
|
2
|
-
require 'pincers/backend
|
1
|
+
require 'pincers/core/base_factory'
|
2
|
+
require 'pincers/webdriver/backend'
|
3
3
|
|
4
|
-
module Pincers::
|
5
|
-
class
|
4
|
+
module Pincers::Webdriver
|
5
|
+
class Factory < Pincers::Core::BaseFactory
|
6
6
|
|
7
7
|
DEFAULT_SETUP = {
|
8
8
|
page_timeout: 60000
|
@@ -17,7 +17,7 @@ module Pincers::Factories
|
|
17
17
|
setup_driver driver, _options
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
Pincers::Webdriver::Backend.new driver
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'pincers/http/utils'
|
2
|
+
|
3
|
+
module Pincers::Webdriver
|
4
|
+
class HttpDocument
|
5
|
+
|
6
|
+
def initialize(_backend)
|
7
|
+
@backend = _backend
|
8
|
+
end
|
9
|
+
|
10
|
+
def uri
|
11
|
+
Pincers::Http::Utils.parse_uri @backend.document_url
|
12
|
+
end
|
13
|
+
|
14
|
+
def content_type
|
15
|
+
'text/html'
|
16
|
+
end
|
17
|
+
|
18
|
+
def content
|
19
|
+
@backend
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pincers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ignacio Baixas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -206,6 +206,20 @@ dependencies:
|
|
206
206
|
- - ~>
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '1.6'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: webmock
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ~>
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '1.22'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ~>
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '1.22'
|
209
223
|
description: Web automation DSL on top of webdriver and nokogiri
|
210
224
|
email:
|
211
225
|
- ignacio@platan.us
|
@@ -214,12 +228,19 @@ extensions: []
|
|
214
228
|
extra_rdoc_files: []
|
215
229
|
files:
|
216
230
|
- lib/pincers.rb
|
217
|
-
- lib/pincers/backend
|
218
|
-
- lib/pincers/
|
219
|
-
- lib/pincers/
|
231
|
+
- lib/pincers/chenso/backend.rb
|
232
|
+
- lib/pincers/chenso/browsing_context.rb
|
233
|
+
- lib/pincers/chenso/browsing_manager.rb
|
234
|
+
- lib/pincers/chenso/factory.rb
|
235
|
+
- lib/pincers/chenso/html_form_request.rb
|
236
|
+
- lib/pincers/chenso/html_page_request.rb
|
237
|
+
- lib/pincers/core/base_backend.rb
|
238
|
+
- lib/pincers/core/base_factory.rb
|
220
239
|
- lib/pincers/core/cookies.rb
|
221
|
-
- lib/pincers/core/
|
222
|
-
- lib/pincers/core/query.rb
|
240
|
+
- lib/pincers/core/helpers/form.rb
|
241
|
+
- lib/pincers/core/helpers/query.rb
|
242
|
+
- lib/pincers/core/replicas/form.rb
|
243
|
+
- lib/pincers/core/replicas/link.rb
|
223
244
|
- lib/pincers/core/root_context.rb
|
224
245
|
- lib/pincers/core/search_context.rb
|
225
246
|
- lib/pincers/css/parser.rb
|
@@ -228,16 +249,24 @@ files:
|
|
228
249
|
- lib/pincers/extension/actions.rb
|
229
250
|
- lib/pincers/extension/labs.rb
|
230
251
|
- lib/pincers/extension/queries.rb
|
231
|
-
- lib/pincers/factories/base.rb
|
232
|
-
- lib/pincers/factories/nokogiri.rb
|
233
|
-
- lib/pincers/factories/webdriver.rb
|
234
252
|
- lib/pincers/factory.rb
|
253
|
+
- lib/pincers/http/base_document.rb
|
254
|
+
- lib/pincers/http/client.rb
|
255
|
+
- lib/pincers/http/cookie.rb
|
256
|
+
- lib/pincers/http/cookie_jar.rb
|
257
|
+
- lib/pincers/http/errors.rb
|
258
|
+
- lib/pincers/http/request.rb
|
259
|
+
- lib/pincers/http/response_document.rb
|
260
|
+
- lib/pincers/http/session.rb
|
261
|
+
- lib/pincers/http/utils.rb
|
262
|
+
- lib/pincers/nokogiri/backend.rb
|
263
|
+
- lib/pincers/nokogiri/factory.rb
|
235
264
|
- lib/pincers/support/configuration.rb
|
236
|
-
- lib/pincers/support/cookie.rb
|
237
|
-
- lib/pincers/support/cookie_jar.rb
|
238
|
-
- lib/pincers/support/http_client.rb
|
239
265
|
- lib/pincers/support/xpath_builder.rb
|
240
266
|
- lib/pincers/version.rb
|
267
|
+
- lib/pincers/webdriver/backend.rb
|
268
|
+
- lib/pincers/webdriver/factory.rb
|
269
|
+
- lib/pincers/webdriver/http_document.rb
|
241
270
|
homepage: https://github.com/platanus/pincers
|
242
271
|
licenses:
|
243
272
|
- MIT
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'pincers/backend/base'
|
2
|
-
|
3
|
-
module Pincers::Backend
|
4
|
-
|
5
|
-
class Nokogiri < Base
|
6
|
-
|
7
|
-
BOOL_PROPERTIES = [:selected, :disabled, :checked, :required]
|
8
|
-
|
9
|
-
def document_root
|
10
|
-
[document]
|
11
|
-
end
|
12
|
-
|
13
|
-
def document_title
|
14
|
-
document.title
|
15
|
-
end
|
16
|
-
|
17
|
-
def close_document
|
18
|
-
# no closing needed
|
19
|
-
end
|
20
|
-
|
21
|
-
def search_by_css(_element, _selector, _limit)
|
22
|
-
# nokogiri does not do any query level optimization when searching just one node
|
23
|
-
_element.css _selector
|
24
|
-
end
|
25
|
-
|
26
|
-
def search_by_xpath(_element, _selector, _limit)
|
27
|
-
# nokogiri does not do any query level optimization when searching just one node
|
28
|
-
_element.xpath _selector
|
29
|
-
end
|
30
|
-
|
31
|
-
def extract_element_tag(_element)
|
32
|
-
_element.name
|
33
|
-
end
|
34
|
-
|
35
|
-
def extract_element_text(_element)
|
36
|
-
_element.content
|
37
|
-
end
|
38
|
-
|
39
|
-
def extract_element_html(_element)
|
40
|
-
_element.to_html
|
41
|
-
end
|
42
|
-
|
43
|
-
def extract_element_attribute(_element, _name)
|
44
|
-
_name = _name.to_sym
|
45
|
-
value = _element[_name]
|
46
|
-
|
47
|
-
if BOOL_PROPERTIES.include? _name
|
48
|
-
value = !value.nil?
|
49
|
-
elsif _name == :value
|
50
|
-
value = checkbox_value_fix _element, value
|
51
|
-
end
|
52
|
-
|
53
|
-
value
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def checkbox_value_fix(_element, _value)
|
59
|
-
if _value.nil? and _element.name.downcase == 'input' and ['checkbox', 'radio'].include? _element[:type].downcase
|
60
|
-
'on'
|
61
|
-
else _value end
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Pincers::Core
|
2
|
-
|
3
|
-
class Download < Struct.new(:mime, :data)
|
4
|
-
|
5
|
-
def self.from_http_response(_response)
|
6
|
-
self.new _response['Content-Type'] || 'text/plain', _response.body
|
7
|
-
end
|
8
|
-
|
9
|
-
def store(_path)
|
10
|
-
File.write _path, data
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|
@@ -1,123 +0,0 @@
|
|
1
|
-
require "uri"
|
2
|
-
require "pincers/support/cookie_jar"
|
3
|
-
|
4
|
-
module Pincers::Support
|
5
|
-
class HttpClient
|
6
|
-
|
7
|
-
class HttpRequestError < StandardError
|
8
|
-
extend Forwardable
|
9
|
-
|
10
|
-
def_delegators :@response, :code, :body
|
11
|
-
|
12
|
-
attr_reader :response
|
13
|
-
|
14
|
-
def initialize(_response)
|
15
|
-
@response = _response
|
16
|
-
super _response.message
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class MaximumRedirectsError < StandardError
|
21
|
-
def initialize
|
22
|
-
super 'Redirection loop detected!'
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
attr_reader :proxy_addr, :proxy_port, :cookies
|
27
|
-
|
28
|
-
def initialize(_options={})
|
29
|
-
if _options[:proxy]
|
30
|
-
@proxy_addr, @proxy_port = _options[:proxy].split ':'
|
31
|
-
end
|
32
|
-
|
33
|
-
@cookies = if _options[:cookies]
|
34
|
-
_options[:cookies].copy
|
35
|
-
else
|
36
|
-
CookieJar.new
|
37
|
-
end
|
38
|
-
|
39
|
-
@default_headers = _options[:headers]
|
40
|
-
end
|
41
|
-
|
42
|
-
def get(_url, _query={}, _headers={})
|
43
|
-
# TODO: append query string?
|
44
|
-
perform_request Net::HTTP::Get, URI(_url), _headers
|
45
|
-
end
|
46
|
-
|
47
|
-
def post(_url, _data, _headers={})
|
48
|
-
perform_request Net::HTTP::Post, URI(_url), _headers do |req|
|
49
|
-
req.body = prepare_data(_data)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def put(_url, _data, _headers={})
|
54
|
-
perform_request Net::HTTP::Put, URI(_url), _headers do |req|
|
55
|
-
req.body = prepare_data(_data)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def delete(_url)
|
60
|
-
perform_request Net::HTTP::Delete, URI(_url), _headers
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def perform_request(_req_type, _uri, _headers, _limit=10)
|
66
|
-
|
67
|
-
raise MaximumRedirectsError.new if _limit == 0
|
68
|
-
|
69
|
-
request = _req_type.new(_uri.request_uri.empty? ? '/' : _uri.request_uri)
|
70
|
-
build_headers(request, _headers)
|
71
|
-
set_cookies(request, _uri)
|
72
|
-
yield request if block_given?
|
73
|
-
|
74
|
-
response = build_client(_uri).request request
|
75
|
-
|
76
|
-
case response
|
77
|
-
when Net::HTTPSuccess then
|
78
|
-
update_cookies(_uri, response)
|
79
|
-
response
|
80
|
-
when Net::HTTPRedirection then
|
81
|
-
location = response['location']
|
82
|
-
perform_request(_req_type, URI.parse(location), _headers, _limit - 1)
|
83
|
-
else
|
84
|
-
handle_error_response response
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def build_client(uri)
|
89
|
-
client = Net::HTTP.new uri.host, uri.port || 80, proxy_addr, proxy_port
|
90
|
-
client.use_ssl = true if uri.scheme == 'https'
|
91
|
-
client.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
92
|
-
client
|
93
|
-
end
|
94
|
-
|
95
|
-
def handle_error_response(_response)
|
96
|
-
raise HttpRequestError.new _response
|
97
|
-
end
|
98
|
-
|
99
|
-
def prepare_data(_data)
|
100
|
-
if _data.is_a? Hash
|
101
|
-
_data.keys.map { |k| "#{k}=#{_data[k]}" }.join '&'
|
102
|
-
else _data end
|
103
|
-
end
|
104
|
-
|
105
|
-
def build_headers(_request, _headers)
|
106
|
-
copy_headers _request, @default_headers if @default_headers
|
107
|
-
copy_headers _request, _headers
|
108
|
-
end
|
109
|
-
|
110
|
-
def set_cookies(_request, _uri)
|
111
|
-
_request['Cookie'] = @cookies.for_origin_as_header _uri
|
112
|
-
end
|
113
|
-
|
114
|
-
def update_cookies(_uri, _response)
|
115
|
-
cookies = _response.get_fields('set-cookie')
|
116
|
-
cookies.each { |raw| @cookies.set_raw _uri, raw } if cookies
|
117
|
-
end
|
118
|
-
|
119
|
-
def copy_headers(_request, _headers)
|
120
|
-
_headers.keys.each { |k| _request[k] = _headers[k] }
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|