pic2ch 0.0.1
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/MIT-LICENSE +20 -0
- data/README +33 -0
- data/Rakefile +53 -0
- data/lib/pic2ch.rb +22 -0
- data/lib/pic2ch/cached_accessor.rb +28 -0
- data/lib/pic2ch/downloaders.rb +3 -0
- data/lib/pic2ch/downloaders/thread.rb +54 -0
- data/lib/pic2ch/pages.rb +19 -0
- data/lib/pic2ch/pages/index.rb +38 -0
- data/lib/pic2ch/parsers.rb +4 -0
- data/lib/pic2ch/parsers/index.rb +54 -0
- data/lib/pic2ch/parsers/thread.rb +45 -0
- data/lib/pic2ch/thread.rb +41 -0
- data/lib/pic2ch/thread/element_parser.rb +14 -0
- data/lib/pic2ch/thread/static.rb +10 -0
- metadata +89 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 [maiha@wota.jp]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
pic2ch
|
2
|
+
======
|
3
|
+
|
4
|
+
A gem that provides api to pic2ch
|
5
|
+
|
6
|
+
|
7
|
+
Usage
|
8
|
+
=====
|
9
|
+
|
10
|
+
threads = Pic2ch.pages.index.threads
|
11
|
+
=> [thread, thread, ...]
|
12
|
+
|
13
|
+
thread = threads.first
|
14
|
+
=> #<struct Pic2ch::Thread
|
15
|
+
name="【はだし】裸足の女の子の画像 Part6【ハダシ】",
|
16
|
+
link="/thread/34071/",
|
17
|
+
created="10/02/02",
|
18
|
+
star=1>
|
19
|
+
|
20
|
+
thread.jpgs
|
21
|
+
=> ["06db8842090121983bd48f7d3bbd8b1d.jpg", ...]
|
22
|
+
|
23
|
+
thread.images
|
24
|
+
=> ["http://strage.giox.info/pics3/1257261441/06db8842090121983bd48f7d3bbd8b1d.jpg", ...]
|
25
|
+
|
26
|
+
thread.thumbs
|
27
|
+
=> ["http://strage.giox.info/thumbs/1257261441/06db8842090121983bd48f7d3bbd8b1d.jpg", ...]
|
28
|
+
|
29
|
+
|
30
|
+
Author
|
31
|
+
======
|
32
|
+
|
33
|
+
maiha@wota.jp
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
GEM_NAME = "pic2ch"
|
5
|
+
AUTHOR = "maiha"
|
6
|
+
EMAIL = "maiha@wota.jp"
|
7
|
+
HOMEPAGE = "http://github.com/maiha/pic2ch"
|
8
|
+
SUMMARY = "A gem that provides api to pic2ch"
|
9
|
+
GEM_VERSION = "0.0.1"
|
10
|
+
|
11
|
+
spec = Gem::Specification.new do |s|
|
12
|
+
s.rubyforge_project = 'asakusarb'
|
13
|
+
s.executables = []
|
14
|
+
s.name = GEM_NAME
|
15
|
+
s.version = GEM_VERSION
|
16
|
+
s.platform = Gem::Platform::RUBY
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.extra_rdoc_files = ["README", "MIT-LICENSE"]
|
19
|
+
s.summary = SUMMARY
|
20
|
+
s.description = s.summary
|
21
|
+
s.author = AUTHOR
|
22
|
+
s.email = EMAIL
|
23
|
+
s.homepage = HOMEPAGE
|
24
|
+
s.require_path = 'lib'
|
25
|
+
s.add_dependency('nokogiri', '>= 1.4.1')
|
26
|
+
s.add_dependency('dsl_accessor', '>= 0.4.0')
|
27
|
+
s.files = %w(MIT-LICENSE README Rakefile) + Dir.glob("{lib,spec,app,public,stubs}/**/*")
|
28
|
+
end
|
29
|
+
|
30
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
31
|
+
pkg.gem_spec = spec
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Install the gem"
|
35
|
+
task :install do
|
36
|
+
Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Uninstall the gem"
|
40
|
+
task :uninstall do
|
41
|
+
Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Create a gemspec file"
|
45
|
+
task :gemspec do
|
46
|
+
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
47
|
+
file.puts spec.to_ruby
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
require 'spec/rake/spectask'
|
52
|
+
desc 'Default: run spec examples'
|
53
|
+
task :default => 'spec'
|
data/lib/pic2ch.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'pathname'
|
3
|
+
require 'dsl_accessor'
|
4
|
+
|
5
|
+
module Pic2ch
|
6
|
+
dsl_accessor :root , Dir.pwd, :writer=>proc{|dir| Pathname(dir)}
|
7
|
+
dsl_accessor :url , 'http://pic2ch.giox.org/' , :writer=>:parse_uri
|
8
|
+
dsl_accessor :image_url, 'http://strage.giox.info/', :writer=>:parse_uri
|
9
|
+
|
10
|
+
private
|
11
|
+
def self.parse_uri(url)
|
12
|
+
URI.parse(url)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
dir = File.dirname(__FILE__) + '/' + File.basename(__FILE__, '.rb') + '/'
|
18
|
+
|
19
|
+
require dir + 'thread'
|
20
|
+
require dir + 'pages'
|
21
|
+
require dir + 'parsers'
|
22
|
+
require dir + 'downloaders'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
######################################################################
|
2
|
+
### CachedAccessor
|
3
|
+
|
4
|
+
module CachedAccessor
|
5
|
+
def self.included(klass)
|
6
|
+
def klass.cached_accessor(&block)
|
7
|
+
Thread.current[:cached_accessor] = true
|
8
|
+
Define.new(self, &block)
|
9
|
+
ensure
|
10
|
+
Thread.current[:cached_accessor] = false
|
11
|
+
end
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
class Define
|
16
|
+
def initialize(klass, &block)
|
17
|
+
@klass = klass
|
18
|
+
instance_eval(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(symbol, &block)
|
22
|
+
cached = "__cached__#{symbol}"
|
23
|
+
@klass.send(:define_method, cached, &block)
|
24
|
+
@klass.class_eval("def #{symbol} ;@#{symbol} ||= #{cached}; end", "(__CACHED_ACCESSOR__)", 1)
|
25
|
+
@klass.class_eval("def #{symbol}!;@#{symbol} = #{cached}; end", "(__CACHED_ACCESSOR__)", 2) unless /\?|!/ === symbol.to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Pic2ch
|
2
|
+
module Downloaders
|
3
|
+
class Thread
|
4
|
+
delegate :time, :to=>"@thread"
|
5
|
+
|
6
|
+
def initialize(thread)
|
7
|
+
@thread = thread
|
8
|
+
end
|
9
|
+
|
10
|
+
def base_path
|
11
|
+
@base_path ||= (
|
12
|
+
path = Pic2ch.root + Pic2ch::Thread.image_url.host + "urls" + time.to_s
|
13
|
+
path.mkpath
|
14
|
+
path
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def images_path_for(type = :images)
|
19
|
+
base_path + "#{type}.txt"
|
20
|
+
end
|
21
|
+
|
22
|
+
def request(type = nil)
|
23
|
+
if type
|
24
|
+
requested?(type) or
|
25
|
+
images_path_for(type).open("w+"){|f| f.puts @thread.send(type)}
|
26
|
+
else
|
27
|
+
request(:thumbs)
|
28
|
+
request(:images)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def requested?(type = :images)
|
33
|
+
images_path_for(type).exist?
|
34
|
+
end
|
35
|
+
|
36
|
+
def done_flag_for(type = :images)
|
37
|
+
base_path + "#{type}.log"
|
38
|
+
end
|
39
|
+
|
40
|
+
def done?(type = :images)
|
41
|
+
done_flag_for(type).exist?
|
42
|
+
end
|
43
|
+
|
44
|
+
def command(type = :images)
|
45
|
+
"wget -x -i %s > %s 2>&1" % [images_path_for(type), done_flag_for(type)]
|
46
|
+
end
|
47
|
+
|
48
|
+
def execute(type = :images)
|
49
|
+
request(type)
|
50
|
+
system(command(type))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/pic2ch/pages.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Pic2ch
|
2
|
+
module Pages
|
3
|
+
def self.index(p = 1)
|
4
|
+
Index.new(p)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.threads
|
8
|
+
index.threads
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.pages
|
13
|
+
Pages
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
dir = File.dirname(__FILE__) + '/' + File.basename(__FILE__, '.rb') + '/'
|
18
|
+
|
19
|
+
require dir + 'index'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Pic2ch
|
2
|
+
module Pages
|
3
|
+
class Index
|
4
|
+
attr_reader :p
|
5
|
+
|
6
|
+
def initialize(p)
|
7
|
+
@p = p.to_i
|
8
|
+
@p = 1 if @p < 1
|
9
|
+
end
|
10
|
+
|
11
|
+
######################################################################
|
12
|
+
### Accessors
|
13
|
+
|
14
|
+
def url
|
15
|
+
Pic2ch.url + path
|
16
|
+
end
|
17
|
+
|
18
|
+
def path
|
19
|
+
p == 1 ? '' : "/?p=#{p}"
|
20
|
+
end
|
21
|
+
|
22
|
+
######################################################################
|
23
|
+
### Fetch
|
24
|
+
|
25
|
+
def html
|
26
|
+
@html ||= open(url).read{}
|
27
|
+
end
|
28
|
+
|
29
|
+
######################################################################
|
30
|
+
### Parsers
|
31
|
+
def parser
|
32
|
+
@parser ||= Parsers::Index.new(html)
|
33
|
+
end
|
34
|
+
|
35
|
+
delegate :threads, :pages, :to=>"parser"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Pic2ch
|
2
|
+
module Parsers
|
3
|
+
class Index
|
4
|
+
module ElementParser
|
5
|
+
def self.next_class_for(e, name, limit = 10, &block)
|
6
|
+
limit.times do
|
7
|
+
e = e.next or return nil
|
8
|
+
next unless e["class"] == name.to_s
|
9
|
+
return block ? block.call(e) : e
|
10
|
+
end
|
11
|
+
return nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(html)
|
16
|
+
@html = html
|
17
|
+
end
|
18
|
+
|
19
|
+
def doc
|
20
|
+
@doc ||= Nokogiri::HTML(@html)
|
21
|
+
end
|
22
|
+
|
23
|
+
def elements
|
24
|
+
@elements ||= doc.xpath("/html/body/div[2]/div[2]/a")
|
25
|
+
end
|
26
|
+
|
27
|
+
def threads
|
28
|
+
@threads ||= elements.map{|e| Pic2ch::Thread.new(*construct(e))}
|
29
|
+
end
|
30
|
+
|
31
|
+
def coded
|
32
|
+
@coded ||= all.inject({}){|hash,obj| hash[obj.code] = obj; hash}
|
33
|
+
end
|
34
|
+
|
35
|
+
def pages
|
36
|
+
@pages ||= doc.css("div.paginate a span.enable_page").map{|span| Pages::Index.new(span.text)}
|
37
|
+
end
|
38
|
+
|
39
|
+
# def get(code)
|
40
|
+
# Static.new(code)
|
41
|
+
# end
|
42
|
+
|
43
|
+
def construct(e)
|
44
|
+
[
|
45
|
+
e.text, # name
|
46
|
+
e["href"], # link
|
47
|
+
ElementParser.next_class_for(e, :created){|e| e.text}, # created
|
48
|
+
ElementParser.next_class_for(e, :star ){|e| e.text}.to_i, # star
|
49
|
+
]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Pic2ch
|
2
|
+
module Parsers
|
3
|
+
class Thread
|
4
|
+
delegate :image_url, :to=>"Pic2ch"
|
5
|
+
delegate :url, :to=>"@thread"
|
6
|
+
|
7
|
+
def initialize(thread)
|
8
|
+
@thread = thread
|
9
|
+
end
|
10
|
+
|
11
|
+
def html
|
12
|
+
@html ||= open(url).read{}
|
13
|
+
end
|
14
|
+
|
15
|
+
def doc
|
16
|
+
@doc ||= Nokogiri::HTML(html)
|
17
|
+
end
|
18
|
+
|
19
|
+
# {id:'1243648801',urls:'54b14715c000a6334ad2e8771cbf70e8.jpg:1e611e8710dd60d616e345aa69334c2d.jpg:...'}
|
20
|
+
def jpgs
|
21
|
+
@jpgs ||= html.scan(/',urls:'(.*?)'/).first.first.split(/:/)
|
22
|
+
end
|
23
|
+
|
24
|
+
def time
|
25
|
+
@time ||= html.scan(/\{id:'(\d+)',urls:'/).first.first.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def title
|
29
|
+
@title ||= doc.search("title").text
|
30
|
+
end
|
31
|
+
|
32
|
+
def thumbs
|
33
|
+
@thumbs ||= jpgs.map{|jpg| image_url + "/thumbs/#{time}/#{jpg}" }
|
34
|
+
end
|
35
|
+
|
36
|
+
def images
|
37
|
+
@images ||= jpgs.map{|jpg| image_url + "/pics3/#{time}/#{jpg}" }
|
38
|
+
end
|
39
|
+
|
40
|
+
def images_with_thumbs
|
41
|
+
@images_with_thumbs ||= [images, thumbs].transpose
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module Pic2ch
|
5
|
+
Thread = Struct.new(:name, :link, :created, :star)
|
6
|
+
class Thread
|
7
|
+
######################################################################
|
8
|
+
### Accessors
|
9
|
+
|
10
|
+
def url
|
11
|
+
Pic2ch.url + link
|
12
|
+
end
|
13
|
+
|
14
|
+
def code
|
15
|
+
link.to_s.scan(/\d+/).flatten.first.to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
######################################################################
|
19
|
+
### Parser
|
20
|
+
|
21
|
+
def parser
|
22
|
+
@parser ||= Parsers::Thread.new(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
delegate :jpgs, :thumbs, :images, :title, :to=>"parser"
|
26
|
+
|
27
|
+
######################################################################
|
28
|
+
### Downloader
|
29
|
+
|
30
|
+
def downloader
|
31
|
+
Downloaders::Thread.new(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def download
|
35
|
+
Dir.chdir(Pic2ch.root) do
|
36
|
+
downloader.execute
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Pic2ch
|
2
|
+
class Thread
|
3
|
+
module ElementParser
|
4
|
+
def self.next_class_for(e, name, limit = 10, &block)
|
5
|
+
limit.times do
|
6
|
+
e = e.next or return nil
|
7
|
+
next unless e["class"] == name.to_s
|
8
|
+
return block ? block.call(e) : e
|
9
|
+
end
|
10
|
+
return nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pic2ch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- maiha
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-02 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nokogiri
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.4.1
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: dsl_accessor
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.0
|
34
|
+
version:
|
35
|
+
description: A gem that provides api to pic2ch
|
36
|
+
email: maiha@wota.jp
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README
|
43
|
+
- MIT-LICENSE
|
44
|
+
files:
|
45
|
+
- MIT-LICENSE
|
46
|
+
- README
|
47
|
+
- Rakefile
|
48
|
+
- lib/pic2ch.rb
|
49
|
+
- lib/pic2ch/pages/index.rb
|
50
|
+
- lib/pic2ch/parsers/thread.rb
|
51
|
+
- lib/pic2ch/parsers/index.rb
|
52
|
+
- lib/pic2ch/downloaders.rb
|
53
|
+
- lib/pic2ch/thread.rb
|
54
|
+
- lib/pic2ch/downloaders/thread.rb
|
55
|
+
- lib/pic2ch/thread/element_parser.rb
|
56
|
+
- lib/pic2ch/thread/static.rb
|
57
|
+
- lib/pic2ch/parsers.rb
|
58
|
+
- lib/pic2ch/cached_accessor.rb
|
59
|
+
- lib/pic2ch/pages.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/maiha/pic2ch
|
62
|
+
licenses: []
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project: asakusarb
|
84
|
+
rubygems_version: 1.3.5
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: A gem that provides api to pic2ch
|
88
|
+
test_files: []
|
89
|
+
|