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 分析才開始準備....

初試 JavaScript

(暫時不知道影音網站要寫哪部份, 從最近在練習的 JavaScript 講一下心得.)

JavaScript 剛開始是由 NetScape 開發, 後來發展成 ECMA 通過的共同標準.

而一般網站結構, 會大約分為前端跟後端, 前端就包括:
HTML 負責網頁結構, 基本內容, 提交表格(form)等.
CSS 負責版型, 樣式.
JavaScript 則負責屬於前端的運算, 邏輯判斷.

雖然 JavaScript 也有在伺服器執行的方式, 不過伺服器端有更多競爭者如: PHP / ASP , 近期還有 Python 等, 所以大多應用於前端.

(稍微跳離一下)
JavaScript , PHP , MariaDB 雖然都有字串處理, 基本的迴圈, 邏輯判斷等功能, 不過使用的時機與要處理的資料來源不同, MariaDB 是處理資料庫存放的資料為主, JavaScript 是透過 http(s) 向 Web 取得資料, 然後在 Client 端運作, PHP 則介於兩者之間, 包括存取資料庫, 也包括接受 Client 端的表格(form)或 Request (如: GET/POST ).

所以除了寫程式的語法不同, 適用的資料也不同, 比如:
1. 消費者輸入訂單, 未成立訂單時, 可以在前端用 JavaScript 試算.
2. 查詢消費者累計消費金額時, 可以直接用資料庫的 select sum 算出總值.
3. 因為某些促銷, 依過去的特定消費紀錄, 計算是否符合優惠, 因為優惠不適合放前端, 可能會被直接修改, 或者需要資料庫的資料, 這時候就需要 PHP 這類程式來處理.

雖然之前用 PHP 寫一個統計系統, 因為環境單純, 都在區網速度快, 所以前端只有使用 HTML 的 form , 然後 PHP 整理後重新顯示, 使用一些 Session 變數來判斷目前顯示的內容, 所以還沒有從頭寫過 JavaScript .... XD

(跳回來)

因為寫 PHP 已經有 物件 的概念, 練習 JavaScript 並不算太大的問題, 基本的語法結構, 判斷式寫法先了解, 然後開始了解如何接收 HTML 的資料, 進行加工, 然後學一些字串判斷, 分割字串等.

目前覺得需要經驗累積的, 是 JavaScript 對變數的處理, 因為 JavaScript 支援物件, 陣列, 傳統變數等型態, 而且 JavaScript 會自動判斷目前最適合的型態, 所以做一個動作之後, 要確認回傳的型態是什麼, 要進一步處理時, 要看看 JavaScript 是否會自動轉換, 或假如輸入意外的資料時, 是否會造成意外的錯誤.

所以練習到這邊, 反而在要處理的資料上, 加了好幾道關卡, 以免意外的錯誤發生.

就這樣, 連續幾天等行政程序的空檔, 練習的心得.

影音網站網址特性....

前一篇有提到要抓網站來分析出 pattern :
http://slimetw.blogspot.com/2018/06/pattern.html

既然要分析, 就要把資料存在合適的地方, 現在關聯式資料庫很容易取得跟安裝, 就分析的網頁結構來說, 不存整部影片的話, 硬碟記憶體空間也很大.

既然要存 資料 , 就要大約知道有哪些資料, 要如何分類, 正規化才能依這些特性進行.

回到原本的主題: 影音網站的自動抓取. 因為不是抓影片本身, 而是抓連結, 再從連結內容分析出 pattern , 再找出可能相關的連結, 排除廣告, 再給程式繼續抓.

所以最關鍵的就是網站連結, 一般會使用 URL 規格, 雖然 URL 基本上不會重複, 但是對影音網站來說, 常常會有配合廣告商, 在連結後面加上廣告商或某些分析用的變數, 例如: /?ref=2397 或 /embedded=xvideo

所以連結可能看起來好幾個, 卻都是同一個影片, 或者同一個業者用了多個 Domain Name , 其實結構都是一樣的, 或者新廠商 A 向廠商 B 致敬, 網址結構相同, 而內容卻不同.

因為這種特性, 所以網址本身必須"純化", 包括幾個步驟:
1. 去除 URL 多餘的變數.
2. 影音網站的網址結構區分:
a. 單一影片.
b. 影片組 ( playlist 或 favorite )
c. 網站整理好的如: 依女優或其他類型列表.
d. 搜尋類型.
3. 再依上面的結構, 分別拆出不同的資料:
a. 影片在該網站內的序號(必存), 影片名稱( 8 成有, 但很多名稱是亂打的), 番號( 3 成有)
b. 通常只有 playlist 名稱或 tag .
c. 這部份不同網站有不同的方式, 有些會編序號, 有些網站只用羅馬拼音, 如果是羅馬拼音就要再加工.
d. 有些網站會故意把影片切短, 然後用影片名稱去搜尋, 屬於影音網站特有的方式.

