qunar 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: abb1c8b487e496de74a3d1aba1011297d09ec936
4
+ data.tar.gz: c31420590fc4344ff961faa8cf5a74c57dd66b49
5
+ SHA512:
6
+ metadata.gz: 7595b89f23e5424c60c5f4d640d51bdc9b31da7a27802390ee2716df5b3909ffccf5d48b4f164cdad164d5d99a04e43ffac0d4abf05c912258b822f96ff66052
7
+ data.tar.gz: c0805458111c8147aff0a921abf7f58b1d9f28fc755f7311e00cbe574f8197af1062945db20e55222cb2daa798cef0acef16ec0fa4ee2289715f1eabe4d007b9
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in qunar.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 charles
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
+ # Qunar
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'qunar'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install qunar
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/qunar/fork )
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 a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,212 @@
1
+ require 'nokogiri'
2
+ require 'httparty'
3
+ module Qunar
4
+ class Hotel
5
+ BASEURI = "http://hotel.qunar.com"
6
+ def initialize(hotelId)
7
+ #super
8
+ raise "id should be string" if !hotelId.instance_of?(String)
9
+ @HotelSEQ = hotelId #hotelId is "cityurl_hotelcode"
10
+ @cityurl = hotelId[0..hotelId.rindex("_",-1)-1]
11
+ @hotelcode = hotelId[hotelId.rindex("_",-1)+1..hotelId.length]
12
+ uri = URI(File.join(BASEURI, 'city', @cityurl, "dt-#{@hotelcode}"))
13
+ page = HTTParty.get(uri.to_s)
14
+ @hotel = Nokogiri::HTML page
15
+ end
16
+
17
+ def parse_mixkey #get some kind of code unkown
18
+ uri = URI(File.join(BASEURI, 'city', @cityurl, "dt-#{@hotelcode}"))
19
+ http_res = HTTParty.get uri.to_s
20
+ res = Nokogiri::HTML http_res
21
+ node = res.search('//span[@id="eyKxim"]').first
22
+ return nil if node.nil?
23
+ return node.text
24
+ end
25
+
26
+ def name #get the name of the hotel
27
+ @hotel.search("//div[@class='htl-info fr']//span").first.text.strip
28
+ # name_tag = @hotel.search("//div[@class='htl-info fr']/h2/span").first
29
+ # return nil if name_tag.nil?
30
+ # name_tag.text[0..name_tag.text.index("\n",1)].strip
31
+ end
32
+
33
+ def star #get the level of the hotel
34
+ #name_tag = @hotel.search('//div[@class="eriefinfo"]//dt').first
35
+ name_tag = @hotel.search('//div[@class="htl-info fr"]//em[@class="dangci"]').first
36
+ return 0 if name_tag.nil?
37
+ if name_tag.text.include?'经济型'
38
+ 1
39
+ elsif name_tag.text.include?'舒适型'
40
+ 3
41
+ elsif name_tag.text.include?'高档型'
42
+ 4
43
+ elsif name_tag.text.include?'豪华型'
44
+ 5
45
+ elsif name_tag.text.include?'star20'
46
+ 2
47
+ elsif name_tag.text.include?'star50'
48
+ 5
49
+ else
50
+ 0
51
+ end
52
+ end
53
+
54
+ def citynameEn
55
+ @cityurl.sub('_city','')
56
+ end
57
+
58
+ def citynameCn
59
+ match_data = @hotel.to_s.match(/var\s*cityName\s*=\s*\'\p{Han}+\'/u)
60
+ return "" if match_data.nil?
61
+ match_data = match_data[0].match(/\p{Han}+/u)
62
+ return "" if match_data.nil?
63
+ match_data[0].strip
64
+ end
65
+
66
+ def id
67
+ @hotelcode = @hotelcode
68
+ end
69
+
70
+ def address
71
+ @hotel.search("//p[@class='adress']/span").first['title'].strip
72
+ #return "" if address.nil?
73
+ #return address['title'].strip
74
+ end
75
+
76
+ def phone
77
+ #phone ||= @hotel.search("//li[contains(text(),'电话:')]").text.sub('电话:','').strip
78
+ @hotel.search("//dl[@class='inform-list']//cite").first.text.sub('电话','').strip
79
+ end
80
+
81
+ #the description of the hotel
82
+ def desc
83
+ #desc = @hotel.search("p[@class='summery less_summery']").text
84
+ #desc = @hotel.search("p[@class='summery expan_summery']").text if desc.empty?
85
+ #desc.gsub(/[[:space:]]/, '')
86
+ @hotel.search("div[@class='introduce']/p").text
87
+ end
88
+
89
+ #开业时间
90
+ def opentime
91
+ #date ||= @hotel.search("p[@class='insttime']/cite").text.sub("开业时间:","")
92
+ #date.strip
93
+ @hotel.search("dl[@class='inform-list']//cite")[-2].text.sub("年开业",'')
94
+ end
95
+ =begin
96
+ #简略描述
97
+ def abstract_desc
98
+ abstract_desc = @hotel.search("p[@class='h_desc']").first
99
+ return "" if abstract_desc.nil?
100
+ return abstract_desc.text.sub('描述:','').strip
101
+ end
102
+
103
+ def brand
104
+ brand ||= @hotel.search("//li[contains(text(),'所属品牌:')]").text.sub('所属品牌:','').strip
105
+ brand.strip
106
+ end
107
+ =end
108
+ def reference_price
109
+ match_data = @hotel.to_s.match(/var\s*miniRetailPrice\s*=\s*\'\d+\';/)
110
+ return 0 if match_data.nil?
111
+ match_data = match_data[0].match(/[\d]+/)
112
+ return 0 if match_data.nil?
113
+ match_data[0].strip
114
+ end
115
+
116
+ def coordinate
117
+ xy = @hotel.to_s.match(/hotelPoint=\[(\d+\.\d+),(\d+\.\d+)\];/)
118
+ puts xy
119
+ if xy.nil?
120
+ return [0.0,0.0]
121
+ else
122
+ return [xy[1],xy[2]]
123
+ end
124
+ end
125
+ #设施
126
+ def facilities
127
+ facility = @hotel.search("//div[@class=\"roundmilieu htintroborder\"]").first
128
+ facilities = Array.new()
129
+ unless facility.nil?
130
+ facility.search("dl").each do |dl|
131
+ ele = Hash.new
132
+ facility_cata = dl.search("dt").first.text.delete(':')
133
+ ele1 = Array.new
134
+ dl.search("dd/ul/li").each do |facility_type|
135
+ ele1 << facility_type.text
136
+ end
137
+ ele['name'] = facility_cata
138
+ ele['info'] = ele1
139
+ facilities << ele
140
+ end
141
+ end
142
+ facilities
143
+ end
144
+
145
+ #交通信息 not runable
146
+ =begin
147
+ def traffic
148
+ traffic = "http://hotel.qunar.com/detail/detailMapData.jsp?seq=#{@hotelcode}&type=traffic,canguan,jingdian,ent"
149
+ traffic = HTTParty.get traffic
150
+ traffic_data = Array.new()
151
+ if traffic['ret'] == true
152
+ traffic['data']['ent'].each do |line|
153
+ ele = Hash.new
154
+ ele['name'] = line['name']
155
+ ele['distance'] = line['distance']
156
+ traffic_data << ele
157
+ end
158
+ end
159
+ end
160
+
161
+ def decorate_date #not found
162
+ match_data = @hotel.to_s.match(/最后装修时间:\d+年/)
163
+ return "" if match_data.nil?
164
+ match_data[0].strip
165
+ end
166
+
167
+
168
+ def comments
169
+ url = "http://review.qunar.com/api/h/#{@hotelcode}/detail/rank/v1/page/1"
170
+ comments = HTTParty.get url
171
+ comments = JSON.parse comments
172
+ comments['data']['list'].map{|comment| JSON.parse(comment['content'])['feedContent'] }
173
+ end
174
+
175
+ #评论总数
176
+ def total_comment
177
+ url = "http://review.qunar.com/api/h/#{@hotelcode}/detail/rank/page/1?rate=all"
178
+ body = HTTParty.get url
179
+ match_data = body.match(/"count":\d+/)
180
+ return "0" if match_data.nil?
181
+ match_data[0].sub(/\"count\":/,"").strip
182
+ end
183
+ #好评
184
+ def good_comment
185
+ url = "http://review.qunar.com/api/h/#{@hotelcode}/detail/rank/page/1?rate=positive"
186
+ body = HTTParty.get url
187
+ match_data = body.match(/"count":\d+/)
188
+ return "0" if match_data.nil?
189
+ match_data[0].sub(/\"count\":/,"")
190
+ end
191
+
192
+
193
+ def images
194
+ url = "http://hotel.qunar.com/render/hotelDetailAllImage.jsp?hotelseq=#{@hotelcode}"
195
+ body = HTTParty.get url
196
+ body = JSON.parse(body)
197
+ return body['data']["all"] if(body['ret'])
198
+ end
199
+
200
+ def score
201
+ url = "http://review.qunar.com/api/h/#{@hotelcode}/detail"
202
+ body = HTTParty.get url
203
+ begin
204
+ body = JSON.parse body
205
+ return body["data"]["score"].strip
206
+ rescue Exception => e
207
+ return "0.0"
208
+ end
209
+ end
210
+ =end
211
+ end
212
+ end
data/lib/qunar/rank.rb ADDED
@@ -0,0 +1,173 @@
1
+ #require 'rubygems'
2
+ require 'capybara'
3
+ #require 'selenium-webdriver'
4
+ require 'nokogiri'
5
+ require 'capybara-webkit'
6
+
7
+ #headless = Headless.new
8
+ #headless.start
9
+ Capybara.current_driver = :webkit
10
+ Capybara.default_selector = :xpath
11
+ Capybara.app_host = 'http://hotel.qunar.com'
12
+
13
+
14
+ module Qunar
15
+ class Rank
16
+ include Capybara::DSL
17
+
18
+ def initialize(hotelId)
19
+ raise "id should be string" if !hotelId.instance_of?(String)
20
+ @HotelSEQ = hotelId #hotelId is "cityurl_hotelcode"
21
+ @cityurl = hotelId[0..hotelId.rindex("_",-1)-1]
22
+ @hotelcode = hotelId[hotelId.rindex("_",-1)+1..hotelId.length]
23
+ @uri = URI(File.join('/city', @cityurl, "dt-#{@hotelcode}"))
24
+ visit @uri
25
+ all('//*[text()="展开报价"]').each do |btn|
26
+ btn.click
27
+ end
28
+ #@page = Capybara.current_session.driver.browser.page_source #use when choose capybara driver selenium
29
+ @page = Capybara.current_session.driver.browser.body #use when choose capybara driver webkit
30
+ @hotel = Nokogiri::HTML @page
31
+ File.open("test1.html","w") do |file|
32
+ file.puts @page
33
+ end
34
+ end
35
+ =begin
36
+ File.open("test1.html","w") do |file|
37
+ file.puts @page
38
+ end
39
+ =end
40
+
41
+ def room
42
+ room = {}
43
+ @hotel.search("//ul[@class='htl-type-list clrfix']/li").each do |li|
44
+ type = li.search("span[@class='type-name']").first.text.strip
45
+
46
+ li.search("div[@class='similar-type-agent-list']/div/div").each do |row|
47
+ ota_pic = row.search("div[@class='agent-pic']/img").first['src'].strip
48
+
49
+ bookable = row.search("a[@class='btn-book']/span").first.text.strip
50
+
51
+ insurance = row.search("p[@class='dbt-ct']").first
52
+ if insurance == nil
53
+ insurance = false
54
+ else
55
+ insurance = true
56
+ end
57
+
58
+ coupon = row.search("span[@class='fan']/em[@class='pr'] |span[@class='fan laps']/em[@class='pr']").first
59
+ if coupon == nil
60
+ coupon = '0'
61
+ else
62
+ coupon = coupon.text.sub(/¥/,'').strip
63
+ end
64
+
65
+ prepay = row.search("span[@title='需要预先支付房款']").first
66
+ if prepay == nil
67
+ prepay = false
68
+ else
69
+ prepay = true
70
+ end
71
+
72
+ price = row.search("p[@class='final-price ']/b").first.text.strip
73
+ neat_price = row.search("p[@class='count_pr']").first.text
74
+
75
+ puts "#{type} #{ota_pic} #{price} #{neat_price} #{coupon} #{prepay} #{insurance} #{bookable}"
76
+ end
77
+
78
+ end
79
+
80
+ return 0
81
+ end
82
+
83
+
84
+ end
85
+ end
86
+
87
+
88
+
89
+ =begin
90
+ require 'nokogiri'
91
+ require 'headless'
92
+ require 'capybara'
93
+ require 'capybara/dsl'
94
+ module Qunar
95
+ class Rank
96
+ include Capybara::DSL
97
+ BASEURI = "http://hotel.qunar.com"
98
+ def initialize(hotelId)
99
+ raise "id should be string" if !hotelId.instance_of?(String) #ckeck the whether hotelId is a string
100
+ @HotelSEQ = hotelId #hotelId is "cityurl_hotelcode"
101
+ @cityurl = hotelId[0..hotelId.rindex("_",-1)-1]
102
+ @hotelcode = hotelId[hotelId.rindex("_",-1)+1..hotelId.length]
103
+ end
104
+
105
+ def parse_mixkey
106
+ uri = URI(File.join(BASEURI, 'city', @cityurl, "dt-#{@hotelcode}")) #ex:http://hotel.qunar.com/city/beijing_city/dt-2933/
107
+ http_res = HTTParty.get uri.to_s
108
+ res = Nokogiri::HTML http_res
109
+ node = res.search('//span[@id="eyKxim"]').first
110
+ return nil if node.nil?
111
+ return node.text
112
+ end
113
+
114
+ def set_cookies
115
+ headless = Headless.new
116
+ headless.start
117
+ Capybara.current_driver = :selenium
118
+ Capybara.app_host = BASEURI
119
+ Capybara.default_wait_time = 10
120
+ begin
121
+ visit "/city/#{@cityurl}/dt-#{@hotelcode}/"
122
+ rescue Errno::ECONNREFUSED => e
123
+ raise
124
+ end
125
+ @cookies = {}
126
+ Capybara.current_session.driver.browser.manage.all_cookies.each { |cookie| @cookies[cookie[:name]] = cookie[:value] }
127
+ end
128
+
129
+ def load_price_ajax
130
+ mixKey = parse_mixkey
131
+ set_cookies
132
+ raise QunarMixKeyParsedException if mixKey.nil?
133
+ uri = URI(File.join(BASEURI, 'render', 'detailV2.jsp'))
134
+ params = {:fromDate=>Date.today+2, :toDate=>Date.today+3, :cityurl=>@cityurl, :HotelSEQ=>@HotelSEQ, :mixKey=>mixKey}
135
+ headers = Hash.new
136
+ headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1; rv:26.0) Gecko/20100101 Firefox/26.0'
137
+ headers['Connection'] = 'keep-alive'
138
+ headers['Accept-Encoding'] = 'gzip, deflate'
139
+ headers['Cookie'] = @cookies.map{|k, v| k+'='+v}.join('; ')
140
+ uri.query = URI.encode_www_form(params)
141
+ res = HTTParty.get(uri.to_s, :headers=>headers)
142
+ File.open("test1.html","w") do |file|
143
+ puts res
144
+ end
145
+
146
+ json_ajax = parse_json_from_response_body(res.body)
147
+ if !json_ajax['errcode'].nil? and json_ajax['errcode'].eql?110
148
+ raise QunarIpBlockException,json_ajax
149
+ end
150
+ raise QunarIpBlockException,json_ajax if !json_ajax['errcode'].nil? and json_ajax['errcode'].eql?110
151
+ @ranks = json_ajax['result'].values
152
+ end
153
+
154
+ def rank(ota, room)
155
+ @ranks.each { |rank| return rank[15]+1 if rank[3].eql?room and rank[6].eql?ota and rank[9].eql?1 }
156
+ return nil
157
+ end
158
+
159
+ def rooms
160
+ @rooms ||= @ranks.map { |e| e[3] }.uniq
161
+ end
162
+
163
+ def otas
164
+ @otas ||= @ranks.map{|e| e[6] }.uniq
165
+ end
166
+
167
+ def parse_json_from_response_body(res)
168
+ JSON.parse(res.gsub(/[()]/,""))
169
+ end
170
+
171
+ end
172
+ end
173
+ =end
@@ -0,0 +1,3 @@
1
+ module Qunar
2
+ VERSION = "0.0.1"
3
+ end
data/lib/qunar.rb ADDED
@@ -0,0 +1,7 @@
1
+ require_relative 'qunar/version'
2
+ require_relative 'qunar/hotel'
3
+ require_relative 'qunar/rank'
4
+
5
+ module Qunar
6
+ # Your code goes here...
7
+ end
data/qunar.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'qunar/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "qunar"
8
+ spec.version = Qunar::VERSION
9
+ spec.authors = ["JusticeChow"]
10
+ spec.email = ["zhengyi.zhou@corp.elong.com"]
11
+ spec.summary = %q{去哪酒店数据明细}
12
+ spec.description = %q{包含去哪酒店基本信息以及各ota报价信息}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qunar
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - JusticeChow
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: 包含去哪酒店基本信息以及各ota报价信息
42
+ email:
43
+ - zhengyi.zhou@corp.elong.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - lib/qunar.rb
54
+ - lib/qunar/hotel.rb
55
+ - lib/qunar/rank.rb
56
+ - lib/qunar/version.rb
57
+ - qunar.gemspec
58
+ homepage: ''
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.3.0
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: 去哪酒店数据明细
82
+ test_files: []