承上一篇,公开申购公告的纲页页面如下
依照我们会需要的栏位,我们的 model 如下
//
// StockSubscriptionInfo.swift
// ITIronMan
//
// Created by Marvin on 2021/9/4.
//
import Foundation
/// 股票申购最小单位的 data model
struct StockSubscriptionInfo {
let stockCode: String
let stockName: String
let subscriptionStartString: String
let subscriptionEndString: String
let subscriptionOccurString: String
/// 承销价
let price: String
/// 实际承销价,不确定为什麽会有这个栏位,但看起来价格和承销价一样
let actualPrice: String
let stockDeliveringDateString: String
let stockCountString: String
/// 总合格件数,所有被扣款成功的数量
let totalApplyCountString: String
/// 中签率
let subscriptionRateString: String
}
如果你用的是 chrome,当滑鼠移到下载 csv 的位置的时候,你会看到下载的网址呈现出来,这个位置就是放 csv 档案的地方。而後面的 yy=2021,就可以知道,他是依照年份为单位,来进行查询的。
如果你换成 2020,那就会是 2020 年的所有资料。
csv 下载位置: https://www.twse.com.tw/announcement/publicForm?response=csv&yy=2021
依照前面的方式,再写一个 StockSubscriptionManager 专门处理申购的资料。
//
// StockSubscriptionManager.swift
// ITIronMan
//
// Created by Marvin on 2021/9/4.
//
import Foundation
/// 这个类别专门处理股票申购资讯
class StockSubscriptionManager {
private lazy var alamofireAdapter: AlamofireAdapter = {
return AlamofireAdapter()
}()
func requestStockSubscriptionInfo(year: Int, completion: @escaping (([StockSubscriptionInfo], Error?) -> Void)) {
// https://www.twse.com.tw/announcement/publicForm?response=csv&yy=2021
let urlString = "https://www.twse.com.tw/announcement/publicForm?response=csv&yy=\(year)"
alamofireAdapter.requestForString(urlString, method: .get) { result in
switch result {
case .success(let string):
print("you got string: \(string)")
case .failure(let error):
print("error: \(error.localizedDescription)")
}
}
}
}
在测试的时候,我们先随便找一个按钮来发动 StockSubscriptionManager 的下载,看会不会有 header 或是资料跑出来
不过,照着这一份程序码,这一个 func 发动的时候,console 上面会印出一堆,你好像看得懂,又好像看不懂的东西。
在印出来的结果上,你看得懂的是那些数字,所以先看这些可被辨识的文字代表什麽。110/09/14 应该是日期,3533 是股票代号,110/09/08 也是日期,後面有个 432。比对这些数字,他应该就是前述截图中的 [嘉泽],只是编码和预设的不同,所以无法被 String 识别。
已经知道 requestForString 会出编码的问题,至少确定 data 的 request 是有的,所以要改用 AlamofireAdapter 中的 request,并传出 (Data?, URLResponse?, Error?) 让这个 manager 进行 String parsing。
// https://www.twse.com.tw/announcement/publicForm?response=csv&yy=2021
let urlString = "https://www.twse.com.tw/announcement/publicForm?response=csv&yy=\(year)"
alamofireAdapter.request(urlString, method: .get) { data, response, error in
if let error = error {
completion([], error)
return
}
var subscriptionList = [StockSubscriptionInfo]()
if let data = data,
let string = String(data: data, encoding: .utf8),
let csv = try? CSVAdapter(rawString: string) {
print(csv.header)
print(csv.namedRows[10])
}
completion(subscriptionList, error)
}
然後再试着找个测试按钮,看一下 csv 能不能被 print 出来。
结果,是完全没有反应,所以你遇到了开发者的日常。「有 bug!」
分析:
是否为网址的问题? →贴到 chrome 上会跳出下载 csv 的视窗,所以网址正确
是否 alamofire 呼叫有问题? → 在 error 那边没有跳出,所以没发生 error
第 31 行是否有 Data? → 使用 console print data,有 26651 bytes,而且和下载的 csv 档比对 file size,不太可能是这边有错
第 32 行後,就跳离 if let,没有往 33 行走,可以确定的是 String(data: data, encoding: .utf8) 这边, string 是 optional,所以程序跳出。
也就是…这个 String 不是 UTF-8 的编码…
那他还可能是什麽编码呢? 如果档案是繁中的话,那应该就是 Big5
Big5 简介如下
https://zh.wikipedia.org/wiki/大五码
先找找看,有没有其他 utf-8 编码的来源?
在公开申购的右上方,有个 [English] 标签,点下去後,页面就变成全部英文了。然後滑鼠移到 csv 那一栏,连结变成下方这样,可以看到,中间多了个 /en/,下载後的档案,里面的内容全部是英文。来试试看换成英文版的 csv 档,能不能拿到我们要的资讯。
https://www.twse.com.tw/en/announcement/publicForm?response=csv&yy=2021
成功了,如果把下载来源换成英文,就可以下载了。但和中文版资料相比,英文版资料只有 code,没有名称,所以还需要有一个 stock code vs. stock name 的表来查。如果是上市/上柜增资,已经在市场上可以交易,所以在前面所提到的 上市/上柜 公司基本资料表里面有,如果真的想使用英文资料的话,可以使用 stock code 去前面的资料库里面反查 stock name。
但是,Swift String 真的只能吃 utf8 吗? iPhone 是被设计出来卖到全世界的产品,如果不能转换成每个地区的语言/历法/习惯,那是卖不出去的。
而 String 的 init 被设计为可以输入 encoding,所以,一定是有方法可以将 Big5 的 Data 转换成 String。
下一篇会说,怎样实作操作 Big5 的 String
>>: Day 04. Zabbix 可监控的服务、设备、应用
说明 在先前的版本中被称为样板字串(template strings) 早期在组字串资料时会用大量的...
最近公司的EIP专案有个需求。主管在签核一览表里会点击要签核的单子另开一个视窗,需求单位希望主管签完...
Breeze 是官方推荐的起手套装,内建有登入、注册、忘记密码等常用的用户功能,令外可以选择使用 V...
前言 本章节,是要讲述如何查看网路设定与设定在主机上的网路资讯。 识别与取得网路介面资讯 在一台主机...
前情提要 艾草:「不知不觉也累积了不少魔力总量了,我们今天透过魔法阵列来找出你适合的属性值吧!」 「...