所以要分析網址, 就要先知道這些分類, 網址的 pattern 才有意義.

影片網站pattern初步分析

要做網站分析, 網站就要分析出結構, 找到 pattern .

而從單純到複雜的程度, 大約是:
1. 政府網站: 基本上不會有廣告, 結構也最單純.
2. 製造業的公司網站: 產品可能會變化, 但基本上不會有廣告, 結構也不太會變.
3. 遊戲網站: 雖然動畫可能很多, 廣告則大多是自家的.
4. Blog 等互動網站: 廣告很多, 大多是別人家的, 結構反而單純.
5. 影音網站: 別人家的廣告多, 自家的廣告也多, 彈跳視窗多.

既然要分析網站的 pattern , 抓取網站內容才能分析, 不過要分析之前, 就要先思考網站裡面有什麼東西.

以影音網站而言, 最重要的影片只會有一個, 就是正準備播放的影片.
但是超多廣告, 所以廣告也要分類, 如果連結是同一個網站, 那可能是自家的.
連結是不同網站則可能是別人家的.

但是這樣並不容易找到影片的本體, 所以還是要試著分開, 例如:

標題: 影片 A ; 影片 ; 影片簡介或分組 g1 ; 廣告(自家) * n1 ; 廣告(他家) * n2
標題: 影片 B ; 影片 ; 影片簡介或分組 g2 ; 廣告(自家) * n3 ; 廣告(他家) * n4

因為廣告可能有數量上的不同, 但仍有一些共通的特性, 就是標題通常是唯一且跟影片最接近的, 所以拆 pattern 時, 就可以先從標題下手, 找出標題大約被包在哪個 div 內.

而影音網站的廣告(自家), 往往就是其他的影片連結, 所以這邊抓出 pattern 後, 就有機會透過程式自動去把所有的連結找出來.

PHP + cURL 爬蟲基本語法

寫程式常常會聽到: 不要重複發明輪子! 或 站在巨人的肩膀上.
意思是已經有很多工具可以用的時候, 學習使用工具就好. (當然授權也要注意.)

如果要做一個網站分析的程式, 首要工作就是把網站的內容抓下來.
抓網站內容就有一個好工具: cURL , 基本上沒有授權問題, 而且 PHP 內已經有相關語法可以直接使用(註1).

在 PHP 內使用 cURL 的步驟, 大約是:
1. curl_init() 初始化一個連線.
2. curl_setopt() 指定相關參數.
3. curl_exec() 連線抓取網站資料.
4. curl_close() 關閉連線.

這樣好像不知道要抓什麼? 其實全部都在 curl_setopt() 內設定, 以常用的功能來看:

$ch = curl_init() ;
$url = 'https://slimetw.blogspot.com/' ;
curl_setopt( $ch , CURLOPT_URL , $url ) ;
curl_setopt( $ch , CURLOPT_HEADER , true ) ;
curl_setopt( $ch , CURLOPT_RETURNTRANSFER , true ) ;
curl_setopt( $ch , CURLOPT_FOLLOWLOCATION , true ) ;
$temp = curl_exec( $ch ) ;
curl_close( $ch ) ;
echo strlen( $temp ) ;

指定一個網址, 然後抓取時連同 header 都抓(註2), 用 CURLOPT_FOLLOWLOCATION 設定允許轉址, 然後用 CURLOPT_RETURNTRANSFER 設定回傳的資料不是直接顯示, 而是可以轉給其他地方用.

執行這個 PHP 之後, 就會把網站本身的內容長度顯示出來, 這當然不是主要的功能, 而是連線測試, 以後只有網址跟存放的地方會換掉, 就可以寫成函式(function)多次呼叫使用.

註:
1. XAMPP 7.2.6 包含的 PHP 已經內建.
2. header 是由網站主機提供給瀏覽器用的參考資料, 一般不會呈現給使用者看, 不過假如以後要分析可能會用到, 所以先抓.

用 MariaDB 切 URL 文字

字串的處理往往是因為應用上的需要,
而在"網站爬蟲"時, URL 常常是要分解的字串,
所以對 URL 的處理就有幾個部份:

A. 判斷是否為 URL :
以一般網站而言, 是 http:// 或 https:// 開頭, 後面至少有一個 / ,
所以可以用 正規表示式 來判斷, where url regexp '^https?://.*/.*$'

