qunar 0.0.32 → 0.1.37
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -2
- data/lib/qunar/hotel.rb +0 -2
- data/lib/qunar/hotel_list.rb +109 -0
- data/lib/qunar/rank.rb +113 -51
- data/lib/qunar/version.rb +1 -1
- data/lib/qunar.rb +17 -1
- data/qunar.gemspec +1 -0
- data/spec/hotel_list_spec.rb +8 -0
- data/spec/hotel_spec.rb +1 -1
- data/spec/rank_spec.rb +21 -23
- data/spec/spec_helper.rb +1 -1
- metadata +20 -5
- data/spec/samples/qunar_hotel.html +0 -862
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 851aeecc15e69334b7f294ee335552a76c0527b1
|
4
|
+
data.tar.gz: abac57dec98f03e9454b267ebda9f759b2ba76c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 310aab733356aaa23ffc2b420ba70f06e4ef9efb1a6f497d0c992f178e2d23e72c3e9b94abd10c814594d8f8c01ee8f4201bbd7e28716afe423018e63869cb80
|
7
|
+
data.tar.gz: fbb907544e968ee7e06080ee2ad7d3e17c7b9be9723740b10c49b6ee1fefd0e378f761bc50c5cc00604a248beacc8e8fbf8b466e8f4858125317e7382e808280
|
data/Gemfile
CHANGED
data/lib/qunar/hotel.rb
CHANGED
@@ -0,0 +1,109 @@
|
|
1
|
+
module Qunar
|
2
|
+
class HotelList
|
3
|
+
|
4
|
+
def initialize(city_url)
|
5
|
+
@city = city_url
|
6
|
+
end
|
7
|
+
|
8
|
+
# Call ajax for more hotels of each page
|
9
|
+
def hotels_in_ajax(page_id)
|
10
|
+
sleep(2) # sleep for 2 seconds
|
11
|
+
@url = "http://touch.qunar.com//h5/hotel/hotellist?cityUrl=#{@city}&page=#{page_id}&tpl=hotel.hotelListTpl"
|
12
|
+
page = HTTParty.get(@url.to_s)
|
13
|
+
@html = Nokogiri::HTML page
|
14
|
+
pois = @html.xpath("//li[@class='qn_bt']")
|
15
|
+
if !pois.empty?
|
16
|
+
hotels = pois.collect { |hotel|
|
17
|
+
title = hotel.at("./div[@class='info qn_arrow_grey r']/div[@class='title']")
|
18
|
+
item = { :city=>@city, :hotel_id=>hotel['data-seq'], :hotel_name=>title.nil? ? nil : title.text.strip }
|
19
|
+
}
|
20
|
+
end
|
21
|
+
hotels
|
22
|
+
end
|
23
|
+
|
24
|
+
=begin
|
25
|
+
include Capybara::DSL
|
26
|
+
|
27
|
+
|
28
|
+
def initialize(city_en)
|
29
|
+
raise ArgumentError, "initizlize: Argument should be string " if !city_en.instance_of?(String)
|
30
|
+
#Global Setting
|
31
|
+
Capybara.run_server = false
|
32
|
+
Capybara.current_driver = :webkit #selenium/poltergeist
|
33
|
+
|
34
|
+
# Use XPath as the default selector for the find method
|
35
|
+
Capybara.default_selector = :xpath
|
36
|
+
|
37
|
+
Capybara.app_host = 'http://hotel.qunar.com'
|
38
|
+
# Set user agent
|
39
|
+
page.driver.header 'User-Agent', "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
|
40
|
+
|
41
|
+
# For poltergeist
|
42
|
+
#page.driver.headers={'User-Agent'=> "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"}
|
43
|
+
|
44
|
+
@city = city_en
|
45
|
+
# log msg
|
46
|
+
puts "正在访问: http://hotel.qunar.com/city/#{@city}"
|
47
|
+
page.visit "/city/#{@city}"
|
48
|
+
@page = Nokogiri::HTML page.html
|
49
|
+
end
|
50
|
+
|
51
|
+
# Wait for ajax, a selector must be passed as capybara will wait for the element
|
52
|
+
def wait_for_ajax(selector)
|
53
|
+
puts "\e[32m Waiting for ajax...\e[0m"
|
54
|
+
# Retry 3 times at most, if still not found, give up
|
55
|
+
limiter = 0
|
56
|
+
begin
|
57
|
+
page.find(selector)
|
58
|
+
rescue Capybara::ElementNotFound
|
59
|
+
limiter+=1
|
60
|
+
retry if limiter<3
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def hotels_in_page
|
65
|
+
# Scroll down and trigger ajax
|
66
|
+
page.execute_script "window.scrollTo(0, document.body.scrollHeight)"
|
67
|
+
self.wait_for_ajax("//span[@class='hotel_num js_hotel_num'][text()='30']")
|
68
|
+
hotels = []
|
69
|
+
@page = Nokogiri::HTML page.driver.browser.body
|
70
|
+
@page.css("div.b_result_box").each { |hotel|
|
71
|
+
item = {:city => @city, :hotel_id => hotel['data-id']}
|
72
|
+
item[:hotel_name] = hotel.search("a[@class='e_title js_list_name']").first.text
|
73
|
+
hotels << item
|
74
|
+
}
|
75
|
+
hotels
|
76
|
+
end
|
77
|
+
|
78
|
+
# click `下一页` to navigate to next page
|
79
|
+
def click_next?
|
80
|
+
next_button = page.all("//li[@class='item next ']/a").first
|
81
|
+
return false if next_button.nil?
|
82
|
+
puts "Next page"
|
83
|
+
next_button.click
|
84
|
+
self.wait_for_ajax("//span[@class='hotel_num js_hotel_num'][text()='15']")
|
85
|
+
return true
|
86
|
+
end
|
87
|
+
|
88
|
+
# Get the page number
|
89
|
+
def page_count
|
90
|
+
a_node = @page.css("li.pager_count")
|
91
|
+
a_node.empty? ? 0 : a_node.first.text.split('/')[1].to_i
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get the screen_shot
|
95
|
+
def screen_shot
|
96
|
+
page.save_screenshot("#{Time.now}.png")
|
97
|
+
end
|
98
|
+
=end
|
99
|
+
|
100
|
+
# Html file
|
101
|
+
def html
|
102
|
+
@html
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
|
data/lib/qunar/rank.rb
CHANGED
@@ -1,68 +1,66 @@
|
|
1
|
-
require 'capybara'
|
2
|
-
require 'nokogiri'
|
3
|
-
require 'capybara/poltergeist'
|
4
|
-
#require 'capybara-webkit'
|
5
|
-
#require 'selenium-webdriver'
|
6
|
-
|
7
1
|
module Qunar
|
8
2
|
class Rank
|
9
3
|
include Capybara::DSL
|
10
|
-
|
4
|
+
|
11
5
|
def initialize(hotelId)
|
12
|
-
|
13
6
|
raise "id should be string" if !hotelId.instance_of?(String)
|
14
|
-
Capybara.current_driver = :
|
7
|
+
Capybara.current_driver = :webkit # :selenium/:poltergeist
|
15
8
|
Capybara.default_selector = :xpath
|
16
9
|
Capybara.app_host = 'http://hotel.qunar.com'
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
|
11
|
+
# Header for webkit
|
12
|
+
page.driver.header 'User-Agent', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.77.4 (KHTML, like Gecko) Version/7.0.5 Safari/537.77.4"
|
13
|
+
|
14
|
+
@HotelSEQ = hotelId #hotelId is "cityurl_hotelcode"
|
15
|
+
@cityurl, suffix, @hotelcode = hotelId.rpartition('_')
|
21
16
|
@uri = URI(File.join('/city', @cityurl, "dt-#{@hotelcode}"))
|
22
|
-
visit @uri
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
17
|
+
page.visit @uri
|
18
|
+
|
19
|
+
limiter = 0
|
20
|
+
begin
|
21
|
+
find("//td[@class='book-ct']//*[text()='展开报价']")
|
22
|
+
page.all('//td[@class="book-ct"]//*[text()="展开报价"] | //td[@class="book-ct"]//*[text()="全部订完"]').each do |spage|
|
23
|
+
puts 'cp 2-1'
|
24
|
+
spage.click
|
25
|
+
puts 'cp 2-2'
|
26
|
+
end
|
27
|
+
puts 'cp 3'
|
28
|
+
# Expand hidden otas
|
29
|
+
page.all("//div[@class='more-quote js-room-more']/a").each do |link|
|
30
|
+
link.click
|
31
|
+
end
|
32
|
+
rescue =>e
|
33
|
+
limiter+=1
|
34
|
+
retry if limiter<3
|
35
|
+
raise e
|
37
36
|
end
|
38
|
-
|
37
|
+
|
39
38
|
#@page = Capybara.current_session.driver.browser.page_source #use when choose capybara driver selenium
|
40
|
-
@
|
41
|
-
@hotel = Nokogiri::HTML @page
|
42
|
-
|
39
|
+
@hotel = Nokogiri::HTML page.html #use when choose capybara driver webkit
|
43
40
|
end
|
44
41
|
|
42
|
+
# Get the rooms details
|
45
43
|
def rooms
|
46
44
|
rooms = []
|
47
45
|
|
48
46
|
# room
|
49
|
-
@hotel.search("//li[@class='default-type defaultpricetype similar-expand']").each do |li|
|
47
|
+
@hotel.search("//li[@class='default-type defaultpricetype similar-expand' or @class='default-type defaultpricetype similar-expand b_result_item_on']").each do |li|
|
50
48
|
#puts 'one roomtype found'
|
51
49
|
room = {}
|
52
50
|
type = li.search("span[@class='type-name js-p-name']").first.text.strip
|
53
|
-
room[
|
54
|
-
room[
|
51
|
+
room[:room_type] = type
|
52
|
+
room[:otas] = []
|
55
53
|
# ota
|
56
54
|
li.search("div[@class='similar-type-agent-list']/div/div").each do |row|
|
57
55
|
otas = {}
|
58
56
|
|
59
57
|
ota = row.search("div[@class='profile-tit']").first
|
60
58
|
ota = ota.text.strip
|
61
|
-
otas[
|
59
|
+
otas[:ota] = ota
|
62
60
|
|
63
61
|
bookable = row.search("a[@class='btn-book']/span")
|
64
62
|
unless bookable.empty?
|
65
|
-
bookable
|
63
|
+
bookable = bookable.first.text.strip
|
66
64
|
if bookable == '订完'
|
67
65
|
bookable = false
|
68
66
|
else
|
@@ -71,15 +69,23 @@ module Qunar
|
|
71
69
|
else
|
72
70
|
bookable = true
|
73
71
|
end
|
74
|
-
otas[
|
72
|
+
otas[:bookable] = bookable
|
75
73
|
|
76
|
-
insurance = row.search("
|
74
|
+
insurance = row.search("a[@class='js-guarantee-plan']").first
|
77
75
|
if insurance == nil
|
78
76
|
insurance = false
|
79
77
|
else
|
80
78
|
insurance = true
|
81
79
|
end
|
82
|
-
otas[
|
80
|
+
otas[:safe] = insurance
|
81
|
+
|
82
|
+
guarantee = row.search("cite[text()='需担保']").first
|
83
|
+
if guarantee == nil
|
84
|
+
guarantee = false
|
85
|
+
else
|
86
|
+
guarantee = true
|
87
|
+
end
|
88
|
+
otas[:guarantee] = guarantee
|
83
89
|
|
84
90
|
coupon = row.search("span[@class='fan']/em[@class='pr']").first
|
85
91
|
if coupon == nil
|
@@ -87,18 +93,15 @@ module Qunar
|
|
87
93
|
else
|
88
94
|
coupon = coupon.text.sub(/¥/,'').strip.to_i
|
89
95
|
end
|
90
|
-
otas[
|
91
|
-
|
96
|
+
otas[:coupon] = coupon
|
97
|
+
|
92
98
|
reduce = row.search("span[@class='fan lapse']/em[@class='pr']").first
|
93
99
|
if reduce == nil
|
94
100
|
reduce = 0
|
95
101
|
else
|
96
102
|
reduce = reduce.text.sub(/¥/,'').strip.to_i
|
97
103
|
end
|
98
|
-
otas[
|
99
|
-
|
100
|
-
reserve_detail = row.search("div[@class='clrfix order-detail']").first.text.strip
|
101
|
-
otas['reserve_detail'] = reserve_detail
|
104
|
+
otas[:reduce] = reduce
|
102
105
|
|
103
106
|
prepay = row.search("span[@title='需要预先支付房款']").first
|
104
107
|
if prepay == nil
|
@@ -106,17 +109,16 @@ module Qunar
|
|
106
109
|
else
|
107
110
|
prepay = true
|
108
111
|
end
|
109
|
-
otas[
|
110
|
-
|
112
|
+
otas[:prepay] = prepay
|
111
113
|
|
112
114
|
|
113
115
|
price = row.search("p[@class='final-price ']/b").first.text.strip
|
114
116
|
neat_price = row.search("p[@class='count_pr']").first.children[1].to_s
|
115
117
|
|
116
|
-
otas[
|
117
|
-
otas[
|
118
|
+
otas[:original_price] = price.to_i
|
119
|
+
otas[:final_price] = neat_price.to_i
|
118
120
|
|
119
|
-
room[
|
121
|
+
room[:otas] << otas
|
120
122
|
end
|
121
123
|
rooms << room
|
122
124
|
|
@@ -124,5 +126,65 @@ module Qunar
|
|
124
126
|
return rooms
|
125
127
|
end
|
126
128
|
|
129
|
+
# Get the Chinese name of the hotel
|
130
|
+
def name
|
131
|
+
name = @hotel.search("//div[@class='htl-info fr']//span")
|
132
|
+
if name.empty?
|
133
|
+
name = '该酒店不存在'
|
134
|
+
else
|
135
|
+
name = name.first.text.strip
|
136
|
+
end
|
137
|
+
return name
|
138
|
+
end
|
139
|
+
|
140
|
+
# Get the level of the hotel
|
141
|
+
def star
|
142
|
+
name_tag = @hotel.search('//div[@class="htl-info fr"]//em[@class="dangci"]').first
|
143
|
+
return 0 if name_tag.nil?
|
144
|
+
if name_tag.text.include?'经济型'
|
145
|
+
1
|
146
|
+
elsif name_tag.text.include?'舒适型'
|
147
|
+
3
|
148
|
+
elsif name_tag.text.include?'高档型'
|
149
|
+
4
|
150
|
+
elsif name_tag.text.include?'豪华型'
|
151
|
+
5
|
152
|
+
elsif name_tag.text.include?'star20'
|
153
|
+
2
|
154
|
+
elsif name_tag.text.include?'star50'
|
155
|
+
5
|
156
|
+
else
|
157
|
+
0
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Get the Chinese name of the City
|
162
|
+
def citynameCn
|
163
|
+
page.evaluate_script("(function f() { return cityName; }());")
|
164
|
+
end
|
165
|
+
|
166
|
+
# Get the English name of the City
|
167
|
+
def cityNameEn
|
168
|
+
page.evaluate_script("(function f() { return cityNameEn; }());")
|
169
|
+
end
|
170
|
+
|
171
|
+
# Get the Hotel details
|
172
|
+
def hotelInfo
|
173
|
+
|
174
|
+
{ :hotel_id => @HotelSEQ, :hotel_name => self.name,
|
175
|
+
:city => self.cityNameEn, :city_cn => self.citynameCn,
|
176
|
+
:star => self.star }
|
177
|
+
end
|
178
|
+
|
179
|
+
# Get the screen_shot
|
180
|
+
def screen_shot
|
181
|
+
page.save_screenshot("#{Time.now}.png")
|
182
|
+
end
|
183
|
+
|
184
|
+
# Html file
|
185
|
+
def html
|
186
|
+
@hotel
|
187
|
+
end
|
188
|
+
|
127
189
|
end
|
128
190
|
end
|
data/lib/qunar/version.rb
CHANGED
data/lib/qunar.rb
CHANGED
@@ -1,7 +1,23 @@
|
|
1
|
+
require 'capybara'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'httparty'
|
5
|
+
require 'capybara-webkit'
|
1
6
|
require 'qunar/version'
|
2
7
|
require 'qunar/hotel'
|
3
8
|
require 'qunar/rank'
|
9
|
+
require 'qunar/hotel_list'
|
4
10
|
|
5
11
|
module Qunar
|
6
|
-
|
12
|
+
# City list
|
13
|
+
def self.city
|
14
|
+
pages = Nokogiri::HTML(open(URI('http://hotel.qunar.com/sitemap/')))
|
15
|
+
@city_list = []
|
16
|
+
pages.xpath("//li/a").each do |li|
|
17
|
+
item = {:city_Cn=>li.text, :city_En=>li['href'][/\w+/]}
|
18
|
+
@city_list << item
|
19
|
+
end
|
20
|
+
@city_list
|
21
|
+
end
|
22
|
+
|
7
23
|
end
|
data/qunar.gemspec
CHANGED
data/spec/hotel_spec.rb
CHANGED
data/spec/rank_spec.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Qunar::Rank do
|
4
4
|
sample = Qunar::Rank.new('beijing_city_2933')
|
5
|
-
|
6
|
-
sz_sample = Qunar::Rank.new('shenzhen_6993')
|
7
|
-
|
5
|
+
p sample.rooms
|
8
6
|
it "has 7 rooms" do
|
9
7
|
# when directly check the hash object the Chinese charactervalue is saved as format like "\u6807\u51C6\u53CC\u5E8A\u623F", it is not been parsed here, so it is not equal to chinese charactor, it's just a sequnce of coding,it needs to be parse,then it could show as Chinese character.
|
10
8
|
# room = {"room_type" => "\u6807\u51C6\u53CC\u5E8A\u623F", "ota" => "\u827A\u9F99\u65C5\u884C\u7F51", "bookable" => "\u9884\u8BA2", "insurance" => true, "coupon" => "0", "prepay" => false, "price" => "918", "neat_price" => "918"}
|
@@ -12,88 +10,88 @@ describe Qunar::Rank do
|
|
12
10
|
end
|
13
11
|
|
14
12
|
it "first room names '标准双床房'" do
|
15
|
-
expect(sample.rooms.first[
|
13
|
+
expect(sample.rooms.first[:room_type]).to eq '标准双床房'
|
16
14
|
end
|
17
15
|
|
18
16
|
it "second room names '标准大床房'" do
|
19
|
-
expect(sample.rooms[1][
|
17
|
+
expect(sample.rooms[1][:room_type]).to eq '标准大床房'
|
20
18
|
end
|
21
19
|
|
22
20
|
|
23
21
|
|
24
22
|
it "has 20 otas for the first room type '标准双床房'" do
|
25
|
-
expect(sample.rooms.first[
|
23
|
+
expect(sample.rooms.first[:otas].size).to eq 20
|
26
24
|
end
|
27
25
|
|
28
26
|
it "has 20 otas for the second room type '标准大床房'" do
|
29
|
-
expect(sample.rooms[1][
|
27
|
+
expect(sample.rooms[1][:otas].size).to eq 20
|
30
28
|
end
|
31
29
|
|
32
30
|
|
33
31
|
it "first ota of first roomtype names '艺龙旅行网'" do
|
34
32
|
#puts subject.rooms.first['otas'].first['ota']
|
35
|
-
expect(sample.rooms.first[
|
33
|
+
expect(sample.rooms.first[:otas].first[:ota]).to eq '艺龙旅行网'
|
36
34
|
end
|
37
35
|
|
38
36
|
|
39
37
|
it "first ota of second roomtype names Expedia" do
|
40
38
|
#puts subject.rooms.first['otas'].first['ota']
|
41
|
-
expect(sample.rooms[1][
|
39
|
+
expect(sample.rooms[1][:otas].first[:ota]).to eq 'Booking.com'
|
42
40
|
end
|
43
41
|
|
44
42
|
it "first ota of first roomtype is bookable" do
|
45
|
-
expect(sample.rooms.first[
|
43
|
+
expect(sample.rooms.first[:otas].first[:bookable]).to eq true
|
46
44
|
end
|
47
45
|
|
48
46
|
it "last ota of first roomtype is not bookable" do
|
49
|
-
expect(sample.rooms.first[
|
47
|
+
expect(sample.rooms.first[:otas][-1][:bookable]).to eq false
|
50
48
|
end
|
51
49
|
|
52
50
|
|
53
51
|
it "first ota of first roomtype need insurance" do
|
54
|
-
expect(sample.rooms.first[
|
52
|
+
expect(sample.rooms.first[:otas].first[:safe]).to eq true
|
55
53
|
end
|
56
54
|
|
57
55
|
it "second ota of first roomtype not need insurance" do
|
58
|
-
expect(sample.rooms.first[
|
56
|
+
expect(sample.rooms.first[:otas][1][:safe]).to eq false
|
59
57
|
end
|
60
58
|
|
61
59
|
it "first ota of first roomtype coupon is 0" do
|
62
|
-
expect(sample.rooms.first[
|
60
|
+
expect(sample.rooms.first[:otas].first[:coupon]).to eq 0
|
63
61
|
end
|
64
62
|
|
65
63
|
it "first ota of first roomtype in shenzhen coupon is 40" do
|
66
|
-
expect(sz_sample.rooms.first[
|
64
|
+
expect(sz_sample.rooms.first[:otas].first[:coupon]).to eq 40
|
67
65
|
end
|
68
66
|
|
69
67
|
it "first ota of first roomtype reserve_detail is '标准双床房 - 仅提供住宿 - 免费取消'" do
|
70
|
-
expect(sample.rooms.first[
|
68
|
+
expect(sample.rooms.first[:otas].first[:reserve_detail]).to eq '标准双床房 - 仅提供住宿 - 免费取消'
|
71
69
|
end
|
72
70
|
|
73
71
|
|
74
72
|
it "first ota of first roomtype need prepay" do
|
75
|
-
expect(sample.rooms.first[
|
73
|
+
expect(sample.rooms.first[:otas][2][:prepay]).to eq true
|
76
74
|
end
|
77
75
|
|
78
76
|
it "second ota of first roomtype not need prepay" do
|
79
|
-
expect(sample.rooms.first[
|
77
|
+
expect(sample.rooms.first[:otas][1][:prepay]).to eq false
|
80
78
|
end
|
81
79
|
|
82
80
|
it "first ota of first roomtype price" do
|
83
|
-
expect(sample.rooms.first[
|
81
|
+
expect(sample.rooms.first[:otas].first[:original_price]).to eq 918
|
84
82
|
end
|
85
83
|
|
86
84
|
it "fifth ota of first roomtype price" do
|
87
|
-
expect(sample.rooms.first[
|
85
|
+
expect(sample.rooms.first[:otas][4][:original_price]).to eq 638
|
88
86
|
end
|
89
87
|
|
90
88
|
it "first ota of first roomtype neat_price" do
|
91
|
-
expect(sample.rooms.first[
|
89
|
+
expect(sample.rooms.first[:otas].first[:final_price]).to eq 918
|
92
90
|
end
|
93
91
|
|
94
92
|
it "sixth ota of first roomtype neat_price" do
|
95
93
|
#puts subject.rooms.first['otas'][5]['neat_price']
|
96
|
-
expect(sample.rooms.first[
|
94
|
+
expect(sample.rooms.first[:otas][4][:final_price]).to eq 734
|
97
95
|
end
|
98
96
|
|
99
97
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qunar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.37
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JusticeChow
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.1.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.1.0
|
41
55
|
description: "包含去哪酒店基本信息以及各ota报价信息"
|
42
56
|
email:
|
43
57
|
- zhengyi.zhou@corp.elong.com
|
@@ -53,12 +67,13 @@ files:
|
|
53
67
|
- Rakefile
|
54
68
|
- lib/qunar.rb
|
55
69
|
- lib/qunar/hotel.rb
|
70
|
+
- lib/qunar/hotel_list.rb
|
56
71
|
- lib/qunar/rank.rb
|
57
72
|
- lib/qunar/version.rb
|
58
73
|
- qunar.gemspec
|
74
|
+
- spec/hotel_list_spec.rb
|
59
75
|
- spec/hotel_spec.rb
|
60
76
|
- spec/rank_spec.rb
|
61
|
-
- spec/samples/qunar_hotel.html
|
62
77
|
- spec/spec_helper.rb
|
63
78
|
homepage: ''
|
64
79
|
licenses:
|
@@ -80,12 +95,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
95
|
version: '0'
|
81
96
|
requirements: []
|
82
97
|
rubyforge_project:
|
83
|
-
rubygems_version: 2.
|
98
|
+
rubygems_version: 2.2.2
|
84
99
|
signing_key:
|
85
100
|
specification_version: 4
|
86
101
|
summary: "去哪酒店数据明细"
|
87
102
|
test_files:
|
103
|
+
- spec/hotel_list_spec.rb
|
88
104
|
- spec/hotel_spec.rb
|
89
105
|
- spec/rank_spec.rb
|
90
|
-
- spec/samples/qunar_hotel.html
|
91
106
|
- spec/spec_helper.rb
|