webshooter 0.0.3a → 0.0.4a

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.
data/Gemfile.lock CHANGED
@@ -1,11 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- webshooter (0.0.3a)
4
+ webshooter (0.0.4a)
5
+ nokogiri (~> 1.4.4)
5
6
 
6
7
  GEM
7
8
  remote: http://rubygems.org/
8
9
  specs:
10
+ nokogiri (1.4.4)
9
11
 
10
12
  PLATFORMS
11
13
  ruby
data/README.txt CHANGED
@@ -11,10 +11,10 @@ gem install webshooter --pre
11
11
 
12
12
  ## From within ruby
13
13
  require 'webshooter'
14
- Webshooter.capture('http://www.jedi.be','jedi.png','1024x768')
14
+ Webshooter.capture('http://www.jedi.be',{ :output => 'jedi.png', :width => '1024' , :height => '768' , :delay => '2')
15
15
 
16
16
  ## As a commandline tool
17
- webshooter 'http://www.jedi.be' 'jedi.png' '1024x768'
17
+ webshooter 'http://www.jedi.be' --width=1024 --height=786 --delay=2 --output=jedi.png
18
18
 
19
19
  # Limitations
20
20
  - does not handle redirects currently
@@ -27,6 +27,10 @@ webshooter 'http://www.jedi.be' 'jedi.png' '1024x768'
27
27
  This library is a compilation of various parts I found on the web
28
28
  The research was done a few years ago, so unfortunatly I don't have all the references anymore
29
29
 
30
+ - webkit2png - http://www.paulhammond.org/webkit2png/
31
+ - http://cocoadevblog.com/webkit-screenshots-cocoa-objective-c
32
+
33
+
30
34
  - Darkroom - Copyright (c) 2007 Justin Palmer.
31
35
  - https://gist.github.com/34824
32
36
  - https://gist.github.com/86435
data/bin/webshooter ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ require 'rubygems'
5
+ require 'webshooter'
6
+ require 'optparse'
7
+
8
+ module Webshooter
9
+ class CLI
10
+ #Ruby CLI tool - http://rubylearning.com/blog/2011/01/03/how-do-i-make-a-command-line-tool-in-ruby/
11
+ def self.execute(url,options)
12
+ webshotr=Webshooter.capture(url,options)
13
+ end
14
+ end
15
+ end
16
+
17
+ options = {}
18
+ parser = OptionParser.new do |opts|
19
+ opts.banner = "Usage: #$0 [options] URL"
20
+
21
+ opts.on('--width=[WIDTH]', Integer, 'Force width of the screenshot') do |v|
22
+ options[:width] = v
23
+ end
24
+
25
+ opts.on('--delay=[DELAY]', Integer, "Delay") do |v|
26
+ options[:delay] = v
27
+ end
28
+
29
+ opts.on('--height=[HEIGHT]', Integer, 'Force height of screenshot') do |v|
30
+ options[:height] = v
31
+ end
32
+
33
+ opts.on('--output=[FILENAME]', String, 'Specify filename for saving') do |v|
34
+ options[:output] = v
35
+ end
36
+
37
+ opts.on_tail('--help', 'Display this message and exit') do
38
+ puts opts
39
+ exit
40
+ end
41
+
42
+ opts.on_tail('-v', "--version", "Show version") do
43
+ puts "webshooter v"+Webshooter::VERSION
44
+ exit
45
+ end
46
+
47
+ opts.parse!(ARGV)
48
+
49
+ end
50
+
51
+ if ARGV.size < 1
52
+ puts "You need to specify the URL as a minimum"
53
+ else
54
+ uri=ARGV.first
55
+ if (uri =~ URI::regexp).nil?
56
+ puts "You specified an invalid URL"
57
+ else
58
+ Webshooter::CLI.execute(uri, options)
59
+ end
60
+
61
+ end
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'net/http'
5
5
  require 'net/https'
6
+ require 'nokogiri'
6
7
 
7
8
  module Webshooter
8
9
 
@@ -27,11 +28,16 @@ class RedirectFollower
27
28
  #http.verify_mode = OpenSSL::SSL::VERIFY_NONE # Not setting this explicitly will result in an error and the value being set anyway
28
29
  end
29
30
 
31
+
30
32
  if (uri.path=="")
31
- request = Net::HTTP::Get.new("/")
33
+ request = Net::HTTP::Get.new("#{ '/' + (uri.query ? ('?' + uri.query) : '')}")
32
34
  else
33
- request = Net::HTTP::Get.new(uri.path)
35
+
36
+ # http://intertwingly.net/blog/2006/08/19/Quack-Squared
37
+ request = Net::HTTP::Get.new(uri.path + (uri.query ? ('?' + uri.query) : '') )
34
38
  end
39
+
40
+
35
41
  self.response = http.start {|http| http.request(request) }
36
42
 
37
43
  if response.kind_of?(Net::HTTPRedirection)
@@ -40,11 +46,34 @@ class RedirectFollower
40
46
 
41
47
  puts "redirect found, headed to #{url}"
42
48
  resolve
43
- end
49
+ end
50
+
51
+ meta_link=meta_parse
52
+ if !meta_link.nil?
53
+ self.url = meta_link
54
+ self.redirect_limit -= 1
55
+ puts "metalink found, headed to #{url}"
56
+ resolve
57
+ end
58
+
44
59
  return url
45
60
 
46
61
  end
47
62
 
63
+ def meta_parse
64
+ # http://stackoverflow.com/questions/5003367/mechanize-how-to-follow-or-click-meta-refreshes-in-rails/5012684#5012684
65
+ html=response.body.to_s.downcase
66
+ #puts html
67
+ doc = Nokogiri::HTML(html)
68
+ meta_tag=doc.at('meta[http-equiv="refresh"]')
69
+ if !meta_tag.nil?
70
+ meta_link = meta_tag['content'][/url=(.+)/, 1]
71
+ else
72
+ meta_link=nil
73
+ end
74
+ meta_link # => "http://www.example.com/"
75
+ end
76
+
48
77
  def redirect_url
49
78
  if response['location'].nil?
50
79
  response.body.match(/<a href=\"([^>]+)\">/i)[1]
@@ -1,3 +1,3 @@
1
1
  module Webshooter
2
- VERSION = "0.0.3a"
2
+ VERSION = "0.0.4a"
3
3
  end
@@ -41,7 +41,7 @@ class WebShotProcessor
41
41
  @webView.preferences.setAutosaves(false)
42
42
  # Set some useful options.
43
43
  @webView.preferences.setShouldPrintBackgrounds(true)
44
- @webView.preferences.setJavaScriptCanOpenWindowsAutomatically(false)
44
+ @webView.preferences.setJavaScriptCanOpenWindowsAutomatically(true)
45
45
  @webView.preferences.setAllowsAnimatedImages(false)
46
46
  # Make sure we don't get a scroll bar.
47
47
  @webView.mainFrame.frameView.setAllowsScrolling(false)
@@ -49,6 +49,7 @@ class WebShotProcessor
49
49
  # This @delegate will get a message when the load completes
50
50
  @delegate = SimpleLoadDelegate.alloc.init
51
51
  @delegate.webshooter = self
52
+
52
53
  @webView.setFrameLoadDelegate(@delegate)
53
54
 
54
55
  # Replace the window's content @webView with the web @webView
@@ -56,15 +57,23 @@ class WebShotProcessor
56
57
  @webView.release
57
58
  end
58
59
 
59
- def capture(uri, path, dimensions = "1024x768" )
60
+ def capture(uri, options )
61
+
62
+ options[:width] ||= 1024
63
+ options[:height] ||= 768
64
+ options[:output] ||= "webshot.png"
65
+ options[:delay] ||= 2
60
66
 
61
- snapshot_dimension=dimensions.split('x')
67
+ @delegate.options = options
68
+
69
+ snapshot_dimension=[ options[:width] , options[:height]]
62
70
  # Tell the frame to load the URL we want
63
71
  @webView.window.setContentSize(snapshot_dimension)
64
72
  @webView.setFrameSize(snapshot_dimension)
65
73
 
66
74
  final_link = RedirectFollower.new(uri).resolve
67
75
 
76
+ #puts "final link = #{final_link}"
68
77
  myURI = URI.parse(final_link)
69
78
 
70
79
  #Allow all https certificates
@@ -73,8 +82,6 @@ class WebShotProcessor
73
82
  #puts "Getting ready for the loadRequest"+uri
74
83
  @webView.mainFrame.loadRequest(NewNSURLRequest.requestWithURL(OSX::NSURL.URLWithString(final_link)))
75
84
 
76
- #Wait for some pages to terminate
77
- sleep 2
78
85
  #
79
86
  # Run the main event loop until the frame loads
80
87
  @timeout=false
@@ -93,7 +100,6 @@ class WebShotProcessor
93
100
  view.window.orderFront(nil)
94
101
  #view.window.display
95
102
 
96
- #puts "-------------------------------------------------"
97
103
  #puts "We got success"
98
104
  @docview=view.mainFrame.frameView.documentView
99
105
 
@@ -125,7 +131,8 @@ class WebShotProcessor
125
131
  if view.bounds.size.height < 300000
126
132
  view.lockFocus
127
133
  bitmap = OSX::NSBitmapImageRep.alloc.initWithFocusedViewRect(view.bounds)
128
- bitmap.representationUsingType_properties(OSX::NSPNGFileType, nil).writeToFile_atomically(path, true)
134
+ bitmap.representationUsingType_properties(OSX::NSPNGFileType, nil).writeToFile_atomically(options[:output], true)
135
+ logger.info( "Webshot for #{final_link} => '#{options[:output]}' ")
129
136
  bitmap.release
130
137
  view.unlockFocus
131
138
 
@@ -136,7 +143,7 @@ class WebShotProcessor
136
143
  end
137
144
 
138
145
  upon_failure do |error, logger|
139
- logger.warn("Unable to load URI: #{uri} (#{error})")
146
+ logger.warn("Unable to load URI: #{final_link} (#{error})")
140
147
  end
141
148
 
142
149
 
@@ -166,7 +173,7 @@ class WebShotProcessor
166
173
 
167
174
  class SimpleLoadDelegate < OSX::NSObject
168
175
 
169
- attr_accessor :webshooter
176
+ attr_accessor :webshooter, :options
170
177
 
171
178
  def stopLoop
172
179
  mainLoop=OSX.CFRunLoopGetMain
@@ -176,10 +183,15 @@ class WebShotProcessor
176
183
  end
177
184
 
178
185
  def webView_didFinishLoadForFrame(sender, frame)
186
+
179
187
  #This did the trick, we have to wait for the right frame to load, not other frames
180
188
  if (frame == sender.mainFrame)
181
189
  then
182
190
  #puts "Finish Load For Frame"
191
+ #sleep 10
192
+ #puts "#{ @options[:delay]}"
193
+ sleep @options[:delay]
194
+ #puts "we got a finish"
183
195
  @webshooter.load_success = true;
184
196
 
185
197
  stopLoop
@@ -189,8 +201,15 @@ class WebShotProcessor
189
201
  end
190
202
  end
191
203
 
204
+ # keeping track of all content being loaded
205
+ # http://www.opensubscriber.com/message/webkitsdk-dev@lists.apple.com/2978556.html
206
+ def webView_didCommitLoadForFrame(sender,frame)
207
+ #puts "we got a commit"
208
+ end
209
+
192
210
  def webView_didFailLoadWithError_forFrame(webview, load_error, frame)
193
211
 
212
+ #puts "we got a failed"
194
213
  #This is trick # 2
195
214
  #We have to catch this stupid error
196
215
  if (load_error.code == OSX::NSURLErrorCancelled)
@@ -208,6 +227,7 @@ class WebShotProcessor
208
227
  end
209
228
 
210
229
  def webView_didFailProvisionalLoadWithError_forFrame(webview, load_error, frame)
230
+ puts "we got a provisional load"
211
231
  if (load_error.code == OSX::NSURLErrorCancelled)
212
232
  then
213
233
  #pp "WARN: did Fail PROVISIONAL LOAD WITH ERROR For Frame"
data/lib/webshooter.rb CHANGED
@@ -5,9 +5,9 @@ require 'webshooter/webshotprocessor'
5
5
 
6
6
  module Webshooter
7
7
  class Webshooter
8
- def self.capture(uri, path, dimensions = "1024x768" )
8
+ def self.capture(uri, options )
9
9
  webProcessor=WebShotProcessor.new
10
- webProcessor.capture(uri,path,dimensions)
10
+ webProcessor.capture(uri,options)
11
11
  end
12
12
  end
13
13
  end
data/webshooter.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.add_development_dependency "bundler", ">= 1.0.0"
18
18
  #s.add_dependency "responsalizr", "~>1.0.2"
19
+ s.add_dependency "nokogiri", "~>1.4.4"
19
20
 
20
21
  s.files = `git ls-files`.split("\n")
21
22
  s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
metadata CHANGED
@@ -1,12 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webshooter
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ hash: 58
5
+ prerelease: 5
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 3a
9
- version: 0.0.3a
9
+ - 4
10
+ - a
11
+ version: 0.0.4a
10
12
  platform: ruby
11
13
  authors:
12
14
  - Patrick Debois
@@ -18,24 +20,42 @@ date: 2011-02-20 00:00:00 +01:00
18
20
  default_executable:
19
21
  dependencies:
20
22
  - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ type: :development
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
22
27
  requirements:
23
28
  - - ">="
24
29
  - !ruby/object:Gem::Version
30
+ hash: 23
25
31
  segments:
26
32
  - 1
27
33
  - 0
28
34
  - 0
29
35
  version: 1.0.0
30
- requirement: *id001
31
36
  name: bundler
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
32
39
  prerelease: false
33
- type: :development
40
+ type: :runtime
41
+ requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ hash: 15
47
+ segments:
48
+ - 1
49
+ - 4
50
+ - 4
51
+ version: 1.4.4
52
+ name: nokogiri
53
+ version_requirements: *id002
34
54
  description: This library allows you to create webshots using webkit on MacOSX. A webshot is a screenshot taken inside the browser. The advantage of this library is that it is headless and gives you the real view not a parsed view
35
55
  email:
36
56
  - patrick.debois@jedi.be
37
57
  executables:
38
- - webshooter.rb
58
+ - webshooter
39
59
  extensions: []
40
60
 
41
61
  extra_rdoc_files: []
@@ -46,7 +66,7 @@ files:
46
66
  - Gemfile.lock
47
67
  - README.txt
48
68
  - Rakefile
49
- - bin/webshooter.rb
69
+ - bin/webshooter
50
70
  - lib/webshooter.rb
51
71
  - lib/webshooter/newnsurlrequest.rb
52
72
  - lib/webshooter/redirectfollower.rb
@@ -68,16 +88,20 @@ rdoc_options: []
68
88
  require_paths:
69
89
  - lib
70
90
  required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
71
92
  requirements:
72
93
  - - ">="
73
94
  - !ruby/object:Gem::Version
95
+ hash: 3
74
96
  segments:
75
97
  - 0
76
98
  version: "0"
77
99
  required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
78
101
  requirements:
79
102
  - - ">="
80
103
  - !ruby/object:Gem::Version
104
+ hash: 23
81
105
  segments:
82
106
  - 1
83
107
  - 3
@@ -86,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
110
  requirements: []
87
111
 
88
112
  rubyforge_project: webshooter
89
- rubygems_version: 1.3.6
113
+ rubygems_version: 1.5.2
90
114
  signing_key:
91
115
  specification_version: 3
92
116
  summary: Create webshot using webkit on MacOSX
data/bin/webshooter.rb DELETED
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
-
4
- require 'rubygems'
5
- require 'webshooter'
6
-
7
- module Webshooter
8
- class CLI
9
- #Ruby CLI tool - http://rubylearning.com/blog/2011/01/03/how-do-i-make-a-command-line-tool-in-ruby/
10
- def self.execute(args)
11
- url=args[0]
12
- filename=args[1]
13
- size=args[2]
14
- webshotr=Webshooter.capture(url, filename, size )
15
- end
16
- end
17
- end
18
-
19
- Webshooter::CLI.execute(ARGV)