B. 如果是網頁 URL , 取出協定 :
因為預設 URL 是有 :// 字串, 所以可以用 position( in ) 來找到字串內的位置, 再用 left 剪裁.
比如: position( '://' in 'https://' ) = 6 表示 :// 從第 6 位開始(註1)
但是如果用 left( 'https://' , position( '://' in 'https://' ) ) 結果是 https:
雖然也是可以理解, 不過一般來說協定只要紀錄成 https , 所以長度要減 1 ,
就用 left( 'https://' , position( '://' in 'https://' ) -1 ) , 取得協定是 http 或 https

(註2)

另外的方法也可以用 regexp 判斷開頭是 https:// 就直接寫入 https 到指定欄位等作法.

C. 為了分析不同網站的 pattern , 所以取得 hostname 紀錄也是必要的,
比如: https://hostname/A/B/C 使用 / 區隔找出 hostname , 但左邊開頭有 // , 可能造成誤判,
所以分兩個階段, 先切成 https:// , hostname/A/B/C , 再取出 hostname ,
第一階段類似前一個步驟取協定的方式,
position( '://' in 'https://hostname/A/B/C' ) = 6
要取得 hostname/A/B/C , 原字串從右側取出總長度減去左側不要的字串長度
所以語法是: right( url , length( url ) - position( '://' in 'https://hostname/A/B/C' ) - 2 )
要 -2 的原因是搜尋 :// 時, 位置在 : , 如果沒有 -2 , 剩下的字串還會有 // , 盡量精簡就不留這個.

取得 hostname/A/B/C 之後, 再判斷一次 / , 就用
left(
right( url , length( url ) - position( '://' in 'https://hostname/A/B/C' ) - 2 ),
position(
'/' in
right( url , length( url ) - position( '://' in 'https://hostname/A/B/C' ) - 2 ) - 1
)
)

就可以取得 hostname , 存起來.
註1: MariaDB 字串位置從 1 開始, 有些軟體或資料庫字串會用 0 開始.
註2: 雖然大部分網址會用小寫字母, 不過有時候複製或轉換常有首字變大寫, 特別是經過 Office 軟體複製貼上, 所以比對時最好加上 lower() 處理.

上週五到昨天在練習QGIS,
然後主管提到地段率, 嗯....

大概兩種作法:
1. 用地段率資料->所有地址或宗地->依地籍圖找座標
2. 用地段率資料->道路座標->分段畫出來

不過地籍圖資料跟道路資料就要找地政單位或養工單位了....


雖然想到要硬幹....

從業務端的地址資料庫, 撈出該路段分奇偶數的第一個跟最後一個
例如:
柏油路1號, 柏油路99號
柏油路2號, 柏油路100號

然後丟給Google地圖轉成座標, 再把座標拉回QGIS當基準點, 手動畫直線.
不過Google地圖回傳的座標系可能不同, 或使用建物中心點的座標,
把座標拉到QGIS後實在對不起來....先想想其他辦法.
以往寫程式, 變數內容在 0 , "" , empty , null 間應該需要一點時間熟悉.

不過在使用函式(function)時, 除了以上幾個之外, 還多了一個: 變數是否已經初始化? 以 PHP 來說, 沒有初始化的變數, 呼叫 函式(變數) 會錯誤....

行動支付繳稅推廣

本網頁僅為個人整理, 引用的資料可能異動而不符現況, 也不代表任何官方說法
行動支付是指使用行動裝置進行付款的服務;為便利民眾,政府也增加使用行動支付的方式繳稅,大約可分為遠端與近端兩種,特點如下:
遠端 近端
名稱 等(不含LINE Pay)
繳稅方式 網路繳稅 臨櫃繳稅
台南市財稅局全功能服務櫃檯:
嘉義區監理所稅務櫃檯:
支付工具
注意: 需搭配支援的手機與信用卡, 信用卡也要支援公務機關信用卡繳費平台才能用
例如: 渣打目前不支援
申請流程
繳稅方式 手機完成綁定信用卡之後, 持手機及稅單到財稅局及監理站據點, 由服務人員引導使用NFC感應扣款.
優惠 台灣Pay金融卡繳牌照稅抽MacBook Pro

可繳納稅目: 牌照稅(4月, 營業用10月再一期), 房屋稅(5月), 所得稅(5月), 地價稅(11月)

常見問題:
  • 台灣Pay: 需要以手機號碼註冊, 收到"簡訊認證碼"之後, 再設定"使用者自己設定的台灣Pay密碼", 要新增金融卡時, 要填寫銀行詢問的問題, 再收到"雲支付金融卡(虛擬金融卡)認證碼", 再設定"使用者這張雲支付(虛擬)金融卡密碼".

