WANTGOO 股票網站的結構改變, 之前透過 Google 試算表自動抓成交金額的函式不能用了, 所以只好改一下:

=IFERROR(GoogleFinance(CONCATENATE("TPE:",A3)),importXML(CONCATENATE("https://www.wantgoo.com/stock/",A3),"//span[@name='Deal']"))

A3 是 Google 試算表內的股票代號(格式為文字)
上面的函式用了幾個功能:
1. CONCATENATE : 合併儲存格內容或字串
2. importXML : 撈取網站資料
3. GoogleFinanace : 取得 Google 財經資料

組合起來, 就是先從 Google 財經撈取 台北股市(TPE) 特定股票代碼的成交價; 如果 Google 財經有問題, 再撈取 WANTGOO 單一股票網頁, 當中有一欄(span)名稱為成交價(name='Deal')的資料.


BenQ ScreenBar Lite 一週心得

大約五六年前, 許多電子產品都是中國製造, 而產能過剩的 LED , 開始轉向腳踏車燈, USB 小燈等. 之前就會在意照明, 所以也會在意 USB 燈適用居家照明等用途.

而 ScreenBar 是第一個以電腦使用為目標的獨立產品系列(非獨立產品有 ThinkPad 小燈), 只是定價 $2990 而一直觀望. 前陣子有網購特價, 考慮桌上型電腦已經有配置好的檯燈, 就選購筆電用的 ScreenBar Lite .

首先考慮的是這種燈跟一般 USB 燈有多了哪些設計:
1. 亮度偵測: 一般的燈只有照明, 而亮度是否適合要自己調整位置; ScreenBar Lite 有自動偵測亮度功能, 可以提供 500 流明照明, .
2. 亮度調整: 一般的燈就算日光燈或省電燈泡也沒有, 只有傳統燈泡跟近期的 LED 才有.
3. 色溫調整: 這是看個人使用習慣, 照明時偏白色對比較大較容易分辨, 而偏黃色在看書等用途較不易疲勞.
4. 夾具設計: 這個有很多可以討論, 比如夾具力道, 開模等.

這些設計, 就有符合注重照明跟視力的人的需求, 不過使用上也有要留意的地方:
1. 夾具厚度範圍小, 適合筆電, 不過會影響到調整螢幕角度, 以及開闔筆電的動作, 所以常開會帶來帶去, 並不適合.
2. 這是補光用, 環境中最好還是有大範圍的照明, 而 ScreenBar Lite 夾在筆電螢幕上, 可以調整對鍵盤或更靠近使用者的桌面照明.

所以整體來說, 這款產品適用在:
1. 辦公環境已經有室內照明, 而筆電較少帶來帶去, 座位亮度稍有不足或休息時間會關掉環境照明的情況.
2. 居家不常開闔筆電, 只是從客廳拿到房間, 環境亮度會變化.

以 $2990 的價位, 個人覺得電腦工作人員務必考慮, 大學生或上班族是可以考慮.

血壓計基本功能簡介

血壓計基本功能簡介:

1. 量血壓跟每分鐘心跳數.
2. 記憶功能/時間: 不一定每台有, 記憶又分最多人數(1~4人等)與筆數(30~60筆等)
3. 臂帶位置偵測: 如果沒裝在指定位置, 會提醒.
4. 心跳異常檢測: 推測是以心跳間隔差距比較.
5. 取平均值/連續測三次: 由於有些人可能休息不夠就開始量, 誤差會比較大, 所以有些機種可以選連測3次, 有些機種是以最近3次來平均.
6. 心房顫動與其他: 更進階檢測可能心房異常.
7. 藍牙配對到手機紀錄.

至於腕式/臂式, 硬管/軟管, 依個人使用上習慣.

用VB收產線資料程式的調整心得

公司之前有委外開發一套收產線資料的程式, 是用VB寫的, 有留下原始碼.

最近有其他同事需要這些功能:
1. 收不同產線資料: 還是連線同一套系統, 只是不同點位的資料.
2. 撈取的頻率不同: 原本是以每分鐘一次, 新的頻率有每秒一次與每一小時一次.
3. 存檔格式不同: 原本以日為單位要增加以月為單位.

