Пишем Anime Wallpaper Downloader На Macruby

Просматривая theotaku.com В поисках интересных обоев для рабочего стола я поймал себя на мысли, что было бы неплохо написать программу, которая автоматически скачивала бы мне обои по тегам.

Судя по тому, что я использую Mac OS X в качестве основной операционной системы программное обеспечение также должно быть для этой платформы и желательно иметь Какао интерфейс.

Мне почему-то не хотелось писать все это на Java. Альтернатив, конечно, было много, но мне почему-то хотелось попробовать что-то другое и в то же время узнать что-то новое.

я сразу вспомнил МакРуби и его тесная интеграция с Какао .

Вооружившись этой идеей, я немедленно отправился в http://www.macruby.org/ и скачал последнюю стабильную версию 0.10. После установки запустил свой любимый X-код и создал новый проект под названием АнимеОбоиЗагрузчик Наш проект на МакРуби состоит из нескольких файлов, которые X-код творит для нас.

Первый файл main.m который просто работает МакРуби сценарий rb_main.rb

  
  
  
  
   

#import <Cocoa/Cocoa.h> #import <MacRuby/MacRuby.h> int main(int argc, char *argv[]) { return macruby_main("rb_main.rb", argc, argv); }

rb_main.rb довольно простой скрипт, он загружает все остальные Рубин сценарии и запуски NSApplicationMain

framework 'Cocoa' # Loading all the Ruby project files. main = File.basename(__FILE__, File.extname(__FILE__)) dir_path = NSBundle.mainBundle.resourcePath.fileSystemRepresentation Dir.glob(File.join(dir_path, '*.

{rb,rbo}')).

map { |x| File.basename(x, File.extname(x)) }.

uniq.each do |path| if path != main require(path) end end # Starting the Cocoa main loop. NSApplicationMain(0, nil)

Последний файл, который для нас уже создан, — это AppDelegate.rb , что играет роль NSApplicationDelegate .

Он содержит пустой метод ПриложениеДидФинишЗапуск который вызывается, когда наша программа завершает работу.



class AppDelegate attr_accessor :window def applicationDidFinishLaunching(a_notification) # Insert code here to initialize your application end end

Здесь attr_accessor:окно действующий IBOutlet *окно и уже привязан к нашему окну программы Откройте MainMenu.xib и создайте простой интерфейс для нашего загрузчика обоев.



Пишем Anime Wallpaper Downloader на MacRuby

Далее мы добавляем методы и выходы в нашу AppDelegate

class AppDelegate attr_accessor :window attr_accessor :tags attr_accessor :size attr_accessor :number attr_accessor :saveInto attr_accessor :startButton attr_accessor :output attr_accessor :downprogress attr_accessor :downloader attr_accessor :img def applicationDidFinishLaunching(a_notification) @startButton.setEnabled(false) @downprogress.setStringValue('') @output.setStringValue('') @saveInto.stringValue = NSHomeDirectory()+"/Pictures" end def windowWillClose(a_notification) NSApp.terminate(self) end def controlTextDidChange(notification) sender = notification.object if sender == tags @startButton.setEnabled(@tags.stringValue.size > 0) elsif sender == number begin @number.setIntValue(@number.intValue) if @number.intValue < 0 @number.setIntValue([email protected]) elsif @number.intValue == 0 @number.setIntValue(20) end rescue @number.setIntValue(20) end end end def browse(sender) dialog = NSOpenPanel.openPanel dialog.canChooseFiles = false dialog.canChooseDirectories = true dialog.allowsMultipleSelection = false if dialog.runModalForDirectory(nil, file:nil) == NSOKButton @saveInto.stringValue = dialog.filenames.first end end def startStop(sender) if @downloader == nil @downloader = Downloader.new(@tags.stringValue,@size.selectedItem.title,@number.stringValue,@saveInto.stringValue,self) @downloader.start @startButton.setTitle("Stop Download") else @downloader.stop @downloader = nil @startButton.setTitle("Start Download") end end def changeImage(file) @img.setImage(NSImage.alloc.initByReferencingFile(file)) end def clearStatus @downprogress.setStringValue('') end def setStatus(i,m) @downprogress.setStringValue("Downloading "+i.to_s()+" of "+m.to_s()) end def setStatusEnd(i) @downprogress.setStringValue("Downloaded "+i.to_s()+" wallpapers") end def puts(val) $stdout.puts val @output.setStringValue(val) end def stopped @startButton.setTitle("Start Download") down = @downloader @downloader = nil down.stop end end

Здесь все довольно просто.

Методы окноWillClose И ControlTextDidChange просто делегируем методы для окна программы и первого текстового поля (пока не введем тег, ничего скачать нельзя).

Метод просматривать открывает диалоговое окно выбора каталога, куда сохраняем наши обои, привязываем его к кнопке Просматривать .

Метод стартСтоп запускает загрузку, поэтому привязываем ее к кнопке Начать загрузку .