其他: 亦可申請約定轉帳納稅等方式.
如果您因為本網頁說明而申辦成功, 敬請回饋申請資料, 以便列入個人推廣業績.

撈資料與呈現的心得

這次的案例主要是, 人員有分總局跟分局,
分局要看分局所轄駐點全部的資料, 確定都有填報, 所以不管有沒有資料都要顯示.
總局要看全部分局所轄駐點, 但只要顯示有填報的資料.

在資料撈取的結構上, 切成 分局代號 , 駐點代號 , 項目 , 期別 ; 撈取的功能分成 明細 , 單項加總 ; 另外有一項功能是查詢最後修改的紀錄, 也用來判斷如果沒有修改記錄, 就不用再查明細跟加總.

資料結構上, 一個分局有多個駐點, 所以先依登入帳號屬於總局或分局, 撈取的駐點清單就加上條件(若是分局人員, 只撈取分局所轄駐點), 這樣雖然清單都是"駐點", 明細數量卻不同, 而主要程式結構就不變.

撈取駐點後, 依期別撈取所有已填寫的資料, 產生一個"實際填寫的項目(A)"陣列.
再來則是從項目清單與駐點清單, 產生一個"應該要有的項目(B)"陣列.

最後要轉成網頁畫面時, 再依登入人員決定要顯示的項目:
如果是分局, 就把整個"應該要有的項目"都呈現出來, 如果項目已經有填寫, 再顯示填寫的項目. (概念是B left join A)
而總局只需要已經填寫的項目, 所以是以實際填寫的項目, 把顯示的名稱撈出來. (概念是 A join B)

這樣整個程式大架構不變, 只有在物件導向的類別(class)加上參數, 撈取的資料就不同, 而顯示時, 也只要小幅度的判斷要顯示的部分, 其他部分都是讓迴圈自己跑.

而且這樣可以避免一種狀況, 就是有些寫法會先產生應有的項目, 再去資料庫指定要搜尋項目的值, 但這樣如果未填寫的部分, 因為資料不存在時, SQL 會將所有填寫明細表搜尋一次才確定為 NULL , 而花較久的時間.
行動支付, 雲支付, 電子票證, 電子票卡, TaiwanPay, 虛擬卡, 金融網路服務, 銀行網路APP, 銀行網路APP裡面的台灣Pay....

一堆很口語卻沒有架構的名詞, 只會讓行動支付更亂啊....

最傳統的是銀行帳戶(活儲存/活存/口褶), 然後定存(另一個帳戶但可以跟活儲存/活存互轉).
這帳戶的活儲存/活存, 可以透過"金融卡"提款, 之後又可以存款.

美國有兩大信用卡認證機制(VISA/Master), 日本有JCB, 原本是刷有凸起的卡號, 再簽帳(Credit); 在台灣則由透過銀行發行信用卡, 為了便利, 銀行也會將信用卡與自家的金融卡結合.

電子票證原本是為悠遊卡量身定做, 而市面上已經有iCash等業者自己發行的卡, 後來又有一卡通等, 這些卡總算有一個類似的規格, 就都歸類在電子票證, 都是在台灣非銀行業者發行.

信用卡業者也求發展, 所以又有兩種作法: 1. 感應式信用卡 2. 綁金融卡; 感應式信用卡的消費流程跟信用卡一樣, 差別只有刷卡方式; 綁金融卡則是透過信用卡認證, 但認證後直接由金融卡對應的活儲存/活存帳戶扣款(可能先圈存定額再實際扣消費金額.)

而許多公司都有預收會員費等機制, 加上網購平台等業者覺得傳統信用卡對於爭議款項處理麻煩, 而手機上網又開始盛行, 所以就有業者希望透過手機來處理金流, 把不同於以上的方式, 歸類出行動支付.

只是在台灣, 這些錢都需要被財金單位管理, 所以各業者的錢往往要存在指定帳戶內不能隨便動用, 行動支付業者多(目前有6~8間), 店家要處理的成本就高而降低意願.

而台灣Pay前身是T-wallet+, 由中華民國政府xx單位跟官股銀行一起來跟民間搶市場用的....把原本銀行的活儲存/活存, 透過HCE等機制, 產生手機APP內的特殊代碼(token), 想像成虛擬的另一張金融卡, 而可以透過QR code傳送指定的交易類型, 再使用手機內的虛擬金融卡, 由指定的銀行帳戶轉帳.