所以就原始碼先分析, 發現這程式其實已經是第二版.
第一版: 設定一個"間隔"(Interval), 可以用按鍵調上調下, 另外有一欄"上次完成後幾秒", 並用 Timer 每秒加 1 , 當"上次完成後幾秒"大於或等於"間隔"時, 就啟動撈取的動作.
第二版: 設定四個"間隔時間"按鈕, 有每分鐘, 每10分鐘, 每半小時, 每小時; 按下"間隔時間"的按鈕時, 有一欄"預定撈取時間"也跟著異動, 同樣透過 Timer 查詢目前時間, 如果"目前時間"等於"預定撈取時間", 則啟動撈取的動作.
而且第二版只是把第一版的幾個物件隱藏, 程式碼本身並沒有改成註解(Remark), 所以剛看完只覺得為什麼有2/5的程式沒有用到, 再對照Form隱藏的圖示, 歸納起來才發現這是有兩個版本了.

然後分析程式的寫法, 大概有這些特性:
1. 第一版有可能操作者不小心按到調整間隔的按鈕, 第二版也可能不小心按到不同間隔時間的按鈕, 造成撈取資料並不是預期的時間.
2. 撈取的點位表, 是用CSV格式存放於特定目錄, 每次要撈取資料時, 會將系統指定的檔名, 先讀取一次點位表, 再依點位表撈產線資料, 而重複開啟檔案會讓磁碟I/O增加.
3. 由於不同產線的點位不同, 原本的程式是寫死每條產線250點, 最多9條產線, 陣列名稱: DATA1(251)~DATA9(251) , 還多預留 1 個點但迴圈只抓 250 個 XD .
4. 第二版的預定撈取時間, 是以全手動把時間的字串, 拆成 時 分 秒, 每次 Timer 會把 秒 加 1 , 如果等於 60 , 再把 分 加 1 , 然後 秒 除以 60 取餘數.... @_@ .
5. 可能為了避免資料檔 lock 住, 所以撈資料後先存到 TEMP 目錄, 再 copy 到使用者讀取的目錄, 而 TEMP 目錄並不刪除, 造成檔案容量要 2 倍.

所以要配合新需求改版, 就改了架構:
1. 採用"間隔"時間法, 但是每個系統可以有各自的"間隔", 而且以每天 00:00:00 開始, 換算成當天的秒數, 如果 秒數 除以 間隔 等於 0 , 就執行撈資料.
2. 為了避免 Timer 意外, 也保留上次撈取後已經過了幾秒, 如果大於"間隔", 也會撈取資料.
以上兩點讓至少"間隔"時間內會撈取一次.
3. 因為產線有好幾條, 之前 9 個, 這次加 2 個共 11 個, 而且有條產線只有 1 個點位, 有條產線超過 50 個點位, 原本程式固定用 250 個點位, 造成輸出的 CSV 資料檔後面全部是空字串.
所以這次改用 2 個陣列: 第 1 個是產線清單, 並設定間隔時間, 存檔類型(每日/每月), 前次資料檔名, 點位數, 點位起始值; 第 2 個陣列則是撈取的點位清單. 陣列就大概長這樣:
A.
產線1, 每1秒, 每日1檔, 20190426MM, 2, 0
產線2, 每3600秒, 每月1檔, 201904CHL, 12, 2
產線3, 每60秒, 每日1檔, 20190426ETC, 44, 14
B.
(0) motor1, A(電流), (註解), (值)
(1) motor2, A(電流), (註解), (值)
(2) temp1, C(溫度), (註解), (值)
(3) temp2, C(溫度), (註解), (值)
這樣剛啟動程式時, 自動撈取指定的產線設定檔清單, 再依清單 redim 陣列大小, 並讀取清單檔寫入陣列, 之後程式就不會再讀取設定檔, 減少磁碟 I/O .
4. Timer 本身還是留著, 每 0.25 秒執行 1 次, 比對上次執行的當日秒數(0~86399), 若與目前秒數不同, 表示已經過了 1 秒, 再執行以下動作:
A. 把產線陣列的 離上次撈取秒數 加 1 .
B. 如果 離上次撈取秒數 大於等於 間隔時間 , 或 當日秒數 除以 間隔時間 的 餘數 等於 0 , 就執行 撈取資料 並把 離上次撈取秒數 設定為 0 .
5. 實際撈取資料時, 則是依 產線 陣列, 找到要撈取的點位序號, 再從 點位 陣列, 找到系統內點位代號, 呼叫 OPC 連線讀取值. 這邊還有些額外的網路連線判斷, 如果斷線的話就存特殊字串, 而不呼叫 OPC 避免時間拉太長.
6. 資料存檔還是使用 TEMP 目錄, 存檔後再 copy 到資料目錄; 不過多了一個動作, 就是紀錄前次存檔的檔名, 如果前次存檔檔名與這次不同, 表示可能換日或換月, 這時候就把 TEMP 目錄的前次檔案 copy 到資料目錄; 確定 資料目錄的前次檔案 存在後, 再把 TEMP 目錄的前次檔案刪除. 這樣確保 TEMP 目錄只有目前在使用的檔案.

