ameblogazo 0.0.1 → 0.0.2

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.
@@ -1,34 +1,35 @@
1
1
  = Ameblogazo
2
2
 
3
- アメーバブログの画像のダウンロードを簡単にしてくれるツールとライブラリ。
3
+ アメーバブログの画像をダウンロードするツールとライブラリ。
4
4
 
5
5
  == Installing
6
6
 
7
7
  gem install ameblogazo
8
8
 
9
- dependencies: nokogiri
9
+ dependencies: capybara, capybara-webkit, headless
10
10
 
11
- == Using tool
11
+ require: qt-devel qt-webkit-devel > 4.7, Xvfb
12
12
 
13
- 画像を全てダウンロード
14
- ameblogazo -i ameba_id -d /tmp -c date
13
+ == Using
15
14
 
16
- 画像を新しいものから10個ダウンロード
17
- ameblogazo -i ameba_id -d /tmp -c date -n 10
15
+ 画像を最新のものから指定枚数だけダウンロード
16
+ ameblogazo -i ameba_id -d /tmp -n 10
17
+
18
+ 指定した場所に保存されている画像と同一のものが見つかるまでダウンロード
19
+ ameblogazo -i ameba_id -d /tmp
18
20
 
19
21
  オプションの説明
20
22
  -i アメーバIDを指定
21
23
  -d 保存先ディレクトリを指定
22
24
  -c カテゴライズ設定(title or date)。デフォルトは無効。titleは記事タイトル毎に分類。dateは日付で分類。
23
- -n ダウンロードする画像の枚数を指定
24
- -p まだダウンロードしてない画像だけダウンロードする
25
+ -n 画像の枚数を指定
26
+ -s SeleniumDriverを使用
25
27
 
26
- == Using library
28
+ == Library
27
29
 
28
30
  サンプル
29
31
  require 'ameblogazo'
30
- Ameblogazo.download(:ameba_id=>'ameba_id', :dir=>'/tmp', :categorize=>'date', :num=>10)
31
- Ameblogazo.download_periodic(:ameba_id=>'ameba_id', :dir=>'/tmp', :categorize=>'date')
32
+ Ameblogazo.download(:ameba_id=>'ameba_id', :dir=>'/tmp', :num=>10, :selenium=>true)
32
33
 
33
34
  == Copyright
34
35
 
@@ -21,5 +21,8 @@ Gem::Specification.new do |s|
21
21
  # specify any dependencies here; for example:
22
22
  # s.add_development_dependency "rspec"
23
23
  # s.add_runtime_dependency "rest-client"
24
- s.add_dependency('nokogiri')
24
+ s.add_dependency('capybara')
25
+ s.add_dependency('capybara-webkit')
26
+ s.add_dependency('headless')
27
+ s.add_development_dependency('rspec')
25
28
  end
@@ -3,28 +3,27 @@
3
3
 
4
4
  require "ameblogazo"
5
5
  require "optparse"
6
+ require "headless"
6
7
 
