link_finder 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/link_finder +7 -0
- data/install.sh +3 -0
- data/lib/link_finder/version.rb +3 -0
- data/lib/link_finder.glade +283 -0
- data/lib/link_finder.rb +277 -0
- data/link_finder.gemspec +19 -0
- metadata +57 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# LinkFinder
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'link_finder'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install link_finder
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/link_finder
ADDED
data/install.sh
ADDED
@@ -0,0 +1,283 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<interface>
|
3
|
+
<requires lib="gtk+" version="2.24"/>
|
4
|
+
<!-- interface-naming-policy project-wide -->
|
5
|
+
<object class="GtkAdjustment" id="adj_recurse">
|
6
|
+
<property name="lower">2</property>
|
7
|
+
<property name="upper">10</property>
|
8
|
+
<property name="value">2</property>
|
9
|
+
<property name="step_increment">1</property>
|
10
|
+
<property name="page_increment">1</property>
|
11
|
+
</object>
|
12
|
+
<object class="GtkAdjustment" id="adj_threads">
|
13
|
+
<property name="lower">1</property>
|
14
|
+
<property name="upper">300</property>
|
15
|
+
<property name="value">10</property>
|
16
|
+
<property name="step_increment">1</property>
|
17
|
+
<property name="page_increment">10</property>
|
18
|
+
</object>
|
19
|
+
<object class="GtkWindow" id="wnd_main">
|
20
|
+
<property name="can_focus">False</property>
|
21
|
+
<property name="border_width">14</property>
|
22
|
+
<property name="window_position">center</property>
|
23
|
+
<property name="default_width">700</property>
|
24
|
+
<property name="default_height">480</property>
|
25
|
+
<signal name="destroy" handler="on_wnd_main_destroy" swapped="no"/>
|
26
|
+
<signal name="delete-event" handler="on_wnd_main_delete_event" swapped="no"/>
|
27
|
+
<child>
|
28
|
+
<object class="GtkVBox" id="vbox1">
|
29
|
+
<property name="visible">True</property>
|
30
|
+
<property name="can_focus">False</property>
|
31
|
+
<child>
|
32
|
+
<object class="GtkHBox" id="hbox1">
|
33
|
+
<property name="visible">True</property>
|
34
|
+
<property name="can_focus">False</property>
|
35
|
+
<child>
|
36
|
+
<object class="GtkVBox" id="vbox2">
|
37
|
+
<property name="visible">True</property>
|
38
|
+
<property name="can_focus">False</property>
|
39
|
+
<child>
|
40
|
+
<object class="GtkHBox" id="hbox3">
|
41
|
+
<property name="visible">True</property>
|
42
|
+
<property name="can_focus">False</property>
|
43
|
+
<child>
|
44
|
+
<object class="GtkLabel" id="label1">
|
45
|
+
<property name="visible">True</property>
|
46
|
+
<property name="can_focus">False</property>
|
47
|
+
<property name="label" translatable="yes">Список ссылок:</property>
|
48
|
+
</object>
|
49
|
+
<packing>
|
50
|
+
<property name="expand">False</property>
|
51
|
+
<property name="fill">True</property>
|
52
|
+
<property name="position">0</property>
|
53
|
+
</packing>
|
54
|
+
</child>
|
55
|
+
<child>
|
56
|
+
<object class="GtkFileChooserButton" id="fcb_links">
|
57
|
+
<property name="visible">True</property>
|
58
|
+
<property name="can_focus">False</property>
|
59
|
+
<signal name="file-set" handler="on_fcb_links_file_set" swapped="no"/>
|
60
|
+
</object>
|
61
|
+
<packing>
|
62
|
+
<property name="expand">True</property>
|
63
|
+
<property name="fill">True</property>
|
64
|
+
<property name="padding">4</property>
|
65
|
+
<property name="position">1</property>
|
66
|
+
</packing>
|
67
|
+
</child>
|
68
|
+
</object>
|
69
|
+
<packing>
|
70
|
+
<property name="expand">True</property>
|
71
|
+
<property name="fill">True</property>
|
72
|
+
<property name="position">0</property>
|
73
|
+
</packing>
|
74
|
+
</child>
|
75
|
+
</object>
|
76
|
+
<packing>
|
77
|
+
<property name="expand">True</property>
|
78
|
+
<property name="fill">True</property>
|
79
|
+
<property name="position">0</property>
|
80
|
+
</packing>
|
81
|
+
</child>
|
82
|
+
<child>
|
83
|
+
<object class="GtkVBox" id="vbox3">
|
84
|
+
<property name="visible">True</property>
|
85
|
+
<property name="can_focus">False</property>
|
86
|
+
<child>
|
87
|
+
<object class="GtkHBox" id="hbox4">
|
88
|
+
<property name="visible">True</property>
|
89
|
+
<property name="can_focus">False</property>
|
90
|
+
<child>
|
91
|
+
<object class="GtkLabel" id="label2">
|
92
|
+
<property name="visible">True</property>
|
93
|
+
<property name="can_focus">False</property>
|
94
|
+
<property name="label" translatable="yes">Список сайтов:</property>
|
95
|
+
</object>
|
96
|
+
<packing>
|
97
|
+
<property name="expand">False</property>
|
98
|
+
<property name="fill">True</property>
|
99
|
+
<property name="position">0</property>
|
100
|
+
</packing>
|
101
|
+
</child>
|
102
|
+
<child>
|
103
|
+
<object class="GtkFileChooserButton" id="fcb_sites">
|
104
|
+
<property name="visible">True</property>
|
105
|
+
<property name="can_focus">False</property>
|
106
|
+
<signal name="file-set" handler="on_fcb_sites_file_set" swapped="no"/>
|
107
|
+
</object>
|
108
|
+
<packing>
|
109
|
+
<property name="expand">True</property>
|
110
|
+
<property name="fill">True</property>
|
111
|
+
<property name="padding">4</property>
|
112
|
+
<property name="position">1</property>
|
113
|
+
</packing>
|
114
|
+
</child>
|
115
|
+
</object>
|
116
|
+
<packing>
|
117
|
+
<property name="expand">True</property>
|
118
|
+
<property name="fill">True</property>
|
119
|
+
<property name="position">0</property>
|
120
|
+
</packing>
|
121
|
+
</child>
|
122
|
+
</object>
|
123
|
+
<packing>
|
124
|
+
<property name="expand">True</property>
|
125
|
+
<property name="fill">True</property>
|
126
|
+
<property name="position">1</property>
|
127
|
+
</packing>
|
128
|
+
</child>
|
129
|
+
</object>
|
130
|
+
<packing>
|
131
|
+
<property name="expand">False</property>
|
132
|
+
<property name="fill">True</property>
|
133
|
+
<property name="position">0</property>
|
134
|
+
</packing>
|
135
|
+
</child>
|
136
|
+
<child>
|
137
|
+
<object class="GtkHSeparator" id="hseparator1">
|
138
|
+
<property name="height_request">8</property>
|
139
|
+
<property name="visible">True</property>
|
140
|
+
<property name="can_focus">False</property>
|
141
|
+
</object>
|
142
|
+
<packing>
|
143
|
+
<property name="expand">False</property>
|
144
|
+
<property name="fill">True</property>
|
145
|
+
<property name="padding">4</property>
|
146
|
+
<property name="position">1</property>
|
147
|
+
</packing>
|
148
|
+
</child>
|
149
|
+
<child>
|
150
|
+
<object class="GtkHBox" id="hbox2">
|
151
|
+
<property name="visible">True</property>
|
152
|
+
<property name="can_focus">False</property>
|
153
|
+
<child>
|
154
|
+
<object class="GtkLabel" id="label4">
|
155
|
+
<property name="visible">True</property>
|
156
|
+
<property name="can_focus">False</property>
|
157
|
+
<property name="label" translatable="yes">Рекурсия:</property>
|
158
|
+
</object>
|
159
|
+
<packing>
|
160
|
+
<property name="expand">False</property>
|
161
|
+
<property name="fill">True</property>
|
162
|
+
<property name="padding">4</property>
|
163
|
+
<property name="position">0</property>
|
164
|
+
</packing>
|
165
|
+
</child>
|
166
|
+
<child>
|
167
|
+
<object class="GtkSpinButton" id="sb_recurse">
|
168
|
+
<property name="visible">True</property>
|
169
|
+
<property name="can_focus">True</property>
|
170
|
+
<property name="invisible_char">•</property>
|
171
|
+
<property name="primary_icon_activatable">False</property>
|
172
|
+
<property name="secondary_icon_activatable">False</property>
|
173
|
+
<property name="primary_icon_sensitive">True</property>
|
174
|
+
<property name="secondary_icon_sensitive">True</property>
|
175
|
+
<property name="adjustment">adj_recurse</property>
|
176
|
+
</object>
|
177
|
+
<packing>
|
178
|
+
<property name="expand">False</property>
|
179
|
+
<property name="fill">True</property>
|
180
|
+
<property name="padding">4</property>
|
181
|
+
<property name="position">1</property>
|
182
|
+
</packing>
|
183
|
+
</child>
|
184
|
+
<child>
|
185
|
+
<object class="GtkLabel" id="label3">
|
186
|
+
<property name="visible">True</property>
|
187
|
+
<property name="can_focus">False</property>
|
188
|
+
<property name="label" translatable="yes">Потоков:</property>
|
189
|
+
</object>
|
190
|
+
<packing>
|
191
|
+
<property name="expand">False</property>
|
192
|
+
<property name="fill">True</property>
|
193
|
+
<property name="padding">4</property>
|
194
|
+
<property name="position">2</property>
|
195
|
+
</packing>
|
196
|
+
</child>
|
197
|
+
<child>
|
198
|
+
<object class="GtkSpinButton" id="sb_threads">
|
199
|
+
<property name="visible">True</property>
|
200
|
+
<property name="sensitive">False</property>
|
201
|
+
<property name="can_focus">True</property>
|
202
|
+
<property name="invisible_char">•</property>
|
203
|
+
<property name="primary_icon_activatable">False</property>
|
204
|
+
<property name="secondary_icon_activatable">False</property>
|
205
|
+
<property name="primary_icon_sensitive">True</property>
|
206
|
+
<property name="secondary_icon_sensitive">True</property>
|
207
|
+
<property name="adjustment">adj_threads</property>
|
208
|
+
<property name="numeric">True</property>
|
209
|
+
<signal name="value-changed" handler="on_sb_threads_value_changed" swapped="no"/>
|
210
|
+
</object>
|
211
|
+
<packing>
|
212
|
+
<property name="expand">False</property>
|
213
|
+
<property name="fill">True</property>
|
214
|
+
<property name="padding">5</property>
|
215
|
+
<property name="position">3</property>
|
216
|
+
</packing>
|
217
|
+
</child>
|
218
|
+
<child>
|
219
|
+
<object class="GtkToggleButton" id="tbtn_startstop">
|
220
|
+
<property name="label" translatable="yes">Старт / Стоп</property>
|
221
|
+
<property name="visible">True</property>
|
222
|
+
<property name="sensitive">False</property>
|
223
|
+
<property name="can_focus">True</property>
|
224
|
+
<property name="receives_default">True</property>
|
225
|
+
<property name="use_action_appearance">False</property>
|
226
|
+
<signal name="toggled" handler="on_tbtn_startstop_toggled" swapped="no"/>
|
227
|
+
</object>
|
228
|
+
<packing>
|
229
|
+
<property name="expand">False</property>
|
230
|
+
<property name="fill">True</property>
|
231
|
+
<property name="padding">4</property>
|
232
|
+
<property name="position">4</property>
|
233
|
+
</packing>
|
234
|
+
</child>
|
235
|
+
<child>
|
236
|
+
<object class="GtkProgressBar" id="pb_progress">
|
237
|
+
<property name="visible">True</property>
|
238
|
+
<property name="can_focus">False</property>
|
239
|
+
</object>
|
240
|
+
<packing>
|
241
|
+
<property name="expand">True</property>
|
242
|
+
<property name="fill">True</property>
|
243
|
+
<property name="padding">4</property>
|
244
|
+
<property name="position">5</property>
|
245
|
+
</packing>
|
246
|
+
</child>
|
247
|
+
</object>
|
248
|
+
<packing>
|
249
|
+
<property name="expand">False</property>
|
250
|
+
<property name="fill">True</property>
|
251
|
+
<property name="position">2</property>
|
252
|
+
</packing>
|
253
|
+
</child>
|
254
|
+
<child>
|
255
|
+
<object class="GtkHSeparator" id="hseparator2">
|
256
|
+
<property name="height_request">8</property>
|
257
|
+
<property name="visible">True</property>
|
258
|
+
<property name="can_focus">False</property>
|
259
|
+
</object>
|
260
|
+
<packing>
|
261
|
+
<property name="expand">False</property>
|
262
|
+
<property name="fill">True</property>
|
263
|
+
<property name="padding">4</property>
|
264
|
+
<property name="position">3</property>
|
265
|
+
</packing>
|
266
|
+
</child>
|
267
|
+
<child>
|
268
|
+
<object class="GtkImage" id="img_diagram">
|
269
|
+
<property name="visible">True</property>
|
270
|
+
<property name="can_focus">False</property>
|
271
|
+
<property name="stock">gtk-missing-image</property>
|
272
|
+
</object>
|
273
|
+
<packing>
|
274
|
+
<property name="expand">True</property>
|
275
|
+
<property name="fill">True</property>
|
276
|
+
<property name="padding">4</property>
|
277
|
+
<property name="position">4</property>
|
278
|
+
</packing>
|
279
|
+
</child>
|
280
|
+
</object>
|
281
|
+
</child>
|
282
|
+
</object>
|
283
|
+
</interface>
|
data/lib/link_finder.rb
ADDED
@@ -0,0 +1,277 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "link_finder/version"
|
3
|
+
require "gtk2"
|
4
|
+
require "nokogiri"
|
5
|
+
require "open-uri"
|
6
|
+
require "timeout"
|
7
|
+
require "thread"
|
8
|
+
require "gruff"
|
9
|
+
|
10
|
+
module LinkFinder
|
11
|
+
class Finder
|
12
|
+
def initialize
|
13
|
+
trap("SIGINT") { exit! }
|
14
|
+
@mutex = Mutex.new
|
15
|
+
|
16
|
+
Gtk.init
|
17
|
+
builder = Gtk::Builder.new
|
18
|
+
builder.add_from_file(File.join(File.dirname(__FILE__), 'link_finder.glade'))
|
19
|
+
builder.connect_signals {|handler| method(handler) }
|
20
|
+
|
21
|
+
@wnd_main = builder.get_object('wnd_main')
|
22
|
+
@fcb_links = builder.get_object('fcb_links')
|
23
|
+
@fcb_sites = builder.get_object('fcb_sites')
|
24
|
+
@tbtn_startstop = builder.get_object('tbtn_startstop')
|
25
|
+
@sb_threads = builder.get_object('sb_threads')
|
26
|
+
@adj_threads = builder.get_object('adj_threads')
|
27
|
+
@sb_recurse = builder.get_object('sb_recurse')
|
28
|
+
@adj_recurse = builder.get_object('adj_recurse')
|
29
|
+
@pb_progress = builder.get_object('pb_progress')
|
30
|
+
@img_diagram = builder.get_object('img_diagram')
|
31
|
+
|
32
|
+
@options = {}
|
33
|
+
begin
|
34
|
+
@options = File.open(File.join(File.dirname(__FILE__), "options.dat"), "rb") {|f| Marshal.load(f)}
|
35
|
+
rescue Exception => e
|
36
|
+
puts e
|
37
|
+
end
|
38
|
+
|
39
|
+
@fcb_links.filename = @options[:links_filename] unless @options[:links_filename].nil?
|
40
|
+
@fcb_sites.filename = @options[:sites_filename] unless @options[:sites_filename].nil?
|
41
|
+
@options[:threads] = 5 if @options[:threads].nil?
|
42
|
+
@adj_threads.value = @options[:threads]
|
43
|
+
@options[:recurse] = 2 if @options[:recurse].nil?
|
44
|
+
@adj_recurse.value = @options[:recurse]
|
45
|
+
|
46
|
+
sensitive_state
|
47
|
+
|
48
|
+
@wnd_main.show
|
49
|
+
Gtk.main
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_wnd_main_destroy
|
53
|
+
gtk_main_quit
|
54
|
+
end
|
55
|
+
|
56
|
+
def gtk_main_quit
|
57
|
+
@browser.close unless @browser.nil?
|
58
|
+
Gtk.main_quit()
|
59
|
+
end
|
60
|
+
|
61
|
+
def on_wnd_main_delete_event(widget, event)
|
62
|
+
begin
|
63
|
+
File.open(File.join(File.dirname(__FILE__), "options.dat"), "wb") {|f| Marshal.dump(@options, f)}
|
64
|
+
rescue Exception => e
|
65
|
+
puts e
|
66
|
+
end
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
|
70
|
+
def on_fcb_links_file_set(widget)
|
71
|
+
@options[:links_filename] = widget.filename
|
72
|
+
sensitive_state
|
73
|
+
end
|
74
|
+
|
75
|
+
def on_fcb_sites_file_set(widget)
|
76
|
+
@options[:sites_filename] = widget.filename
|
77
|
+
sensitive_state
|
78
|
+
end
|
79
|
+
|
80
|
+
def on_sb_threads_value_changed(widget)
|
81
|
+
@options[:threads] = @adj_threads.value
|
82
|
+
end
|
83
|
+
|
84
|
+
def on_sb_recurse_value_changed(widget)
|
85
|
+
@options[:recurse] = @adj_recurse.value
|
86
|
+
end
|
87
|
+
|
88
|
+
def on_tbtn_startstop_toggled(widget)
|
89
|
+
if widget.active?
|
90
|
+
start_process
|
91
|
+
else
|
92
|
+
stop_process
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def sensitive_state
|
97
|
+
result = (!@options[:links_filename].nil? and !@options[:sites_filename].nil?)
|
98
|
+
@tbtn_startstop.sensitive = result
|
99
|
+
@sb_threads.sensitive = result
|
100
|
+
@sb_recurse.sensitive = result
|
101
|
+
end
|
102
|
+
|
103
|
+
def progress_reset
|
104
|
+
@pb_progress.text = " "
|
105
|
+
@pb_progress.fraction = 0
|
106
|
+
end
|
107
|
+
|
108
|
+
def progress_set(max, value)
|
109
|
+
perc = value * 100 / max
|
110
|
+
@pb_progress.text = "#{value} из #{max}"
|
111
|
+
@pb_progress.fraction = perc * 0.01
|
112
|
+
Gtk::main_iteration_do(blocking = false) while Gtk::events_pending?
|
113
|
+
end
|
114
|
+
|
115
|
+
def dia_refresh
|
116
|
+
pixbuf = Gdk::Pixbuf.new("/home/chemt79/result.png", 700, 520)
|
117
|
+
@img_diagram.pixbuf = pixbuf
|
118
|
+
Gtk::main_iteration_do(blocking = false) while Gtk::events_pending?
|
119
|
+
end
|
120
|
+
|
121
|
+
def start_process
|
122
|
+
progress_reset
|
123
|
+
@progress_value = 0
|
124
|
+
|
125
|
+
@fcb_links.sensitive =
|
126
|
+
@fcb_sites.sensitive =
|
127
|
+
@sb_threads.sensitive =
|
128
|
+
@sb_recurse.sensitive = false
|
129
|
+
|
130
|
+
@threads = []
|
131
|
+
@result = []
|
132
|
+
@main_thread = Thread.new do
|
133
|
+
@links = File.open(@options[:links_filename], "rb:UTF-8").read.split("\n").map do |l|
|
134
|
+
begin
|
135
|
+
URI.parse(l.gsub(/[\n\r]/, '')).to_s
|
136
|
+
rescue Exception => e
|
137
|
+
puts e
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
@sites = File.open(@options[:sites_filename], "rb:UTF-8").read.split(/\n/).map do |s|
|
142
|
+
begin
|
143
|
+
uri = URI.parse(s.gsub(/[\n\r]/, ''))
|
144
|
+
URI::HTTP.new('http', nil, uri.host, nil, nil, nil, nil, nil, nil).to_s
|
145
|
+
rescue Exception => e
|
146
|
+
puts e
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
section = 0
|
151
|
+
@sites.each_index do |index|
|
152
|
+
site = @sites[index]
|
153
|
+
|
154
|
+
sleep 0.1 while (Thread.list.length() - 1 > @options[:threads])
|
155
|
+
@threads << Thread.new(site, @links, @options[:recurse]) do |site, links, recurse|
|
156
|
+
r = []
|
157
|
+
recurse_select_refs(site, site, links.clone, r, recurse)
|
158
|
+
@mutex.synchronize do
|
159
|
+
r.each { |t| @result << t }
|
160
|
+
@progress_value += 1
|
161
|
+
progress_set(@sites.length, @progress_value)
|
162
|
+
|
163
|
+
if @progress_value >= section
|
164
|
+
section += @sites.length / 100
|
165
|
+
dia_data = []
|
166
|
+
@links.each do |l|
|
167
|
+
c = 0
|
168
|
+
@result.each { |r| c += 1 if r[:link] == l }
|
169
|
+
dia_data << {:link => l, :count => c}
|
170
|
+
end
|
171
|
+
dia = Gruff::Bar.new
|
172
|
+
dia.title = "Отчет"
|
173
|
+
dia_data.each { |d| dia.data(d[:link], d[:count]) }
|
174
|
+
dia.write("/home/chemt79/result.png")
|
175
|
+
dia_refresh
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
break if index >= 10
|
181
|
+
end
|
182
|
+
@threads.each {|t| t.join}
|
183
|
+
|
184
|
+
dia_data = []
|
185
|
+
File.open("/home/chemt79/result.txt", "wb:UTF-8") do |f|
|
186
|
+
f.write Time.now.to_s + "\n"
|
187
|
+
all = @sites.length
|
188
|
+
@result.each do |r|
|
189
|
+
url = URI.parse(r[:page])
|
190
|
+
url = URI::HTTP.new('http', nil, url.host, nil, nil, nil, nil, nil, nil).to_s
|
191
|
+
index = @sites.index(url)
|
192
|
+
@sites.delete_at(index) unless index.nil?
|
193
|
+
end
|
194
|
+
no = @sites.length
|
195
|
+
yes = all - no
|
196
|
+
|
197
|
+
f.write "Обработано сайтов #{all}\n"
|
198
|
+
f.write "Ссылки найдены на #{yes} сайтах\n"
|
199
|
+
f.write "Ссылки не обнаружены на #{no} сайтах\n"
|
200
|
+
f.write "Эффективность размещения #{(yes.to_f * 100 / all.to_f).round(2).to_s}%\n"
|
201
|
+
|
202
|
+
f.write "\n\nНайденные ссылки:\n"
|
203
|
+
f.write "-----------------------\n"
|
204
|
+
|
205
|
+
@links.each do |l|
|
206
|
+
f.write "#{l}:\n---\n"
|
207
|
+
c = 0
|
208
|
+
@result.each do |r|
|
209
|
+
if r[:link] == l
|
210
|
+
c += 1
|
211
|
+
f.write "#{r[:page]}\n"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
dia_data << {:link => l, :count => c}
|
215
|
+
end
|
216
|
+
|
217
|
+
f.write "\n\nНе найденные ссылки:\n"
|
218
|
+
f.write "-----------------------\n"
|
219
|
+
@sites.each do |s|
|
220
|
+
f.write "#{s}\n"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
dia = Gruff::Bar.new
|
224
|
+
dia.title = "Отчет"
|
225
|
+
dia_data.each { |d| dia.data(d[:link], d[:count]) }
|
226
|
+
dia.write("/home/chemt79/result.png")
|
227
|
+
dia_refresh
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def stop_process
|
232
|
+
@main_thread.kill unless @main_thread.nil?
|
233
|
+
@threads.each { |t| t.kill }
|
234
|
+
progress_reset
|
235
|
+
@fcb_links.sensitive =
|
236
|
+
@fcb_sites.sensitive =
|
237
|
+
@sb_threads.sensitive =
|
238
|
+
@sb_recurse.sensitive = true
|
239
|
+
end
|
240
|
+
|
241
|
+
def recurse_select_refs(host, url, links, result, recurse)
|
242
|
+
return if recurse <= 0
|
243
|
+
|
244
|
+
doc = ''
|
245
|
+
begin
|
246
|
+
status = Timeout::timeout(10) do
|
247
|
+
doc = Nokogiri::HTML(open(url))
|
248
|
+
end
|
249
|
+
rescue Exception => e
|
250
|
+
puts e
|
251
|
+
return nil
|
252
|
+
end
|
253
|
+
|
254
|
+
refs = doc.xpath('//a')
|
255
|
+
refs.each do |r|
|
256
|
+
begin
|
257
|
+
uri = URI.parse(r['href'])
|
258
|
+
rescue Exception => e
|
259
|
+
puts e.to_s + '-' + r['href'].to_s
|
260
|
+
next
|
261
|
+
end
|
262
|
+
|
263
|
+
uri.scheme = URI.parse(host).scheme if uri.scheme.nil?
|
264
|
+
uri.host = URI.parse(host).host if uri.host.nil?
|
265
|
+
|
266
|
+
index = links.index(uri.to_s)
|
267
|
+
result << { :page => url, :link => uri.to_s } unless index.nil?
|
268
|
+
|
269
|
+
# puts ".#{recurse} - #{uri.to_s}"
|
270
|
+
|
271
|
+
recurse_select_refs(host, uri.to_s, links, result, recurse - 1) if uri.host == URI.parse(host).host
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Your code goes here...
|
277
|
+
end
|
data/link_finder.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'link_finder/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "link_finder"
|
8
|
+
gem.version = LinkFinder::VERSION
|
9
|
+
gem.authors = ["Chemeris P.Taras"]
|
10
|
+
gem.email = ["chemt79@gmail.com"]
|
11
|
+
gem.description = %q{Искалка ссылок на сайтах}
|
12
|
+
gem.summary = %q{Утилита}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: link_finder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chemeris P.Taras
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-17 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Искалка ссылок на сайтах
|
15
|
+
email:
|
16
|
+
- chemt79@gmail.com
|
17
|
+
executables:
|
18
|
+
- link_finder
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- bin/link_finder
|
28
|
+
- install.sh
|
29
|
+
- lib/link_finder.glade
|
30
|
+
- lib/link_finder.rb
|
31
|
+
- lib/link_finder/version.rb
|
32
|
+
- link_finder.gemspec
|
33
|
+
homepage: ''
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.8.24
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: Утилита
|
57
|
+
test_files: []
|