基本上這樣就改造完了, 不過實際上線時, 因為大部分產線都是每分鐘抓一次, 而當次要撈的點位太多, 造成全部抓完大約 8~9 秒, 另外一條產線的每秒抓一次, 就跳過了 8~9 秒沒有資料.

看了一下 VB 本身沒有真正的多執行緒, 要靠快速切換的寫法, 於是....把程式拆成兩個, 一個執行每分鐘的撈取, 一個執行不是每分鐘的撈取, 然後 Windows 同時執行兩個不同檔名的撈取程式, 裡面指定的目錄也不同.... XD

PHP連結資料庫以及存放表格規劃

繼續影音網站的自動化....

前面有兩篇提到網址, 網頁都要整理出 pattern , 既然要整理, 就需要有存放資料的地方, 以便撈取.

而整理 pattern 時, 由於需要跨時間與跨不同網站或不同網頁比較, 所以使用資料庫來存放是比較合適的作法.

因為授權關係, PHP 常搭配 mariaDB (由 MySQL 發展出來), 而連線的方式通常有兩種:
1. mysqli : 是由 mysql 改良而來, 傳統 mysql 可能會遇到 SQL Injection 等攻擊, mysqli 提供了"預存結構法", 確保查詢指令與查詢資料是分開的, 而 SQL Injection 就會單純當資料而不容易攻擊.
2. PDO : 由於大部分關聯式資料庫都遵循 ANSI SQL , 基本的挑選(select), 更新(update)功能都是相同的, 但各資料庫服務的語法仍有些許不同, 所以 PHP 提供 PDO 方式, 在 PHP 內保持語法一致, 讓開發者假如跨不同資料庫, 語法不用重寫, 只有剛開始的連線指令不同.

假如是 XAMPP 環境, 基本上就已經裝好 Apache + PHP 擴充 + mariaDB , PHP 程式內寫入連線語法即可, 不過還沒開始用程式分析 pattern , 就先規劃資料表.

學資料庫一定會學到正規化, 不過學正規化跟實作上還是有差別, 主要是實作時, 有些業務上雖然不同, 但規格上是相同的資料, 其實可以放在一起, 舉兩個例子:
1. 為民服務有專案, 群, 服務三層項目, 剛學資料庫可能就會拆三個表, 不過實際上可以用同一張表, 多加一個欄位: 屬於第幾層, 然後再用 view 或程式內篩選.
2. 影音網站是收集 URL , 可是 URL 有包括: a. 由使用者輸入的第一批, b. 依使用者輸入, 實際連線時, 網站會回傳的. c. 根據網站回傳的 URL , 分析 pattern 後, 產生"純"的 URL .

網頁內容因為要分析 pattern 中哪些 div 相同哪些不同, 所以要在不同時間抓取多次來比較, 基本上 div 不同的地方就很可能是廣告, 可以排除, 至於網站內容是否也要產生"純"的網頁內容來當快取, 暫時還沒有想到, 先用 timestamp 多存幾次就好.

這樣基本上就有兩個資料表: 1. URL 2. 網頁內容 ; 而 URL 目前有兩類: a. 使用者輸入 b. 連結時, 網站回傳的 URL , 所以有幾欄: 1. 這個 URL 屬於那一類 2. URL 3. URL 序號 4. URL 是否對應其他序號(假如使用者輸入與網站回傳的 URL 不同時), 5. 抓取的時間  ; 網頁內容則只有 3 欄: 1. 是對應 URL 的序號, 2. 是抓取的時間, 3. 是存放抓取的網頁內容.

這樣的結構, 在 PHP 基本上就有兩個事情:
1. 使用者輸入 URL , 記錄下來.
2. 用 cURL 去抓看看, 然後把抓到的結果存起來.
pattern 分析才開始準備....