7
- opts = {}
8
- op = OptionParser.new do |opt|
9
- opt.on('-i ID', '--ameba-id=ID', 'アメーバIDを指定') {|v| opts[:ameba_id] = v}
10
- opt.on('-d DIR', '--dir=DIR', '画像の保存先ディレクトリを指定') {|v| opts[:dir] = v}
11
- opt.on('-c TYPE', '--categorize=TYPE', ['title', 'date'], 'カテゴライズ(title or date)を指定') {|v| opts[:categorize] = v}
12
- opt.on('-n NUM', '--num=NUM', '画像の枚数を指定。指定がないと全て取得') {|v| opts[:num] = v}
13
- opt.on('-p', '--periodic', 'ダウンロード済みの画像が見つかるまで取得') {|v| opts[:periodic] = v}
14
-
15
- opt.parse!
16
- end
17
- if opts.empty?
18
- puts op
19
- exit
20
- end
21
-
22
- begin
23
- if opts[:periodic]
24
- Ameblogazo.download_periodic(opts)
25
- else
26
- Ameblogazo.download(opts)
27
- end
28
- rescue => ex
29
- puts ex.message
8
+ Headless.ly do
9
+ opts = {}
10
+ op = OptionParser.new do |opt|
11
+ opt.on('-i ID', '--ameba-id=ID', 'アメーバIDを指定') {|v| opts[:ameba_id] = v}
12
+ opt.on('-d DIR', '--dir=DIR', '画像の保存先ディレクトリを指定') {|v| opts[:dir] = v}
13
+ opt.on('-c TYPE', '--categorize=TYPE', ['title', 'date'], 'カテゴライズ(title, date)を指定') {|v| opts[:categorize] = v}
14
+ opt.on('-n NUM', '--num=NUM', '画像の枚数を指定') {|v| opts[:num] = v}
15
+ opt.on('-s', '--selenium', 'selenium driverを使用') {|v| opts[:selenium] = true}
16
+
17
+ opt.parse!
18
+ end
19
+ if opts.empty?
20
+ puts op
21
+ exit
22
+ end
23
+
24
+ begin
25
+ Ameblogazo.download(opts)
26
+ rescue => ex
27
+ puts ex.message
28
+ end
30
29
  end
@@ -1,14 +1,34 @@
1
1
  # coding: utf-8
2
2
  require "ameblogazo/version"
3
3
  require 'open-uri'
4
- require 'nokogiri'
5
4
  require 'fileutils'
5
+ require 'capybara'
6
+ require 'capybara/dsl'
7
+ require 'capybara-webkit'
6
8
 
7
9
  module Ameblogazo
8
10
  class Gazo
9
11
  class GazoException < StandardError
10
12
  end
11
13
 
14
+ class Driver
15
+ include Capybara::DSL
16
+ end
17
+
18
+ class WebkitDriver < Driver
19
+ def initialize()
20
+ Capybara.default_driver = :webkit
21
+ Capybara.javascript_driver = :webkit
22
+ end
23
+ end
24
+
25
+ class SeleniumDriver < Driver
26
+ def initialize()
27
+ Capybara.default_driver = :selenium
28
+ Capybara.javascript_driver = :selenium
29
+ end
30
+ end
31
+
12
32
  # オプションチェック
13
33
  def _check_options(options)
14
34
  if options.nil? or !options.is_a?(Hash)
@@ -28,6 +48,15 @@ module Ameblogazo
28
48
  options
29
49
  end
30
50
 
51
+ # driver初期化
52
+ def _init_driver(selenium)
53
+ if selenium
54
+ @driver = SeleniumDriver.new
55
+ else
56
+ @driver = WebkitDriver.new
57
+ end
58
+ end
59
+
31
60
  # 一番最初の画像のURLを取得する
32
61
  def _find_image_url(ameba_id)
33
62
  puts "検索中..."
@@ -43,6 +72,12 @@ module Ameblogazo
43
72
  end
44
73
  doc = Nokogiri::HTML(html)
45
74
 
75
+ # 有効なameba_idか確認
76
+ sorry = doc.xpath("//body[@class='sorry']")
77
+ unless sorry.empty?
78
+ raise GazoException, "存在しないIDです"
79
+ end
80
+
46
81
  a = doc.xpath("//a")
47
82
  a.each do |node|
48
83
  if /http:\/\/ameblo.jp\/#{ameba_id}\/image-\d{11}-\d{11}.html/ =~ node[:href]
@@ -59,155 +94,129 @@ module Ameblogazo
59
94
  end
60
95
  image_url
61
96
  end
