weatherscout 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b0d63da54f05eea838d5a10bed697dcd1d735eb
4
- data.tar.gz: db40952ef17dee2abf0ebe33df5ec1a0fd8d3dc2
3
+ metadata.gz: 2af3cc5c390cc4e5a9817b474ab059230a767041
4
+ data.tar.gz: 99b4a96130932e19941e0541eddd1c93d80a7413
5
5
  SHA512:
6
- metadata.gz: 4587da3cc3e1945bfb4285c792f5032d07c11925112e4de641ba7aa08761e5ed0a3b7e7af6a99bd78e19bd23a0d5aa7e2c7ba909f25f698e633b1233ffd9c793
7
- data.tar.gz: 86e041ebf87ee31d42b40714a3386911661064fa0550cd798d46e8a4ee9cb1da13c236d4eb4c7ae74e358142bba4bb3c421bf6b2abb5cd7f3ff62049b003f97e
6
+ metadata.gz: 0c375ce7327f53c051819d3f02092527cbbfad7ea5977ac7f14d43e5ba09eb83d689cde40c1374028ab499d755ace21c51f9c4b4ccbe1be8755f2e72cf13e394
7
+ data.tar.gz: c65150ec72d3c362dc693cbcfd28486fb57a095003b0fb7484c563f358339bd56b14f409eeca9664da0525a1e928faf5f52b4d22e89cf3be18870006dd46a837
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ source 'https://rubygems.org'
3
3
  gem 'oga'
4
4
  gem 'minitest'
5
5
  gem 'thor'
6
+ gem 'vcr'
7
+ gem 'webmock'
6
8
 
7
9
  group :test do
8
10
  gem 'rake'
data/README.md CHANGED
@@ -15,34 +15,144 @@ $ gem install weatherscout
15
15
  To see the weather today
16
16
  ```sh
17
17
  $ weatherscout today 新竹
18
- 新竹(01/01)天氣狀況:
19
- 白天氣象:多雲,氣溫 15 ~ 16 度
20
- 晚上氣象:多雲,氣溫 15 ~ 23
21
- 降雨機率:0 %
18
+ 新竹(HsinchuCity)的天氣預測:
19
+ 今晚至明晨 01/21 00:00~01/21 06:00
20
+ -氣溫:15 ~ 16
21
+ -降雨機率:70 %
22
+ -天氣狀況:多雲短暫雨
23
+ 明日白天 01/21 06:00~01/21 18:00
24
+ -氣溫:15 ~ 18 度
25
+ -降雨機率:60 %
26
+ -天氣狀況:多雲短暫雨
27
+ 明日晚上 01/21 18:00~01/22 06:00
28
+ -氣溫:15 ~ 17 度
29
+ -降雨機率:70 %
30
+ -天氣狀況:多雲時陰陣雨
22
31
  溫馨叮嚀:
23
- 清晨東北季風影響,早晚氣溫低
24
- (31)日,新竹市地區仍受東北季風影響,為多雲的天氣,空曠地區易有8至9級強陣風,香山區白天溫度在15-19度左右;外出請注意保暖及注意安全。
25
- 明(1)日,新竹市地區清晨東北季風影響,早晚氣溫低,為多雲的天氣,預報溫度在1618度之間;外出請注意保暖及注意安全。
26
- 明(1)日,新竹沿海地區風力7至8陣風10級下午轉5至6陣風8級,作業船隻及海邊活動仍請注意安全。
32
+ 東北季風及華南雲雨區影響,多雲短暫雨
33
+ (20)日,持續受大陸冷氣團影響,氣溫較低,水氣增加,為多雲時陰有短暫雨的天氣,清晨起,局部地區已有短暫陣雨發生。
34
+ (21)日,受東北季風及華南雲雨區影響,氣溫略回升,為多雲短暫雨的天氣。預估氣溫16-18度,空曠地區有6至8級強陣風;清晨部分地區有短暫陣雨,外出請注意保暖和強風及攜帶雨具備用。
27
35
  ```
28
36
 
