rstackoverflow 0.1.0
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.
- checksums.yaml +7 -0
- data/lib/rstackoverflow.rb +25 -0
- data/lib/rstackoverflow/question.rb +76 -0
- data/lib/rstackoverflow/utils.rb +10 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 12387e336eeaad5a7d0631b57b3f4cc038c6dc3d
|
4
|
+
data.tar.gz: 65df29d177341a81d87f0278812cde6f7425aa64
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bb2491b0069dfb77882b6bea846ae3c7f7d3573a35468ee22d99a683c3de3a62e1a3cf240485e3c6d675ed517ebb4228e9455f9f65fd41c907a288734e9d4ad7
|
7
|
+
data.tar.gz: 52b7cc6c07361959b2e1c726a678511e9b179956a371a2e3cfff288f798791de9bbb6a4dbca1d3ac4b8279f9b501f56fc7abcf5d5cbfb9b89544a96899f1618f
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module StackOverflow
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module ExtensionString
|
6
|
+
refine String do
|
7
|
+
def escape!
|
8
|
+
self.tr!(' ', '+')
|
9
|
+
URI.escape(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Engine
|
15
|
+
Native = :native
|
16
|
+
Github = :github
|
17
|
+
Engines = [Native, Github]
|
18
|
+
end
|
19
|
+
|
20
|
+
class InvalidSearchEngine < StandardError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require_relative 'rstackoverflow/utils'
|
25
|
+
require_relative 'rstackoverflow/question'
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module StackOverflow
|
2
|
+
module Questions
|
3
|
+
using ExtensionString
|
4
|
+
extend Engine
|
5
|
+
class << self
|
6
|
+
def add_class(klass, *args)
|
7
|
+
eval <<-init
|
8
|
+
class #{klass.capitalize}
|
9
|
+
attr_reader :#{args.join(', :')}
|
10
|
+
def initialize(#{args.join(', ')})
|
11
|
+
#{args.map {|e| "@#{e} = #{e};"}.join}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
init
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](q_index)
|
18
|
+
return nil unless q_index.is_a? Integer
|
19
|
+
html = Utils.http_get("/questions/#{q_index}")
|
20
|
+
href = html.css('a').first.attr('href')
|
21
|
+
arr = href.split('/')
|
22
|
+
return nil unless q_index == arr[2].to_i
|
23
|
+
html = Utils.http_get(href)
|
24
|
+
q_title = html.css('div[id=question-header]').first.css('a').text
|
25
|
+
question = html.css('div[class=question]').first
|
26
|
+
q_detail = question.css('div[class=post-text]').text.strip
|
27
|
+
q_vote = question.css('span[class~=vote-count-post]').text.to_i
|
28
|
+
list = question.css('div[class=post-taglist]')
|
29
|
+
q_labels = list.first.children.css('a').map {|e| e.text}
|
30
|
+
q_comments = question.css('td[class=comment-text]').map {|e| e.text.strip}
|
31
|
+
|
32
|
+
answers = html.css('div[class~=answer]').map do |e|
|
33
|
+
a_index = e.attr('id')[7..-1].to_i
|
34
|
+
a_detail = e.css('div[class=post-text]').text.strip
|
35
|
+
a_accepted = e.attr('class').index('accepted-answer') ? true : false
|
36
|
+
a_vote = e.css('span[class~=vote-count-post]').text.to_i
|
37
|
+
a_comments = e.css('td[class=comment-text]').map {|t| t.text.strip}
|
38
|
+
Answer.new(a_index, a_detail, a_accepted, a_vote, a_comments)
|
39
|
+
end
|
40
|
+
Question.new(q_index, "#{Utils::DOMAIN}#{href}",
|
41
|
+
q_title, q_detail, q_vote, q_labels, q_comments,
|
42
|
+
answers)
|
43
|
+
end
|
44
|
+
|
45
|
+
alias :at :[]
|
46
|
+
|
47
|
+
def search(cond, engine = Native)
|
48
|
+
return nil unless cond.is_a? String
|
49
|
+
case engine
|
50
|
+
when Native
|
51
|
+
html = Utils.http_get("/search?q=#{cond.escape!}")
|
52
|
+
results = html.css('div[class~=search-result]')
|
53
|
+
results.map do |r|
|
54
|
+
r_index = r.attr('id')[17..-1].to_i
|
55
|
+
r_title = r.css('div[class=result-link]').text.strip
|
56
|
+
r_abstract = r.css('div[class=excerpt]').text.strip
|
57
|
+
r_vote = r.css('span[class~=vote-count-post]').text.to_i
|
58
|
+
r_answer_count = r.css('div[class~=answered-accepted]').text.to_i
|
59
|
+
Result.new(r_index, r_title, r_abstract, r_vote, r_answer_count)
|
60
|
+
end
|
61
|
+
when Github
|
62
|
+
#TODO
|
63
|
+
fail InvalidSearchEngine
|
64
|
+
else
|
65
|
+
fail InvalidSearchEngine
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
add_class :Question, :id, :url, :title, :detail, :vote, :labels, :comments, :answers
|
71
|
+
add_class :Answer, :id, :detail, :accepted, :vote, :comments
|
72
|
+
#TODO
|
73
|
+
#add_class :Comment
|
74
|
+
add_class :Result, :id, :title, :abstract, :vote, :answer_count
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rstackoverflow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Breeze
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.5.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.5'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.5.2
|
33
|
+
description: Ruby toolkit to Stackoverflow API by html parsing.
|
34
|
+
email: sjtubreeze@163.com
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- lib/rstackoverflow.rb
|
40
|
+
- lib/rstackoverflow/question.rb
|
41
|
+
- lib/rstackoverflow/utils.rb
|
42
|
+
homepage: https://github.com/jicong/rStackOverflow
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.9.2
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.4.8
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: StackOverflow API
|
66
|
+
test_files: []
|