62
-
63
- # カテゴライズしたパスを返す
64
- def _categorize(dir, categorize, img)
97
+
98
+ # ダウンロード対象のURLや保存先を取得
99
+ def _get_info(dir, categorize)
100
+ img = @driver.find(:xpath, '//img[@id="imgItem"]')
101
+ download_url = img[:src]
102
+ filename = File.basename(download_url)
103
+ title = @driver.find("#entryLink").text
104
+ date = download_url[/\d{8}/]
105
+
65
106
  # カテゴリー分け(タイトルとか日付)
66
107
  if categorize == "title"
67
- title = img[:alt]
68
108
  dir = "#{dir}/#{title}"
69
109
  elsif categorize == "date"
70
- if /http:\/\/stat.ameba.jp\/user_images\/(\d{8})\/.*/ =~ img[:src]
71
- date = $1
110
+ if date
72
111
  dir = "#{dir}/#{date}"
73
112
  else
74
- print "うまく日付がとれなかったのでカテゴライズせずに保存します\n"
113
+ puts "うまく日付がとれなかったのでカテゴライズせずに保存します"
75
114
  end
76
115
  end
77
- dir
78
- end
79
-
80
- # ダウンロード対象のドキュメントを取得
81
- def _download_doc(url)
82
- html = open(url)
83
- doc = Nokogiri::HTML(html)
116
+
117
+ # ディレクトリが存在しなければ作成する
118
+ unless File.directory?(dir)
119
+ print "ディレクトリを作成します #{dir}\n"
120
+ FileUtils.mkdir_p(dir)
121
+ end
122
+ download_file = "#{dir}/#{filename}"
123
+ {:url=>download_url, :file=>download_file, :title=>title, :date=>date}
84
124
  end
85
-
86
- # ダウンロード対象のURLや保存先を取得
87
- def _download_info(doc, dir, categorize)
88
- img = doc.xpath('//img[@id="centerImg"]')
89
- unless img.empty?
90
- download_url = img[0][:src]
91
- filename = File.basename(download_url)
92
-
93
- # カテゴリー分け(タイトルとか日付)
94
- dir = _categorize(dir, categorize, img[0])
95
125
 
96
- # ディレクトリが存在しなければ作成する
97
- unless File.directory?(dir)
98
- print "ディレクトリを作成します #{dir}\n"
99
- FileUtils.mkdir_p(dir)
100
- end
101
- download_file = "#{dir}/#{filename}"
102
- return {:url=>download_url, :file=>download_file}
103
- end
104
- return {}
126
+ # 次にダウンロードするべき画像を開く
127
+ def _next_page()
128
+ @driver.find("#nextNavi").click
105
129
  end
106
-
107
- # 画像本体をダウンロード
108
- def _download_img(url, file)
130
+
131
+ # 画像をダウンロードして保存
132
+ def _save_img(url, file)
109
133
  open(url) do |doc|
110
134
  open(file, 'w') do |fp|
111
135
  fp.print doc.read
112
136
  end
113
137
  end
114
138
  filename = File.basename(file)
115
- print "#{filename} をダウンロードしました\n"
139
+ puts "#{filename} を保存しました"
116
140
  end
117
141
 
118
- # 次にダウンロードするべきURLを取得する
119
- def _download_next_url(doc)
120
- a = doc.xpath('//a[@id="imgLink"]')
121
- unless a.empty?
122
- image_url = a[0][:href] # 次の画像URL
123
- end
124
- end
125
-
126
- # 指定URLの物を保存する
127
- def _download(url, dir, categorize)
128
- doc = _download_doc(url)
129
- info = _download_info(doc, dir, categorize)
130
-
131
- if File.exists?(info[:file])
132
- print "もうダウロード済みみたいです\n"
133
- else
134
- _download_img(info[:url], info[:file])
135
- end
136
- _download_next_url(doc)
137
- end
138
-
139
- # ダウンロード済みの画像をみつけたら止める
140
- def _download_periodic(url, dir, categorize)
141
- doc = _download_doc(url)
142
- info = _download_info(doc, dir, categorize)
143
-
144
- if File.exists?(info[:file])
145
- print "ダウロード済みの見つけたので終了します\n"
146
- return nil
147
- else
148
- _download_img(info[:url], info[:file])
149
- end
150
- _download_next_url(doc)
151
- end
152
-
153
- # 画像を取得する
142
+ # 画像を保存する
154
143
  # :ameba_id => アメーバID
