20260319

【JSON】気象庁のjsonから天気予報を取り出す(Applescript 海なし県対応)


【JSON】気象庁のjsonから天気予報を取り出す(Applescript 海なし県対応)


【スクリプトエディタで開く】 |

JSON天気予報.scpt
ソース
001#!/usr/bin/env osascript
002#coding: utf-8
003----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
004(*
005気象庁のJSON取得
006Jsonの取得と解析は難しくないが
007『海がない気象台』『観測所にはURLがない』とかがあることをお忘れなく
008V1初回作成
009V2 色々直した
010v2.1 海なし県対応で修正した
011
012 com.cocolog-nifty.quicktimer.icefloe*)
013----+----1----+----2----+-----3----+----4----+----5----+----6----+----7
014use AppleScript version "2.8"
015use framework "Foundation"
016use framework "AppKit"
017use framework "UniformTypeIdentifiers"
018use scripting additions
019property refMe : a reference to current application
020####################
021#設定項目
022set strAreaUrl to "https://www.jma.go.jp/bosai/common/const/area.json"
023
024####################
025#出力用テキスト
026set ocidOutPutArray to refMe's NSMutableArray's alloc()'s init()
027####################
028#URL
029set ocidAreaUrlStr to refMe's NSString's stringWithString:(strAreaUrl)
030set ocidAreaURL to refMe's NSURL's alloc()'s initWithString:(ocidAreaUrlStr)
031####################
032#メタ
033
034set strLF to ("" & linefeed & "") as text
035set strCR to ("" & return & "") as text
036set strCRLF to ("" & return & linefeed & "") as text
037set strSpace to ("" & space & "") as text
038set strTab to ("" & tab & "") as text
039####################
040#NSDATA
041set ocidOption to (refMe's NSDataReadingMappedIfSafe)
042set listResponse to refMe's NSData's alloc()'s initWithContentsOfURL:(ocidAreaURL) options:(ocidOption) |error|:(reference)
043if (item 2 of listResponse) = (missing value) then
044   log "initWithContentsOfURL 正常処理"
045   set ocidReadJsonData to (item 1 of listResponse)
046else if (item 2 of listResponse) ≠ (missing value) then
047   set strErrorNO to (item 2 of listResponse)'s code() as text
048   set strErrorMes to (item 2 of listResponse)'s localizedDescription() as text
049   refMe's NSLog("■:" & strErrorNO & strErrorMes)
050   return "initWithContentsOfURL エラーしました" & strErrorNO & strErrorMes
051end if
052####################
053#JSON ルートがDICT
054set ocidOption to (refMe's NSJSONReadingJSON5Allowed)
055set listResponse to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidReadJsonData) options:(ocidOption) |error|:(reference))
056if (item 2 of listResponse) = (missing value) then
057   log "JSONObjectWithData 正常処理"
058   set ocidJsonDict to (item 1 of listResponse)
059else if (item 2 of listResponse) ≠ (missing value) then
060   set strErrorNO to (item 2 of listResponse)'s code() as text
061   set strErrorMes to (item 2 of listResponse)'s localizedDescription() as text
062   refMe's NSLog("■:" & strErrorNO & strErrorMes)
063   return "JSONObjectWithData エラーしました" & strErrorNO & strErrorMes
064end if
065####################
066#centers 
067set ocidCentersDict to ocidJsonDict's objectForKey:("centers")
068set ocidCentersArray to ocidCentersDict's allKeys()
069#ソート
070set ocidCentersArray to ocidCentersArray's sortedArrayUsingSelector:("compare:")
071#ダイアログ用の地方気象台名リスト
072set listCenterName to {} as list
073#逆引きDICT
074set ocidReverseCenterDict to refMe's NSMutableDictionary's alloc()'s init()
075repeat with itemKey in ocidCentersArray
076   set ocidCenter to (ocidCentersDict's valueForKey:(itemKey))
077   set strCenterName to (ocidCenter's valueForKey:("officeName")) as text
078   copy strCenterName to end of listCenterName
079   (ocidReverseCenterDict's setValue:(itemKey) forKey:(strCenterName))
080end repeat
081log ocidReverseCenterDict as record
082####################
083#ダイアログ
084set strName to (name of current application) as text
085if strName is "osascript" then
086   tell application "SystemUIServer" to activate
087else
088   tell current application to activate
089end if
090try
091   tell application "SystemUIServer"
092      activate
093      set valueResponse to (choose from list listCenterName with title "選んでください" with prompt "地方気象台を選んでください" default items (item 3 of listCenterName) OK button name "OK" cancel button name "キャンセル" with multiple selections allowed without empty selection allowed)
094   end tell
095on error
096   tell application "SystemUIServer" to quit
097   log "Error choose from list"
098   return false
099end try
100tell application "SystemUIServer" to quit
101if (class of valueResponse) is boolean then
102   log "Error キャンセルしました"
103   error "ユーザによってキャンセルされました。" number -128
104else if (class of valueResponse) is list then
105   if valueResponse is {} then
106      log "Error 何も選んでいません"
107      return false
108   else
109      set strResponse to (item 1 of valueResponse) as text
110   end if
111end if
112set ocidOutPutStrint to refMe's NSString's stringWithString:("天気予報: Center: " & strResponse & strLF)
113(ocidOutPutArray's addObject:(ocidOutPutStrint))
114####################
115#逆引き辞書からセンター番号を取得
116set ocidCenterNo to ocidReverseCenterDict's valueForKey:(strResponse)
117#センター番号からOffice情報を取得
118set ocidOfficeDict to (ocidCentersDict's objectForKey:(ocidCenterNo))
119#Office情報 DICTから気象台番号を取得
120set ocidOfficeNoArray to (ocidOfficeDict's objectForKey:("children"))
121set ocidOfficeNoArray to ocidOfficeNoArray's sortedArrayUsingSelector:("compare:")
122####################
123#offices
124set ocidOfficesDict to ocidJsonDict's objectForKey:("offices")
125set ocidOfficesArray to ocidOfficesDict's allKeys()
126#測候所はURLがないので除外
127set appPredicate to refMe's NSPredicate's predicateWithFormat_("SELF CONTAINS %@", "測候所")
128set ocidOfficesArrayRev to ocidOfficesArray's filteredArrayUsingPredicate:(appPredicate)
129set ocidOfficesArray to ocidOfficesArrayRev's sortedArrayUsingSelector:("compare:")
130#ダイアログ用の気象台名リスト
131set listOfficesName to {} as list
132#逆引きDICT
133set ocidReverseOfficesDict to refMe's NSMutableDictionary's alloc()'s init()
134repeat with itemKey in ocidOfficeNoArray
135   set ocidOffice to (ocidOfficesDict's valueForKey:(itemKey))
136   set strOfficeName to (ocidOffice's valueForKey:("officeName")) as text
137   if strOfficeName does not contain "測候所" then
138      copy strOfficeName to end of listOfficesName
139      (ocidReverseOfficesDict's setValue:(itemKey) forKey:(strOfficeName))
140   end if
141end repeat
142log ocidReverseOfficesDict as record
143####################
144#ダイアログ
145set strName to (name of current application) as text
146if strName is "osascript" then
147   tell application "SystemUIServer" to activate
148else
149   tell current application to activate
150end if
151try
152   tell application "SystemUIServer"
153      activate
154      set valueResponse to (choose from list listOfficesName with title "選んでください" with prompt "気象台を選んでください" default items (last item of listOfficesName) OK button name "OK" cancel button name "キャンセル" with multiple selections allowed without empty selection allowed)
155   end tell
156on error
157   tell application "SystemUIServer" to quit
158   log "Error choose from list"
159   return false
160end try
161tell application "SystemUIServer" to quit
162if (class of valueResponse) is boolean then
163   log "Error キャンセルしました"
164   error "ユーザによってキャンセルされました。" number -128
165else if (class of valueResponse) is list then
166   if valueResponse is {} then
167      log "Error 何も選んでいません"
168      return false
169   else
170      set strResponse to (item 1 of valueResponse) as text
171   end if
172end if
173set ocidOutPutStrint to refMe's NSString's stringWithString:("Office: " & strResponse & " 発表" & strLF)
174(ocidOutPutArray's addObject:(ocidOutPutStrint))
175#######################
176#本処理 天気予報jSON取得
177set ocidOfficeNo to ocidReverseOfficesDict's valueForKey:(strResponse)
178set strOfficeNo to ocidOfficeNo as text
179#日付
180set strDate to doGetDateNo("yyyyMMddhhmmss") as text
181###URL整形
182set strURL to ("https://www.jma.go.jp/bosai/forecast/data/forecast/" & strOfficeNo & ".json?__time__=" & strDate & "") as text
183log strCR & strURL & strCR
184####################
185#URL
186set ocidUrlStr to refMe's NSString's stringWithString:(strURL)
187set ocidURL to refMe's NSURL's alloc()'s initWithString:(ocidUrlStr)
188####################
189#NSDATA
190set ocidOption to (refMe's NSDataReadingMappedIfSafe)
191set listResponse to refMe's NSData's alloc()'s initWithContentsOfURL:(ocidURL) options:(ocidOption) |error|:(reference)
192if (item 2 of listResponse) = (missing value) then
193   log "initWithContentsOfURL 正常処理"
194   set ocidReadJsonData to (item 1 of listResponse)
195else if (item 2 of listResponse) ≠ (missing value) then
196   set strErrorNO to (item 2 of listResponse)'s code() as text
197   set strErrorMes to (item 2 of listResponse)'s localizedDescription() as text
198   refMe's NSLog("■:" & strErrorNO & strErrorMes)
199   return "initWithContentsOfURL エラーしました" & strErrorNO & strErrorMes
200end if
201####################
202#JSON ルートがArray
203set ocidOption to (refMe's NSJSONReadingJSON5Allowed)
204set listResponse to (refMe's NSJSONSerialization's JSONObjectWithData:(ocidReadJsonData) options:(ocidOption) |error|:(reference))
205if (item 2 of listResponse) = (missing value) then
206   log "JSONObjectWithData 正常処理"
207   set ocidJsonArray to (item 1 of listResponse)
208else if (item 2 of listResponse) ≠ (missing value) then
209   set strErrorNO to (item 2 of listResponse)'s code() as text
210   set strErrorMes to (item 2 of listResponse)'s localizedDescription() as text
211   refMe's NSLog("■:" & strErrorNO & strErrorMes)
212   return "JSONObjectWithData エラーしました" & strErrorNO & strErrorMes
213end if
214####################
215#天気予報辞書 天気予報 と 習慣天気予報
216set ocidDailyDict to ocidJsonArray's firstObject()
217set ocidWeeklyDict to ocidJsonArray's firstObject()
218####################
219#各項目取得
220set ocidTimeSeriesArray to ocidDailyDict's objectForKey:("timeSeries")
221set ocidWeathers to ocidTimeSeriesArray's firstObject()
222set ocidRainPops to ocidTimeSeriesArray's objectAtIndex:(1)
223set ocidTemps to ocidTimeSeriesArray's lastObject()
224####################
225#天気予報
226set strOutPutStrint to ("") as text
227set ocidAreaArray to ocidWeathers's objectForKey:("areas")
228repeat with itemArea in ocidAreaArray
229   set strAreaName to ((itemArea's objectForKey:("area"))'s valueForKey:("name")) as text
230   set ocidWeathersArray to (itemArea's objectForKey:("weathers"))
231   set ocidWindsArray to (itemArea's objectForKey:("winds"))
232   set ocidWavesArray to (itemArea's objectForKey:("waves"))
233   set numCntWavesArray to ocidWeathersArray's |count|()
234   repeat with itemNo from 0 to (numCntWavesArray - 1) by 1
235      set strOutPutStrint to ("" & strOutPutStrint & strAreaName & "地方" & strLF) as text
236      if itemNo = 0 then
237         set strOutPutStrint to ("" & strOutPutStrint & "今日の天気: ") as text
238      else if itemNo = 1 then
239         set strOutPutStrint to ("" & strOutPutStrint & "明日の天気: ") as text
240      else if itemNo = 2 then
241         set strOutPutStrint to ("" & strOutPutStrint & "明後日の天気: ") as text
242      end if
243      set strSetString to (ocidWeathersArray's objectAtIndex:(itemNo))
244      set strOutPutStrint to ("" & strOutPutStrint & strSetString & strLF & strTab & "風: ") as text
245      set strSetString to (ocidWindsArray's objectAtIndex:(itemNo))
246      set strOutPutStrint to ("" & strOutPutStrint & strSetString & strLF) as text
247      if ocidWavesArray ≠ (missing value) then
248         set strSetString to (ocidWavesArray's objectAtIndex:(itemNo))
249         set strOutPutStrint to ("" & strOutPutStrint & strTab & "波: " & strSetString & strLF) as text
250      end if
251   end repeat
252   
253   set strOutPutStrint to ("" & strOutPutStrint & strLF) as text
254end repeat
255set ocidOutPutStrint to refMe's NSString's stringWithString:(strOutPutStrint)
256ocidOutPutArray's addObject:(ocidOutPutStrint)
257####################
258#降雨確率
259set strOutPutStrint to ("降水確率(6時間毎):" & strLF) as text
260set ocidAreaArray to ocidRainPops's objectForKey:("areas")
261repeat with itemArea in ocidAreaArray
262   set ocidAreaName to ((itemArea's objectForKey:("area"))'s valueForKey:("name"))
263   set strOutPutStrint to ("" & strOutPutStrint & ocidAreaName & "地域: ") as text
264   set ocidPopsString to ((itemArea's objectForKey:("pops"))'s componentsJoinedByString:("→"))
265   set strOutPutStrint to ("" & strOutPutStrint & ocidPopsString & strLF) as text
266end repeat
267set ocidOutPutStrint to refMe's NSString's stringWithString:(strOutPutStrint)
268ocidOutPutArray's addObject:(ocidOutPutStrint)
269####################
270#気温
271set strOutPutStrint to ("気温(12時間毎):" & strLF) as text
272set ocidAreaArray to ocidTemps's objectForKey:("areas")
273repeat with itemArea in ocidAreaArray
274   set ocidAreaName to ((itemArea's objectForKey:("area"))'s valueForKey:("name"))
275   set strOutPutStrint to ("" & strOutPutStrint & ocidAreaName & "地域: ") as text
276   set ocidTempString to ((itemArea's objectForKey:("temps"))'s componentsJoinedByString:("→"))
277   set strOutPutStrint to ("" & strOutPutStrint & ocidTempString & strLF) as text
278end repeat
279set ocidOutPutStrint to refMe's NSString's stringWithString:(strOutPutStrint)
280(ocidOutPutArray's addObject:(ocidOutPutStrint))
281####################
282#出力用テキスト
283set ocidJoinText to ocidOutPutArray's componentsJoinedByString:(strLF)
284#保存先
285set appFileManager to refMe's NSFileManager's defaultManager()
286set ocidTempDirURL to appFileManager's temporaryDirectory()
287set ocidUUID to refMe's NSUUID's alloc()'s init()
288set ocidUUIDString to ocidUUID's UUIDString
289set ocidSaveDirPathURL to ocidTempDirURL's URLByAppendingPathComponent:(ocidUUIDString) isDirectory:(true)
290#
291set ocidAttrDict to refMe's NSMutableDictionary's alloc()'s init()
292ocidAttrDict's setValue:(511) forKey:(refMe's NSFilePosixPermissions)
293set listDone to appFileManager's createDirectoryAtURL:(ocidSaveDirPathURL) withIntermediateDirectories:(true) attributes:(ocidAttrDict) |error|:(reference)
294if (item 1 of listDone) is false then
295   set strErrorNO to (item 2 of listDone)'s code() as text
296   set strErrorMes to (item 2 of listDone)'s localizedDescription() as text
297   refMe's NSLog("■:" & strErrorNO & strErrorMes)
298   log "createDirectoryAtURL エラーしました" & strErrorNO & strErrorMes
299   return false
300end if
301###パス
302set strFileName to "jma.txt" as text
303set ocidSaveFilePathURL to ocidSaveDirPathURL's URLByAppendingPathComponent:(strFileName) isDirectory:false
304set listDone to ocidJoinText's writeToURL:(ocidSaveFilePathURL) atomically:(true) encoding:(refMe's NSUTF8StringEncoding) |error|:(reference)
305if (item 1 of listDone) is true then
306   set appSharedWorkspace to refMe's NSWorkspace's sharedWorkspace()
307   set boolDone to appSharedWorkspace's openURL:(ocidSaveFilePathURL)
308   
309else if (item 1 of listDone) is false then
310   log (item 2 of listDone)'s localizedDescription() as text
311   return "保存に失敗しました"
312end if
313
314return ocidJoinText as text
315
316
317to doGetDateNo(strDateFormat)
318   ####日付情報の取得
319   set ocidDate to current application's NSDate's |date|()
320   ###日付のフォーマットを定義
321   set ocidNSDateFormatter to current application's NSDateFormatter's alloc()'s init()
322   ocidNSDateFormatter's setLocale:(current application's NSLocale's localeWithLocaleIdentifier:"ja_JP_POSIX")
323   ocidNSDateFormatter's setDateFormat:strDateFormat
324   set ocidDateAndTime to ocidNSDateFormatter's stringFromDate:ocidDate
325   set strDateAndTime to ocidDateAndTime as text
326   return strDateAndTime
327end doGetDateNo
AppleScriptで生成しました