29
- The weather in the future week and other feature will be coming soon! :grinning:
37
+ To see the weather in the future week
38
+ ```sh
39
+ ➜ weather-scout-scraper git:(weekly-weather) ✗ ./bin/weatherscout week 新竹
40
+ 新竹(HsinchuCity)的未來一週預測:
41
+ 01/23星期六
42
+ -白天溫度:8 ~ 12 度
43
+ -白天天氣狀況:陰時多雲陣雨
44
+ -晚上溫度:6 ~ 8 度
45
+ -晚上天氣狀況:陰時多雲短暫雨
46
+ 01/24星期日
47
+ -白天溫度:5 ~ 7 度
48
+ -白天天氣狀況:多雲短暫雨
49
+ -晚上溫度:4 ~ 5 度
50
+ -晚上天氣狀況:多雲
51
+ 01/25星期一
52
+ -白天溫度:4 ~ 10 度
53
+ -白天天氣狀況:多雲時晴
54
+ -晚上溫度:8 ~ 9 度
55
+ -晚上天氣狀況:晴時多雲
56
+ 01/26星期二
57
+ -白天溫度:8 ~ 18 度
58
+ -白天天氣狀況:多雲時晴
59
+ -晚上溫度:13 ~ 15 度
60
+ -晚上天氣狀況:晴時多雲
61
+ 01/27星期三
62
+ -白天溫度:12 ~ 19 度
63
+ -白天天氣狀況:多雲時陰
64
+ -晚上溫度:15 ~ 16 度
65
+ -晚上天氣狀況:陰時多雲短暫陣雨
66
+ 01/28星期四
67
+ -白天溫度:15 ~ 18 度
68
+ -白天天氣狀況:多雲時陰短暫陣雨
69
+ -晚上溫度:15 ~ 16 度
70
+ -晚上天氣狀況:陰短暫陣雨
71
+ 01/29星期五
72
+ -白天溫度:15 ~ 18 度
73
+ -白天天氣狀況:陰短暫陣雨
74
+ -晚上溫度:15 ~ 16 度
75
+ -晚上天氣狀況:陰天
76
+ ```
30
77
 
31
78
  ## Development
32
79
  Use it from your Ruby code:
80
+ #### DailyWeather
33
81
  ````ruby
34
82
  require 'weatherscout'
35
83
  CITY = "新竹"
36
- weather = DailyWeatherScraper::DailyWeather.new(CITY)
84
+ daily_weather = DailyWeatherScraper::DailyWeather.new(CITY)
85
+
86
+ city = daily_weather.city
87
+ # ""HsinchuCity""
37
88
 
38
- temp = weather.temperature_day
39
- puts "今天白天氣溫:#{temp}"
89
+ weathers = daily_weather.weathers
90
+ # {"今晚至明晨 01/21 00:00~01/21 06:00"=>
91
+ # {"temperature"=>"15 ~ 16",
92
+ # "rain_probability"=>"70 %",
93
+ # "condition"=>"多雲短暫雨"},
94
+ # "明日白天 01/21 06:00~01/21 18:00"=>
95
+ # {"temperature"=>"15 ~ 18",
96
+ # "rain_probability"=>"60 %",
97
+ # "condition"=>"多雲短暫雨"},
98
+ # "明日晚上 01/21 18:00~01/22 06:00"=>
99
+ # {"temperature"=>"15 ~ 17",
100
+ # "rain_probability"=>"70 %",
101
+ # "condition"=>"多雲時陰陣雨"}}
40
102
 
41
- tips = weather.tips
42
- puts "溫馨提示:\n#{tips}"
103
+ tips = daily_weather.tips
104
+ # "東北季風及華南雲雨區影響,多雲短暫雨\n昨 (20)日,持續受大陸冷氣團影響,氣溫較低,水氣增加,為多雲時陰有短暫雨的天氣,清晨起,局部地區已有短暫陣雨發生。\n明 (21)日,受東北季風及華南雲雨區影響,氣溫略回升,為多雲短暫雨的天氣。預估氣溫16-18度,空曠地區有6至8級強陣風;清晨部分地區有短暫陣雨,外出請注意保暖和強風及攜帶雨具備用。\n"
43
105
 