155
144
  # :dir => 保存先ディレクトリ
156
145
  # :categorize => タイトル毎などに分類する(デフォルト無効)[nil, "title", "date"]
157
146
  # :num => 取得する枚数(新しいものから順番に)[数値]
158
- def get(options)
147
+ def fetch(options)
159
148
  options = _check_options(options)
160
149
  ameba_id = options[:ameba_id]
161
150
  categorize = options[:categorize]
162
151
  dir = options[:dir]
163
152
  num = options[:num]
164
153
 
165
- image_url = _find_image_url(ameba_id)
154
+ # driver初期化
155
+ _init_driver(options[:selenium])
166
156
 
167
- if num
168
- num.times do |i|
169
- # 最初にみつけた画像から次の画像へと順番にたどってく
170
- image_url = _download(image_url, dir, categorize)
171
- break if image_url.nil?
172
- sleep(0.3)
173
- end
174
- else
175
- loop do
176
- # 最初にみつけた画像から次の画像へと順番にたどってく
177
- image_url = _download(image_url, dir, categorize)
178
- break if image_url.nil?
179
- sleep(0.3)
157
+ # 画像ページに移動
158
+ @driver.visit(_find_image_url(ameba_id))
159
+
160
+ # 最初にみつけた画像から次の画像へと順番にたどってく
161
+ info_list = []
162
+ loop.with_index do |_, i|
163
+ break if i == num # 指定枚数で終了
164
+ info = _get_info(dir, categorize)
165
+ break if !info_list[0].nil? and info_list[0][:file] == info[:file]
166
+ info_list.push(info)
167
+
168
+ if File.exists?(info[:file])
169
+ if num
170
+ puts "既にダウンロードされている画像です"
171
+ else
172
+ puts "ダウンロード済みの画像が見つかったので終了します"
173
+ break
174
+ end
175
+ else
176
+ _save_img(info[:url], info[:file])
180
177
  end
178
+ _next_page
179
+ sleep(0.5)
181
180
  end
182
181
  end
183
182
 
184
- # 取得済みの画像がみつかるまで新しいものから順番に画像を取得する
185
- # 毎日定期的に取得したいひと向け
186
- def get_periodic(options)
183
+ # 画像の情報を取得する
184
+ def info(options)
187
185
  options = _check_options(options)
188
186
  ameba_id = options[:ameba_id]
189
187
  categorize = options[:categorize]
190
188
  dir = options[:dir]
189
+ num = options[:num]
190
+
191
+ # driver初期化
192
+ _init_driver(options[:selenium])
193
+
194
+ # 画像ページに移動
195
+ @driver.visit(_find_image_url(ameba_id))
191
196
 
192
- image_url = _find_image_url(ameba_id)
193
- loop do
194
- # 最初にみつけた画像から次の画像へと順番にたどってく
195
- image_url = _download_periodic(image_url, dir, categorize)
196
- break if image_url.nil?
197
- sleep(0.3)
197
+ # 最初にみつけた画像から次の画像へと順番にたどってく
198
+ info_list = []
199
+ loop.with_index do |a, i|
200
+ break if i == num # 指定枚数で終了
201
+ info = _get_info(dir, categorize)
202
+ break if !info_list[0].nil? and info_list[0][:file] == info[:file]
203
+ info_list.push(info)
204
+ _next_page
205
+ sleep(0.5)
198
206
  end
207
+ info_list
199
208
  end
200
209
  end
201
210
 
202
211
  def download(options)
203
212
  gazo = Gazo.new
204
- gazo.get(options)
213
+ gazo.fetch(options)
205
214
  end
206
215
 