另外三大手機業者推出的GooglePay, ApplePay, SamsungPay, 則是原本手機內的信用卡付款機制, 除了買手機內的App外, 也建立虛擬的信用卡, 並在支援的店家, 透過NFC傳送手機內的虛擬信用卡(token)給信用卡業者認證, 但是在台灣因為要透過發卡銀行跟業者的刷卡機, 所以往往會出現"F家(合作的卡機業者)支援4間銀行的卡, S家(合作的卡機業者)只支援1間銀行"的限制....

這樣應該可以稍微解釋在台灣的行動支付為什麼這麼複雜了....因為銀行跟政府每個步驟都在檢核啊.... XD

廉價刮鬍刀的好幫手: 香皂.

廉價刮鬍刀的好幫手: 香皂.

現在的刮鬍刀大多是拋棄式, 將刀片用塑膠固定; 很少傳統一個刀具, 裡面刀片可以換的款式, 後者大概只有傳統美容理髮店才有了.

而拋棄式刮鬍刀除了刀片外, 也越來越多花樣, 要刮鬍泡沫讓刀子滑順, 或刀片上下有潤滑層, 幾天就會乾掉, 提醒使用者該換刀片了....

回想一下, 潤滑層, 刮鬍泡沫的主要功能? 潤滑啊....

那手邊還會潤滑的還有什麼? KY嗎(x), 就是洗手台旁邊常見的香皂啊.

既然是潤滑為主, 就拿拋棄式刮鬍刀, 先刨一點香皂, 然後沾一點水, 接著要刮鬍子就很滑順了, 刮完鬍子, 一樣用水把臉洗乾淨, 把刮鬍刀沖乾淨, 然後再刨一點香皂, 吸水跟隔絕氧氣, 刮鬍刀就不易生鏽而可以用更久了.

物件導向設計的方便性

物件導向設計的方便性

以前寫過的程式, 雖然會使用函式(function)將通用性的功能包在一起, 不過需要自己設定一些變數, 避免干擾其他程式設定.

看了物件導向的程式範例後, 總算理解: "封裝"不只是把函式分類, 而是透過物件導向語言, 在程式寫成類型後, 語言就會幫忙把程式每次產生的物件分開, 省去寫程式的人自己做標記或加上一堆變數的工作.

比如這兩個月在新工作的其中一個任務, 就是寫一個為民服務統計系統, 在經過幾週的訪談跟取得現有文件後開始分析. 流程還算單純, 就填報人, 核可, 統計; 但是為民服務項目很多樣化, 所以有些以天為單位, 有些以月或季為單位, 有些項目在機關但又有駐點.

所以應用物件導向的設計原則, 後端先把系統用的功能如資料庫連線, 服務管理, 帳號管理, 週期(日, 月, 年), 駐點單位分別建立一個類型.
另外參考MVC結構, 進網站基本上只有一個PHP網頁, 而透過隱藏的參數, 這個網頁再引入其他的網頁內容來顯示.
比如剛開始就是先判斷參數"目前使用者", 推測是否已經登入, 再自動引入登入畫面.

登入後, 依登入者的權限, 顯示相對應的功能, 在填寫服務功能下, 主畫面只有引入服務清單, 然後呼叫服務管理內的判斷是否已經填過, 或已經過期無法填寫, 這判斷就放在服務管理類型下, 每個服務只要直接用 類型::static_function(服務代號,查詢); 就可以了, 實際運作就由 服務管理 這個類型內的動作去處理, 完全不用再考慮到底怎樣處理的, 而 服務管理 類型裡面就包含呼叫資料庫, 也是只有短短幾行, 其他由 資料庫 的類型內的其他程式去處理, 這樣 服務管理 本身就只負責服務相關的處理.

基礎架構規劃好, 實際上寫程式時也就方便多了, 因為填寫資料大概分為表頭與表身存檔, 表頭包括: 期/機關/填寫日/是否鎖定/服務專案, 表身是服務專案內的清單, 以及實際服務人次.

有些服務專案多了駐點, 則評估影響的範圍, 包括填寫網頁內新增第二層清單, 以及服務管理中跟表頭有關的動作, 加上選擇性對駐點的判斷, 程式中有駐點則增加一點動作, 其他程式都不變.

所以主架構完成後, 加上駐點只要一天就完成了, 這就是物件導向程式的方便所在.

除濕輪(或沸石)除濕與壓縮機除濕簡易比較

除濕輪(或沸石)除濕與壓縮機除濕簡易比較:

1. 原理:

A. 除濕輪空調是用吸水的材料, "捕捉"空氣中的水分子, 然後轉動除濕輪到另一個加熱區, 讓水分子蒸散離開材料, 再因為冷空氣而凝結成水滴.

相近的動作在電子防潮箱也是, 先打開內門讓吸水材料吸收箱內的水汽, 隔一陣子關掉內門, 改開外門加熱, 只是水分子直接蒸散到空間中.