44
106
  ````
45
107
 
108
+ ####WeeklyWeather
109
+ ```ruby
110
+ require 'weatherscout'
111
+ CITY = "新竹"
112
+ weekly_weather = WeatherScraper::WeeklyWeather.new(CITY)
113
+
114
+ city = daily_weather.city
115
+ # ""HsinchuCity""
116
+
117
+ weathers = daily_weather.weathers
118
+ # {"01/23星期六"=>{
119
+ # "day_temperature"=>"8 ~ 12",
120
+ # "day_condition"=>"陰時多雲陣雨",
121
+ # "night_temperature"=>"6 ~ 8",
122
+ # "night_condition"=>"陰時多雲短暫雨"},
123
+ # "01/24星期日"=>{
124
+ # "day_temperature"=>"5 ~ 7",
125
+ # "day_condition"=>"多雲短暫雨",
126
+ # "night_temperature"=>"4 ~ 5",
127
+ # "night_condition"=>"多雲"},
128
+ # "01/25星期一"=>{
129
+ # "day_temperature"=>"4 ~ 10",
130
+ # "day_condition"=>"多雲時晴",
131
+ # "night_temperature"=>"8 ~ 9",
132
+ # "night_condition"=>"晴時多雲"},
133
+ # "01/26星期二"=>{
134
+ # "day_temperature"=>"8 ~ 18",
135
+ # "day_condition"=>"多雲時晴",
136
+ # "night_temperature"=>"13 ~ 15",
137
+ # "night_condition"=>"晴時多雲"},
138
+ # "01/27星期三"=>{
139
+ # "day_temperature"=>"12 ~ 19",
140
+ # "day_condition"=>"多雲時陰",
141
+ # "night_temperature"=>"15 ~ 16",
142
+ # "night_condition"=>"陰時多雲短暫陣雨"},
143
+ # "01/28星期四"=>{
144
+ # "day_temperature"=>"15 ~ 18",
145
+ # "day_condition"=>"多雲時陰短暫陣雨",
146
+ # "night_temperature"=>"15 ~ 16",
147
+ # "night_condition"=>"陰短暫陣雨"},
148
+ # "01/29星期五"=>{
149
+ # "day_temperature"=>"15 ~ 18",
150
+ # "day_condition"=>"陰短暫陣雨",
151
+ # "night_temperature"=>"15 ~ 16",
152
+ # "night_condition"=>"陰天"}}
153
+
154
+ ```
155
+
46
156
  ## Test