207
- def download_periodic(options)
216
+ def info(options)
208
217
  gazo = Gazo.new
209
- gazo.get_periodic(options)
218
+ gazo.info(options)
210
219
  end
211
220
 
212
- module_function :download, :download_periodic
221
+ module_function :download, :info
213
222
  end
@@ -1,3 +1,3 @@
1
1
  module Ameblogazo
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,47 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Ameblogazo::Gazo do
5
+ before(:all) do
6
+ @gazo = Ameblogazo::Gazo.new
7
+ end
8
+
9
+ describe "オプションをチェックするとき" do
10
+ it "nilだったら例外を投げること" do
11
+ expect{ @gazo._check_options(nil) }.to raise_error(Ameblogazo::Gazo::GazoException)
12
+ end
13
+ it "ディレクトリが指定されていなかったら例外を投げること" do
14
+ options = {}
15
+ expect{ @gazo._check_options(options) }.to raise_error(Ameblogazo::Gazo::GazoException)
16
+ end
17
+ it "枚数指定の値が数値以外だったら例外を投げること" do
18
+ options = {:dir=>'/tmp', :num=>'abc'}
19
+ expect{ @gazo._check_options(options) }.to raise_error(Ameblogazo::Gazo::GazoException)
20
+ end
21
+ end
22
+
23
+ describe "最初の画像のURLを取得するとき" do
24
+ it "無効なIDが渡されたら例外を投げること" do
25
+ expect{ @gazo._find_image_url("ameblogazotest") }.to raise_error(Ameblogazo::Gazo::GazoException)
26
+ end
27
+
28
+ it "返ってくる値がnilではないこと" do
29
+ @gazo._find_image_url("staff").nil?.should == false
30
+ end
31
+ end
32
+
33
+ describe "画像をダウンロードするとき" do
34
+ before(:all) do
35
+ url = @gazo._find_image_url("staff")
36
+ @gazo.instance_eval{@driver.visit(url)}
37
+ end
38
+
39
+ it "ダウンロードURLや保存先が取得できること" do
40
+ @gazo._get_info("/tmp", "title").empty?.should == false
41
+ end
42
+
43
+ it "次の画像に移動できること" do
44
+ @gazo._next_page
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,22 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'rspec'
9
+ require 'ameblogazo'
10
+
11
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+
17
+ # Run specs in random order to surface order dependencies. If you find an
18
+ # order dependency and want to debug it, you can fix the order by providing
19
+ # the seed, which is printed after each run.
20
+ # --seed 1234
21
+ config.order = 'random'
22
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ameblogazo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-09 00:00:00.000000000Z
12
+ date: 2012-12-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: nokogiri
16
- requirement: &85180950 !ruby/object:Gem::Requirement
15
+ name: capybara
16
+ requirement: &69325480 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,40 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *85180950
24
+ version_requirements: *69325480
25
+ - !ruby/object:Gem::Dependency
26
+ name: capybara-webkit
27
+ requirement: &69325180 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *69325180
36
+ - !ruby/object:Gem::Dependency
37
+ name: headless
38
+ requirement: &69324970 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *69324970
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &69324760 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *69324760
25
58
  description: get ameba blog images
26
59
  email:
27
60
  - labs.ninxit@gmail.com
@@ -38,6 +71,8 @@ files:
38
71
  - bin/ameblogazo
39
72
  - lib/ameblogazo.rb
40
73
  - lib/ameblogazo/version.rb
74
+ - spec/ameblogazo_spec.rb
75
+ - spec/spec_helper.rb
41
76
  homepage: ''
42
77
  licenses: []
43
78
  post_install_message:
@@ -62,4 +97,6 @@ rubygems_version: 1.8.10
62
97
  signing_key:
63
98
  specification_version: 3
64
99
  summary: get ameba blog images
65
- test_files: []
100
+ test_files:
101
+ - spec/ameblogazo_spec.rb
102
+ - spec/spec_helper.rb