只要會開車騎車的人,都會想知道現在的油價,現在中國石油開放資料可供串接,然而規格是我從來沒碰過的SOAP,這塊「肥皂」比起簡潔的JSON複雜多,於是我還要借助開源來幫我處理~
乍看這個網頁:中國石油SOAP功能,實在不曉得它要怎麼串接,好在我搜尋網路前人經驗,慢慢看得懂它想表達什麼⋯⋯
我是使用資料集:
getCPCMainProdListPrice_Historical
1:無鉛汽油92, 2:無鉛汽油95, 3:無鉛汽油98, 4:超級/高級柴油, 5:低硫燃料油(0.5%), 6:甲種低硫燃料油(0.5) — 中油汽柴燃油 歷史零售牌價 DataSet
後來發現1-6是要代入的參數。
<?xml version="1.0" encoding="utf-8"?> <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Body> <getCPCMainProdListPrice_Historical xmlns="http://tmtd.cpc.com.tw/"> <prodid>string</prodid> </getCPCMainProdListPrice_Historical> </soap12:Body> </soap12:Envelope>
夥伴幫我找了開源SOAPEngine,點進去看說明很簡單使用,於是就套進我的專案,語法是這麼寫:
/** Theme: Taiwan Oil Open Data IDE: Xcode 8 Language: Objective C Date: 105/12/27 Author: HappyMan Blog: https://cg2010studio.wordpress.com/ */ /* string 為油品代號( 1-6 )的參數: 1:無鉛汽油92 2:無鉛汽油95 3:無鉛汽油98 4:超級/高級柴油 5:低硫燃料油(0.5%) 6:甲種低硫燃料油(0.5) */ SOAPEngine *soap = [[SOAPEngine alloc] init]; soap.actionNamespaceSlash = YES; [soap setValue:@"1" forKey:@"prodid"]; [soap requestURL:@"http://vipmember.tmtd.cpc.com.tw/OpenData/ListPriceWebService.asmx" soapAction:@"http://tmtd.cpc.com.tw/getCPCMainProdListPrice_Historical" completeWithDictionary:^(NSInteger statusCode, NSDictionary *dict) { DxLog(@"Result 92 %@", [dict[@"diffgram"][@"NewDataSet"][@"tbTable"] lastObject][@"參考牌價"]); aOil92Label.text = [dict[@"diffgram"][@"NewDataSet"][@"tbTable"] lastObject][@"參考牌價"]; NSString *dateStr = [NSString stringWithFormat:@"臺灣中油 更新時間 %@", [[[dict[@"diffgram"][@"NewDataSet"][@"tbTable"] lastObject][@"牌價生效時間"] componentsSeparatedByString:@"T"] firstObject]]; aOilTimeLabel.text = dateStr; } failWithError:^(NSError *error) { DxLog(@"Error: %@", error); }];
回傳結果是一個充滿元素4個key的陣列:
(lldb) po dict[@"diffgram"][@"NewDataSet"][@"tbTable"][0]
{
“\U53c3\U8003\U724c\U50f9″ = 15;
“\U724c\U50f9\U751f\U6548\U6642\U9593″ = “1999-01-06T00:00:00+08:00″;
“\U7522\U54c1\U540d" = “\U7121\U925b\U6c7d\U6cb992″;
“\U8a08\U50f9\U55ae\U4f4d" = “\U5143/\U516c\U5347″;
}(lldb) po [dict[@"diffgram"][@"NewDataSet"][@"tbTable"][0] allKeys]
<__NSArrayI 0x14fc2b8f0>(
產品名,
參考牌價,
牌價生效時間,
計價單位
)
真是令人感動哪~終於透過SOAP來取得油價!
關鍵在於:
- requestURL
- soapAction
- prodid
這樣我就稍微懂SOAP規格啦~
然而發現一個挑戰,是我用的開源有限制⋯⋯
看來是位高人所寫,然而他是要付費來隱藏這個「第一次執行」都會跳出的「假提示」。好在我還能破解它XD~不然我就要付費13歐元來解鎖,嗯⋯⋯佩服我自己:P~
我是這麼破解⋯⋯
<__NSArrayM 0x15045bed0>(
<UILayoutContainerView: 0x14ed5a490; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: 0x14ef89190>; layer = <CALayer: 0x14ed59f80>>,
<UITransitionView: 0x150475e10; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x150476210>>
)
原來是個UITransitionView,直接加在UIWindow上,啊哈~知道畫面層級之後,就找出它來移除!
/** Theme: Taiwan Oil Open Data IDE: Xcode 8 Language: Objective C Date: 105/12/27 Author: HappyMan Blog: https://cg2010studio.wordpress.com/ */ -(void)removeBlockView { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ for (int i = 0; i < 1000000; i++) { [self isAlertViewShowing]; } }); }); } - (BOOL)isAlertViewShowing { UIWindow *window = [UIApplication sharedApplication].windows[0]; NSArray* subviews = window.subviews; if (subviews.count >= 2) { dispatch_async(dispatch_get_main_queue(), ^{ [subviews[1] removeFromSuperview]; }); return YES; } return NO; }
用很簡單的指令把它給移除,甚至不讓使用者發現,它有被加到螢幕上~我預估開源在回傳結果後0.5-1秒會跳出提示,用for loop在背景跑,這樣不卡住介面,一旦發現UIWindow上多了一個View,就在前景把它給移除。
注意170308:
- 此作法有一定的風險,不同硬體裝置的執行速度有差異,如果沒有全面性測試,是有可能讓某些人看到幾秒鐘才消失喔~
- 以道德的角度來看,會讓作者失去賺錢的機會,敬請三思。
參考:
Comments on: "[iOS] 開放資料之中國石油" (3)
[…] 我發現在刻意阻擋使用者操作時,很容易崩潰XD~那是我要破解第三方套件所使用的撇步。 […]
讚讚
好聰明的方法!!
讚Liked by 1 person
當一下Hacker o(^▽^)o
讚讚