B. 壓縮機空調是利用冷媒的熱脹冷縮, 冷媒管在室內吸熱膨脹, 然後傳到中介區, 由壓縮機壓縮冷媒, 這時候會釋放出原本冷媒中的熱量, 也增加壓縮機運作時的熱量, 不過是排到室外, 因為溫度降低, 冷媒管本身也會沾附水汽, 而在戶外排出.

相近的動作則是室內的除濕機, 透過冷媒的冷熱交換, 把水汽集中到水箱附近.

2. 特點:

這些設備基本動作都在於冷熱交換同時有水分子的移動, 而空調/除濕機的差別, 在於著重的功能不同.

空調是以溫度控制為主, 所以裝在窗戶或冷氣口, 隔開室內/外的冷熱空間, 通常功率也較大一些; 而除濕機著重水分的移動, 有時是裝在浴室, 更衣室等小空間, 不需要控制溫度, 所以功率可能小一點, 而且只隔離水份.

在運作上, 因為壓縮機的除濕是透過凝結, 所以在戶外下大雨, 或溫度很低時, 空氣中的濕度已經飽和, 就不易凝結, 而無法發揮效果(網友經驗大約 20 度 C 以上, 壓縮機除濕才有效果), 也就是一般人常誤會, 以為天氣冷除濕機壞掉了.

而除濕輪在運作上是直接使用吸水材料, 再加熱蒸散, 所以溫度影響不大, 但因為加熱耗能, 所以耗電量通常比壓縮機款式大.

3. 選擇:

這些設備的原理了解, 實際上的應用, 是否需要購買, 則依幾個條件考慮:

A. 家中是否有人容易過敏或貴重物品需要保存, 而需要長時間除濕?

如果是長時間的溫濕度控制, 直接買"冷熱空調", 再視情況加購除濕機, 因為要直接形成一個適合的環境, 所以大功率的空調最必要, 但空調畢竟以溫度控制為主, 如果濕度控制不容易時, 再加裝除濕機補足.

B. 是否已經有壓縮機空調? 平常室內溫度大約多少?

有些住家或租屋本身已經有壓縮機空調, 而只有人在的時候或只有少數物品需要濕度控制, 則可以考慮以壓縮機空調的除濕功能為主, 如果長時間溫度低(網友經驗常在 15 度 C 以下), 再買除濕輪式除濕機, 物品則放在電子防潮箱.
今天參訪其他地區的同行, 其他機關給他們一種很久以前使用的資料檔結構, 而同行的年輕人覺得茫然.

而看了一下, 就知道是以前電文傳送常用的格式:
Hhhhhiiiijjjjjj (表頭)
Bbbbbbxxxxx (表身1)
Bcccccclllll (表身2)
Oooooo (其他備註)
Bbbbbbxxxxx (表身1)
Oooooo (其他備註)

所以要先從找到表頭開始, 還好這是建物檔, 所以有地址, 基本上地址不是表頭就是其他, 然後同行手邊有其他單位提供的 Table Layout , 所以表頭救出來了.

然後重新排列成
H1 B1 O1
H1 B2 O1
H2 B1 O1
再把 Hhhhhiiiijjjjjj 拆開成三欄, Bbbbbbxxxxx , Bcccccclllll 拆成兩欄, Oooooo 維持一欄.

這樣就可以獲得現在常用的關聯式資料庫, 用幾張 table 去 cross 出來的大表了.

然後再用正規化的順序, 拆開欄位保留 key 值, 重新產生 distinct 的結果....

不過這是技術上的作法, 行政上向其他單位重要一份 DB dump 資料比較快.... XD



看指數型投資的兩個特徵

(雜想)看指數型投資的兩個特徵:

1. 有一種綜藝節目的問答題, 是選出很少人知道的答案, 通常正確答案就是最多人選的答案, 因為只要有少數人真的知道而答對, 其他不知道的人, 亂猜的答案基本上會平均分配.

而投資股市就像這種問答題, 不知道哪個產業哪間公司正在賺錢, 但是絕大多數公司都是正向願意賺錢的方向時, 總會一直成長, 而這整群就形成了市場.

2. 跟基金/投資型保單比起來, 指數型投資只扣除少許手續費, 而大部分都真正投入股票, 減少虛工的消耗. 就算標的相同, 基金大多還要經理費, 行銷費, 投資型保單還要轉買的手續費等.

除了大環境景氣問題, 造成公司營利無法繼續, 不然指數型投資就會持續賺錢, 市場會反應公司的營利目標; 而且民眾願意消費的方向, 也就帶動公司發展方向, 這樣只要保留生活所需, 其他的投資其實就是跟著消費市場走.