47
157
  Using [rake](http://docs.seattlerb.org/rake/) to run tests. If you don't have rake using `gem install rake` to install it.
48
158
 
data/bin/weatherscout CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'thor'
3
3
  require 'weatherscout' # for production
4
- # require './lib/weatherdesc/daily_weather.rb' # for cmd line testing purposes
4
+ # require './lib/weathers/weather_scraper/daily_weather.rb' # for cmd line testing purposes
5
+ # require './lib/weathers/weather_scraper/weekly_weather.rb' # for cmd line testing purposes
6
+
5
7
 
6
8
  class WeatherCLI < Thor
7
9
  desc 'today CITY', 'see the weather of the city today'
8
10
  def today(city)
9
- weather = DailyWeatherScraper::DailyWeather.new(city)
11
+ weather = WeatherScraper::DailyWeather.new(city)
10
12
  city_eng = weather.city
11
13
  weathers = weather.weathers
12
14
  tips = weather.tips
@@ -21,6 +23,26 @@ class WeatherCLI < Thor
21
23
  puts "溫馨叮嚀:"
22
24
  puts "#{tips}"
23
25
  end
26
+
27
+ desc 'week CITY', 'see the weather of the city this week'
28
+ def week(city)
29
+ weather = WeatherScraper::WeeklyWeather.new(city)
30
+ city_eng = weather.city
31
+ weathers = weather.weathers
32
+
33
+ day_temp = weathers.values.map {|e| e['day_temperature']}
34
+ day_cond = weathers.values.map {|e| e['day_condition']}
35
+ night_temp = weathers.values.map {|e| e['night_temperature']}
36
+ night_cond = weathers.values.map {|e| e['night_condition']}
37
+ puts "#{city}(#{city_eng})的未來一週預測:"
38
+ weathers.keys.each_index do |i|
39
+ puts "#{weathers.keys[i]}"
40
+ puts " -白天溫度:#{day_temp[i]} 度"
41
+ puts " -白天天氣狀況:#{day_cond[i]}"
42
+ puts " -晚上溫度:#{night_temp[i]} 度"
43
+ puts " -晚上天氣狀況:#{night_cond[i]}"
44
+ end
45
+ end
24
46
  end
25
47
 
26
48
  WeatherCLI.start(ARGV)
@@ -0,0 +1,5 @@
1
+ # Versioning
2
+ module WeatherDesc
3
+ VERSION = '0.3.1'
4
+ DATE = '2016-01-23'
5
+ end
@@ -0,0 +1,6 @@
1
+ require_relative './weather_scraper/weekly_weather.rb'
2
+ require_relative './weather_scraper/daily_weather.rb'
3
+ require_relative './weather_scraper/name_mapping.rb'
4
+
5
+ module WeatherScraper
6
+ end
@@ -0,0 +1,69 @@
1
+ require 'oga'
2
+ require 'open-uri'
3
+ require_relative 'name_mapping'
4
+
5
+ module WeatherScraper
6
+ # parse daily weather description from cwb website
7
+ class DailyWeather
8
+ include NameMapping
9
+ CWB_URL = "http://www.cwb.gov.tw"
10
+ CITY_WEATHER_URL = "#{CWB_URL}/V7/forecast/taiwan/"
11
+
12
+ def initialize(city)
13
+ @city = city_mapping(city).delete("_")
14
+ parse_html(city_mapping(city))
15
+ end
16
+
17
+ def city
18
+ @city
19
+ end
20
+
21
+ def weathers
22
+ @weathers ||= parse_weathers
23
+ end
24
+
25
+ def tips
26
+ @tips ||= parse_tips
27
+ end
28
+
29
+ private
30
+
31
+ def parse_html(city)
32
+ url = "#{CITY_WEATHER_URL}/#{city}.htm"
33
+ @document = Oga.parse_html(open(url))
34
+ end
35
+
36
+ def parse_weathers
37
+ data = @document.xpath("//table[@class='FcstBoxTable01']")
38
+ data[2].children[3].children.map do |weathers|
39
+ timestamp= weathers.children[1].children.text.force_encoding('UTF-8')
40
+ temperature = weathers.children[3].children.text
41
+ rain_probability = weathers.children[9].children.text
42
+ condition = weathers.children[5].children[1].attributes[1].value.force_encoding('UTF-8')
43
+ [timestamp,
44
+ {"temperature" => temperature,
45
+ "rain_probability" => rain_probability,
46
+ "condition" => condition}]
47
+ end.to_h
48
+ end
49
+
50
+ def parse_tips
51
+ data = @document.xpath("//div[@id='box8']")
52
+ tips_api = data[0].children[13].children[0].text.split("'")[1]
53
+ tips_url = "#{CWB_URL}/#{tips_api}"
54
+ tips_doc = Oga.parse_html(open(tips_url))
55
+ result = ""
56
+ tips_doc.children.each do |element|
57
+ if element.text.empty?
58
+ result << "\n"
59
+ elsif element.text.split(":")[0].force_encoding('UTF-8') == "更新時間"
60
+ break
61
+ else
62
+ result << element.text
63
+ end
64
+ end
65
+ result = result.gsub("\n\n","\n")
66
+ result.force_encoding('UTF-8')
67
+ end
68
+ end
69
+ end
@@ -1,70 +1,7 @@
1
- require 'oga'
2
- require 'open-uri'
3
-
4
- module DailyWeatherScraper
5
- # parse course description from sharecourse web
6
- class DailyWeather
7
- CWB_URL = "http://www.cwb.gov.tw"
8
- CITY_WEATHER_URL = "#{CWB_URL}/V7/forecast/taiwan/"
9
-
10
- def initialize(city)
11
- @city = name_mapping(city).delete("_")
12
- parse_html(name_mapping(city))
13
- end
14
-
15
- def city
16
- @city
17
- end
18
-
19
- def weathers
20
- @weathers ||= parse_weathers
21
- end
22
-
23
- def tips
24
- @tips ||= parse_tips
25
- end
26
-
27
- private
28
-
29
- def parse_html(city)
30
- url = "#{CITY_WEATHER_URL}/#{city}.htm"
31
- @document = Oga.parse_html(open(url))
32
- end
33
-
34
- def parse_weathers
35
- data = @document.xpath("//table[@class='FcstBoxTable01']")
36
- data[2].children[3].children.map do |weathers|
37
- timestamp= weathers.children[1].children.text.force_encoding('UTF-8')
38
- temperature = weathers.children[3].children.text
39
- rain_probability = weathers.children[9].children.text
40
- condition = weathers.children[5].children[1].attributes[1].value.force_encoding('UTF-8')
41
- [timestamp,
42
- {"temperature" => temperature,
43
- "rain_probability" => rain_probability,
44
- "condition" => condition}]
45
- end.to_h
46
- end
47
-
48
- def parse_tips
49
- data = @document.xpath("//div[@id='box8']")
50
- tips_api = data[0].children[13].children[0].text.split("'")[1]
51
- tips_url = "#{CWB_URL}/#{tips_api}"
52
- tips_doc = Oga.parse_html(open(tips_url))
53
- result = ""
54
- tips_doc.children.each do |element|
55
- if element.text.empty?
56
- result << "\n"
57
- elsif element.text.split(":")[0].force_encoding('UTF-8') == "更新時間"
58
- break
59
- else
60
- result << element.text
61
- end
62
- end
63
- result = result.gsub("\n\n","\n")
64
- result.force_encoding('UTF-8')
65
- end
66
-
67
- def name_mapping(city)
1
+ module WeatherScraper
2
+ # provide city name mapping
3
+ module NameMapping
4
+ def city_mapping(city)
68
5
  case city
69
6
  when "臺北", "台北", "臺北市", "台北市", "Taipei", "TaipeiCity"
70
7
  result = "Taipei_City"
@@ -0,0 +1,53 @@
1
+ require 'oga'
2
+ require 'open-uri'
3
+ require_relative 'name_mapping'
4
+
5
+ module WeatherScraper
6
+ # parse weekly weather description from cwb website
7
+ class WeeklyWeather
8
+ include NameMapping
9
+ CWB_URL = "http://www.cwb.gov.tw"
10
+ CITY_WEATHER_URL = "#{CWB_URL}/V7/forecast/taiwan/inc/city"
11
+
12
+ def initialize(city)
13
+ @city = city_mapping(city).delete("_")
14
+ parse_html(city_mapping(city))
15
+ end
16
+
17
+ def city
18
+ @city
19
+ end
20
+
21
+ def weathers
22
+ @weathers ||= parse_weathers
23
+ end
24
+
25
+ private
26
+
27
+ def parse_html(city)
28
+ url = "#{CITY_WEATHER_URL}/#{city}.htm"
29
+ @document = Oga.parse_html(open(url))
30
+ end
31
+
32
+ def parse_weathers
33
+ timestamp = @document.xpath("//th[@width='11%']")
34
+ timestamp = timestamp.map {|e| e.text.force_encoding('UTF-8')}
35
+
36
+ data = @document.xpath("//td")
37
+ temperature = data.map { |e| e.text.split(" ")[2]}
38
+ condition = data.map{ |e| e.children[1].attributes[1].value.force_encoding('UTF-8')}
39
+
40
+ result = []
41
+ timestamp.each_index do |i|
42
+ result << [timestamp[i],
43
+ {"day_temperature" => temperature[i+7],
44
+ "day_condition" => condition[i+7],
45
+ "night_temperature" => temperature[i],
46
+ "night_condition" => condition[i]
47
+ }
48
+ ]
49
+ end
50
+ result.to_h
51
+ end
52
+ end
53
+ end
data/lib/weatherscout.rb CHANGED
@@ -1 +1 @@
1
- require 'weatherdesc/daily_weather.rb'
1
+ require 'weathers/weather_scraper.rb'
@@ -1,54 +1,63 @@
1
+ require 'vcr'
2
+ require 'webmock'
1
3
  require 'minitest/autorun'
2
4
  require './lib/weatherscout.rb'
3
5
 
4
- CITY = "新竹"
5
- daily_weather = DailyWeatherScraper::DailyWeather.new(CITY)
6
+ DAILY_CITY = "新竹"
6
7
 
7
- describe 'Daily weather desc scrap' do
8
+ VCR.configure do |config|
9
+ config.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
10
+ config.hook_into :webmock
11
+ end
8
12
 
9
- it 'should return city name' do
10
- city = daily_weather.city
11
- city.must_be_instance_of String
12
- end
13
+ VCR.use_cassette('dailytweather') do
14
+ daily_weather = WeatherScraper::DailyWeather.new(DAILY_CITY)
15
+ describe 'Daily weather desc scrap' do
13
16
 
14
- it 'has the right number of period weathers' do
15
- weathers = daily_weather.weathers
16
- weathers.size.must_equal 3
17
- end
17
+ it 'should return city name' do
18
+ city = daily_weather.city
19
+ city.must_be_instance_of String
20
+ end
18
21
 
19
- it 'should return the timestamp in correct format' do
20
- timestamps = daily_weather.weathers.keys
21
- timestamps.each do |timestamp|
22
- timestamp.must_match /\A.{4,5}\s\d\d\/\d\d\s\d\d:\d\d~\d\d\/\d\d\s\d\d:\d\d/
22
+ it 'has the right number of period weathers' do
23
+ weathers = daily_weather.weathers
24
+ weathers.size.must_equal 3
23
25
  end
24
- end
25
26
 
26
- it 'should return temperature' do
27
- weathers = daily_weather.weathers.values
28
- weathers.each do |weather|
29
- temperature = weather["temperature"]
30
- temperature.must_match /(-|\d)\d+\s~\s(-|\d)\d+/
27
+ it 'should return the timestamp in correct format' do
28
+ timestamps = daily_weather.weathers.keys
29
+ timestamps.each do |timestamp|
30
+ timestamp.must_match /\A.{4,5}\s\d\d\/\d\d\s\d\d:\d\d~\d\d\/\d\d\s\d\d:\d\d/
31
+ end
31
32
  end
32
- end
33
33
 
34
- it 'should return weather condition' do
35
- weathers = daily_weather.weathers.values
36
- weathers.each do |weather|
37
- condition = weather["condition"]
38
- condition.must_be_instance_of String
34
+ it 'should return temperature' do
35
+ weathers = daily_weather.weathers.values
36
+ weathers.each do |weather|
37
+ temperature = weather["temperature"]
38
+ temperature.must_match /(-|\d)\d*\s~\s(-|\d)\d*/
39
+ end
39
40
  end
40
- end
41
41
 
42
- it 'should return rain probaliity' do
43
- weathers = daily_weather.weathers.values
44
- weathers.each do |weather|
45
- probaliity = weather["rain_probability"]
46
- probaliity.must_match /\d+\s%/
42
+ it 'should return weather condition' do
43
+ weathers = daily_weather.weathers.values
44
+ weathers.each do |weather|
45
+ condition = weather["condition"]
46
+ condition.must_be_instance_of String
47
+ end
48
+ end
49
+
50
+ it 'should return rain probaliity' do
51
+ weathers = daily_weather.weathers.values
52
+ weathers.each do |weather|
53
+ probaliity = weather["rain_probability"]
54
+ probaliity.must_match /\d+\s%/
55
+ end
47
56
  end
48
- end
49
57
 
50
- it 'should return weather tips' do
51
- tips = daily_weather.tips
52
- tips.must_be_instance_of String
58
+ # it 'should return weather tips' do
59
+ # tips = daily_weather.tips
60
+ # tips.must_be_instance_of String
61
+ # end
53
62
  end
54
63
  end