Остальные методы являются вспомогательными и будут использоваться классом Загрузчик , который мы будем использовать для поиска ссылок и скачивания обоев.



require 'thread' require 'net/http' class Downloader attr_accessor :tags, :size, :number, :saveTo, :thread attr_accessor :app, :exit def initialize(tags, size, number, saveTo, app) @tags = tags.sub(' ','_') @size = size == 'Any' ? '' : size.sub('x','_') @number = number @saveTo = saveTo @app = app @exit = false end def getIndexPage(page) walls = {} url = ' http://www.theotaku.com/wallpapers/tags/'+tags+'/Эsort_by=&resolution='+size+'&date_filter=&category=&page='+page.to_s() @app.puts 'getting index for page: '+page.to_s() @app.puts url response = Net::HTTP.get_response(URI.parse(url)) res = response.body res.each_line { |line| f = line.index('wallpapers/view') while f != nil b = line.rindex('"',f) e = line.index('"',b+1) u = line[b+1,e-b].

gsub('"','') walls[u] = u line = line.sub(u,'') f = line.index('wallpapers/view') end } @app.puts 'got '+walls.size.to_s()+' wallpapers' return walls.keys end def downloadWall(url) @app.puts 'downloading '+url response = Net::HTTP.get_response(URI.parse(url)) res = response.body b = res.index('src',res.rindex('wall_holder'))+5 e = res.index('"',b) img = res[b,e-b] self.downloadFile(img) end def downloadFile(url) name = url[url.rindex('/')+1,1000] if File.exists?(@saveTo+'/'+name) @app.puts 'wallpaper already saved '+name @app.changeImage(@saveTo+'/'+name) else @app.puts 'downloading file '+url response = Net::HTTP.get_response(URI.parse(url)) open(@saveTo+'/'+name, 'wb') { |file| file.write(response.body) } @app.puts 'wallpaper saved '+name @app.changeImage(@saveTo+'/'+name) end end def getWallUrl(i,url,size) sizes = {} i = i+1 @app.puts 'getting '+url+' sizes' response = Net::HTTP.get_response(URI.parse(url)) res = response.body res.each_line { |line| f = line.index('wallpapers/download') while f != nil b = line.rindex('\'',f) e = line.index('\'',b+1) u = line[b+1,e-b] u = u.gsub('\'','') sizes[u] = u line = line.sub(u,'') f = line.index('wallpapers/download') end } sizef = @size.sub('_','-by-') sizes = sizes.keys() if sizef == '' maxi = 0 max = 0 i = 0 sizes.each { |s| f = s.rindex('/') l = s[f+1,100] l = l.sub('-by-',' ') l = l.split(' ') rs = l[0].

to_i()*l[1].

to_i() if rs > max maxi = i max = rs end i = i+1 } return sizes[maxi] else sizes.each { |s| if s =~ /#{Regexp.escape(sizef)}$/ return s end } end return sizes[0] end def start @thread = Thread.new { @app.puts "Download started" begin i = 0 p = 1 @app.clearStatus while i < @number.to_i() and not @exit w = self.getIndexPage(p) if w.size == 0 break end w.each { |w| wallu = self.getWallUrl(i,w,self.size) if wallu != nil @app.setStatus(i+1,@number.to_i()) self.downloadWall(wallu) i = i+1 if i >= @number.to_i() or @exit break end end } p = p+1 end @app.puts "" @app.setStatusEnd(i) rescue => e puts e end @app.stopped } end def stop begin @app.puts "Download stopped" if @thread.alive? if @thread == Thread.current Thread.exit(0) else @exit = true end end rescue => e puts e end end end

Огромный класс, не так ли? Да, он напичкан логикой, но на самом деле всё довольно тривиально.

Метод начинать просто запускает отдельную ветку, в которой будут скачиваться наши обои, останавливаться останавливает его.

Методы getIndexPage , getWallUrl , скачатьСтена специфичный для сайта theotaku.com и содержат довольно много логики, но по сути довольно тривиальны и используются для поиска обоев по тегу, выбора нужной ссылки на нужный размер обоев и скачивания этих обоев Результат – хорошо проведенный воскресный вечер, хорошее чувство удовлетворения собой, а также масса интересных мыслей о будущем.

МакРуби как альтернативная платформа для развития на Mac OS X .

Конечно без грабли не получилось и некоторые вещи сделать не удалось, но я думаю, что платформа МакРуби начинает набирать популярность и имеет блестящее будущее.

Результат можно увидеть здесь здесь , ну а готовый билд можно скачать здесь отсюда (Вы должны иметь МакРуби ) Спасибо за внимание пока, братик

Пишем Anime Wallpaper Downloader на MacRuby

УПД: Спасибо Эстет по рефакторингу парсера выглядит просто великолепно, последнюю версию смотрите на Github Теги: #mac os x #mac os x #ruby #Cocoa #macruby #ruby

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.