PHP 使用 PDO 讀取 MySQL , 判斷登入帳號

PHP 使用 PDO 讀取 MySQL , 判斷登入帳號完成....(雖然寫得不是很漂亮)

原理:
一支 PHP 程式, 用 POST 送登入訊息給自己, 所以程式剛開始先判斷有沒有 POST 資料, POST 資料有"動作"一項, 分為 登入 跟 登出 , 再呼叫對應的 function , 如果是登出, 則清除相關變數, 再 refresh 自己, 如果是登入, 再比對輸入是否正確, 讀取 MySQL 如果帳號檔可以查到, 表示帳號密碼正確, 並把帳號另外存在變數內.

如果沒有 POST 資料, 則比對變數內是否有帳號資料, 如果有, 就 require 主選單, 如果沒有, 則呼叫 function login() ; 顯示登入畫面.

沒有寫得很漂亮的地方在於:
1. 變數有點多, 又分在 $_POST , $_SESSION , 還有一些是 global 以便 function 取用, 沒有寫完整規格書. (感謝以前的同事幫忙發現我概念不足.)
2. 以前用 mysql 直接呼叫, PHP7 改用 mysqli , PDO , 有些語法已經忘掉(60%)或不合用(40%), 所以乾脆重學 PDO ....
3. 對陣列處理的不熟悉....
PHP 變數心得-2 :

可以跨不同程式的變數, 要這樣設定:
1. setcookie
2. POST/GET

只用 $_COOKIE["abc"] 無效, $_SESSION 也不行, 一般變數更不行....

PHP 傳送變數心得

原本有: 一般變數, 全域(global), 靜態(static)

另外有: $_COOKIE(存在瀏覽器), $_SESSION(存在server), $_POST/$_GET(由瀏覽器的表頭送給Server).

而 $_POST 有個特殊的情況, 因為瀏覽器本身有一份, 而每次 reload 程式時, 會再送出, 所以就算 server 端執行 unset($_POST) 等方式, 每次 reload 就會重送一次, 而又產生一次.

簡論: 漢字思維與拼音字母思維差異

簡論: 漢字思維與拼音字母思維差異

歐美用的是拼音字母, "字根"本身有累積其意思, 所以像嚴格的德語有定義嚴格的陽性, 陰性等, 美語則有些常見規則, 但仍有很多例外. 而字母組合成字根, 大多需要靠學習字根的含意, 所以, 學會一定字根後, 才能對話, 但字母的數量少, 拼音字母的學習上比較快.

漢字的發展則有許多字本身包含字根, 也有半數包含拼音, 所以學習漢字時, 常常是同時學習字根與拼音; 但漢字發展與簡化過程中, 一則字根的複雜性, 二則可以書寫的工具往往只有官員與商人, 所以生活用語在漢語中其實較少, 而且漢字的拼音也比羅馬字母的拼音少.

而在台語的使用上, 用漢字或拼音, 則需要依用途回到拼音與字義的考慮, 採用羅馬拼音可以接近原音.
而台語或粵語, 客語的"用詞", 個人認為有六成左右受到中原地區影響, 所以雖然很多發音不同, 但都可以透過漢字"理解"其意思.

而這就是已經習慣用漢字的人, 常有兩種誤會:
1. 台語可以用漢字, 這個問題在於漢字本身有字根與發音, 但台語還有(個人觀察)約四成的用詞, 沒有漢字的字根, 這些用漢字並不能表達.
2. 羅馬字母看不懂, 這個問題在於羅馬字母本來就不包含"字義", 而台語又不像歐美有"字根", 所以就算學過英文的人來看台語羅馬字, 仍要重頭學台語的文法.

至於透過政治打壓台語, 就屬於另一層次的問題了....


用 LINE 當臨時筆記....

由於手機裝軟體會考慮記憶體用量, 雖然 Evernote 很方便, 但很多時候只是記個帳, 記車子的里程等小事, 不想另外開軟體甚至裝軟體.

之前是用 Facebook 貼文然後設定隱私為"只限個人", 不過由於 Facebook 一直改演算法, 或有時轉貼其他訊息後, 短期的筆記就不太好找.

最近發現 LINE 群組也不錯用, 先開一個只有自己的群組, 命名時群組名稱前面可以多加幾個空白, 會讓群組排到最前面.
然後這種小資料, 就可以筆記在群組內, 如果有需要, 也可以直接轉貼給 LINE 的其他使用者.


電腦裝 Lubuntu Linux + 新酷音 + Dvorak 完成

這兩天試著在電腦上安裝 Lubuntu , 原本卡在鍵盤配置, 輸入法間, 如果預設鍵盤配置為 Dvorak , 新酷音的注音就會出問題.

