webshooter 0.0.3a → 0.0.4a

Sign up to get free protection for your applications and to get access to all the features.
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)