先稍微說明一下結構....

由於電腦鍵盤本身有自己的 key code , 而作業系統處理時, 就分成兩種方式:
一種是直接把 key code 轉送給軟體,
一種是先把 key code 轉成 ascii 碼或類似原理, 再轉給軟體.

在歐美國家不管哪種方式, 問題都不大, 因為拉丁字母數量不多, 大概只有鍵盤配置的差別.
但在亞洲文字(含中亞地區)就有問題了, 因為亞洲文字有許多不是拉丁文字, 除了需要不同的文字編碼(如 Unicode ), 還需要輸入法把使用者從字母鍵盤按的鍵, 轉譯成應用軟體能理解的文字.

因為多了這一層, 輸入法的處理就變得有點複雜, Windows 2000, XP, 7 跟 MacOS X 的輸入法, 都可以跟系統語系分開, 而 Linux 由於大多是開放軟體, 所以也有許多不同的輸入法平台, 目前常見的有: iBus, SCIM, Fcitx, 而 Lubuntu 17.10 預設是使用 Fcitx .

因為新酷音(支援注音輸入方式)是在 Fcitx 平台上運作, 所以使用者從鍵盤按的鍵, 會先經過 Fcitx 處理, 如果系統預設鍵盤為 Dvorak 時, Fcitx 就會以 Dvorak 排列的方式, 傳給新酷音, 反而打出來的是錯的.

所以要使用 Dvorak 當鍵盤配置時, 就需要修改新酷音的設定, 這次整個安裝過程大約是:
1. Lubuntu 17.10 隨身碟開機, 清空硬碟安裝, 語言選 中文(繁體) 鍵盤配置先選 英文(美國), 這樣會自動裝 Fcitx 及新酷音.
2. 在語言與文字把 漢語(台灣) 拉到底下, 這只是個人習慣, 系統顯示都是英文.
3. 了解 Fcitx 結構, Fcitx 把輸入法的第一項稱為"未啟用(inactive)", 其他的輸入法稱為"啟用".
4. 調整 Fcitx 設定, 主要有: a. 切換輸入法包含"未啟用"的輸入法 b. Share State Among Window 改為 PerProgram , 然後輸入法選 Dvorak 跟新酷音兩個.

5. 最後修改 ~/.config/fcitx/conf/fcitx-chewing.config , 增加 Layout=Dvorak Keyboard

6. 登出再登入, 就可以得到預設輸入法是 Dvorak , 而按 Ctrl-Space 或 Ctrl-Shift 都可以切換成新酷音了, 也就更接近原本 Windows 2000, XP, 7 或 MacOS X 的方式.

(Windows 8/8.1/10那種把語系跟輸入法綁得亂七八糟的就別管了....)

PHP&MySQL學習(續.登入)

可能架構上希望比較有彈性.

網路上的範例大多為:首頁 -> 登入 -> 使用功能.

而我想的是: 登入為獨立系統, 在檢查未曾登入或已經過期, 就會跳出來確認, 而且確認後可以繼續使用原功能.

目前已經用mysqli連線, 但"首頁->登入"建立的SQL連線, 在登入頁的<form>轉向驗證後的PHP, 原本的SQL連線就無效了.

另外在安全性&預防SQL injection考慮下, 密碼檔的帳號是MySQL加密, 而密碼檔的密碼是PHP讀寫時就加密, 這樣就算直接讀資料庫也無法得知帳號.

另外看起來趨勢是改用PDO, 還要學一下OO概念跟寫法....

PHP&SQL登入考慮

  • 存放項目
    • SQL: 帳號, 密碼, 目前的session辨識碼, 登入時間或到期時間
    • 瀏覽器Cookie: session辨識碼, 到期時間.
    • PHP不同程式: 載入時寫一個變數, 平常執行時會檢查變數是否已經設定.
  • 處理的條件:
    • 登入時(瀏覽器無Cookie, SQL內無session辨識碼及時間.
      • 首頁->登入頁->輸入帳密->檢查帳號密碼是否與SQL相符->正確的話給一組session辨識碼, 同時記錄於SQL及cookie.
    • 正常運作程式
      • 隔一陣子更新一次session, 同時更新cookie與SQL內記錄
    • 過一陣子開程式
      • 功能頁->檢查cookie session是否到期->如果已經到期->重新檢查帳號密碼->更新session->回到原畫面或登入頁.
    • 登出時
      • 清除cookie, SQL的session辨識碼
    • 在另一台電腦登入時,
      • 比對session不同, 依應用面決定允許多個登入, 或踢掉原登入.