Python Plot 雙Y軸對齊任一值(如:對齊0)

用Plot做圖時,覺得雙Y軸對齊會好看多了,但是網路上沒有令人滿意的正解,最接近的是找到這一篇《Python – dual y axis chart, align zero》。

仔細詳讀,可能是個人理解能力衰退了,也不明白是如何運算,直接套用也會讓部分數據被新設的最大值或最小值被切掉。

回到數學,要左右Y軸對齊在某點上,首先要讓第一軸的V1點對到第二軸的V2點出發,之後再做延伸。

接下來,選一軸(通常是AX1)為主,依照AX1對應V1的比例,以V2為中心點,以AX1的比例延伸直到涵蓋AX2的原範圍,確保數據能不被切除。

不過,在此情況下,V1對到AX1最大或最小值,調整AX2會是無解的。此時換成去調整AX1。若再調整AX1也無解,可能是無法對齊或是不需要對齊。

最後,若V1不在AX1內,圖表的Y軸當然不會顯示V1,自然也無法對齊。所以在計算之前,得先確保V1與V2都出現在AX1與AX2內。


def align_yaxis(ax1, v1, ax2, v2):
    # 取得AX1和AX2的範圍
    miny1 , maxy1 = ax1.get_ylim()
    miny2 , maxy2 = ax2.get_ylim()
    print(“調整前”, miny1, maxy1, miny2, maxy2)
    # 確保 v1 一定出現在AX1
    if v1 > maxy1: maxy1 = v1
    elif v1 < miny1: miny1 = v1
    # 確保 v2 一定出現在AX2
    if v2 > maxy2: maxy2 = v2
    elif v2 < miny2: miny2 = v2
    # 與V上下距離
    upy1 = abs(maxy1 – v1)
    downy1 = abs(v1 – miny1)
    upy2 = abs(maxy2 – v2)
    downy2 = abs(v2 – miny2)
    print(“調整中”, miny1, maxy1, miny2, maxy2)
    # 有解
    if upy1 > 0 and downy1 > 0:
        up_ratio = upy2 / upy1
        down_ratio = downy2 / downy1
        # 調整AX2
        if up_ratio > down_ratio: # 如果上方需延伸較多,則對齊最大值,依上方比例去調整最小值。
            miny2 = v2 – downy1 * up_ratio
        elif down_ratio > up_ratio:
            maxy2 = v2 + upy1 * down_ratio
        else:
            pass
    # 調整AX2無解,則調整AX1。注意比例是AX2/AX1,故調整AX1時,調整比例需要變成倒數。
    elif upy2 > 0 and downy2 > 0:
        #因為upy1或downy2為0才會來到這裡,若除其中一項將會發生除零的錯誤。
        up_ratio = upy1 / upy2
        down_ratio =  downy1 / downy2
        if up_ratio > down_ratio:
            miny1 = v1 – downy2 * up_ratio
        elif down_ratio > up_ratio:
            maxy1 = v1 + upy2 * down_ratio
        else:
            pass
    # 調整AX1與AX2都無解,則不調整
    else:
        print(“無法調整或不需調整”)
        pass
    # 重新調整AX1和AX2
    print(“調整後”,miny1, maxy1, miny2, maxy2)
    ax1.set_ylim(miny1, maxy1)
    ax2.set_ylim(miny2, maxy2)
    return None

ACCESS如何移除完全重複的資料

在用python做回測時,發現同樣時間的資料點有兩個,仔細檢查,原來是access的資料表有重複資料。

一般教學是教只有一項重複,但是,因為是用python寫入,結果重複資料全部欄位皆相同。

每次用access都有一種水土不服的感覺,明明就是用python或sql很好理解的解法,但是access的使用者介面卻讓自己用不出來。

如何移除完全重複並只保留一項,這花了不少時間才找出解法,在此紀錄一下。

最大的問題是「兩筆資料完全重複」,直接用SQL篩選就一定會同時篩出兩筆。

如果讓兩筆資料不完全重複,至少一欄,那就能用SQL篩出刪除重複。

如果不熟的朋友,建議先備分資料表。

步驟一:替有完全重複資料表新增一欄「自動編號」。

步驟二:「建立」→「查詢精靈」→「尋找重複資料查詢精靈」→選擇該資料表。

步驟三:選擇「應唯一」含有重複值的欄位(如日期或ID),下一步 

步驟四:選擇「自動編號」附加查詢,下一步  ,完成。

步驟五:選取該查詢「設計檢視」。

步驟六:在「自動編號」新增準則,如果是輸入一次兩筆完全重複資料,則是「mod 2 = 1」,除二餘一或二都可以。如果是連輸兩次,則篩選開始重複的標號。

步驟七:「設計查詢」右邊按下「刪除」,然後按下「執行」。

步驟八:跳出警示視窗,詢問是否要刪除,選擇「是」。

步驟九:回原資料表,刪除「自動編號」欄位,即大功告成。

當初想快破頭,現在仔細想想,都是因為sql沒有能選擇其中一個重複資料,代條件選取會同時選中所有重複資料。直到看到用自動編號,才破解了這個難關。

PTT八卦版爆文分析 教你如何發『秒』爆文

最近看到了一篇文章《[爆卦] 大量帳號行為異常》,激起我的研究心。公關公司到底要怎麼認定?是否看到的情勢都是砸錢買出來的風向?要如何找出那些刻意帶風向的帳號呢?


我覺得這行為很不公平,就像中國玩家因為遊戲語言或是一些敏感因素就刷爆大量負評,即使水準不高的只占一小部分,但是「基數」高,那就會變得很可怕,並且可以掩蓋掉其他聲音。 公關公司帶風向也是如此,只要花錢買,就能讓特定聲音的基數增加,但那並不是真實地反映社會人民觀點。這樣的利弊就像獨裁政權,好能到很好,壞就無法與之抗衡,社會一起沉淪。 怕的不是做對的事,而是怕拿去做壞事。 本文不是要揪出那些帳號,因為是否背後為公關公司實在難以認定,此外,板規也沒有不允許這樣的現象。 不論怎麼防,只要存心要帶風向,都可以繞過去。 所以做點愉快點地分析,教你如何發『秒』爆文,一分鐘內就『爆!』文。 →在地震發生當下,東部在震,北部還沒震時就要發起來,搶得首篇發。 PTT八卦版的尖峰時間:10:00 – 13:00、 15:00 – 19:00。 即使沒有搶到地震,也可以用「發錢」,來吸引鄉民近來幫你推。 本次數據是在2019年3月1日晚間取樣, 樣本是2019年1月1日到3月1日的八卦版30推以上的文章,共有約7900則。 以及其留言,共有約184萬則。 爆文的定義是:推 – 噓 >= 100。 其中『秒爆!』發文後不到一分鐘內就爆文的有七篇。 這些文章的最大相似點就是「地震」。留言內容大多為「有感、超大、台北」。 「你媽知道你地震不逃命,還急著上ptt發文推文嗎? = =」 接下來『五分鐘內的爆文』,共四十篇。 這些文章的主題是「發錢、紅包、新年」,總而言之就是發p幣收買推文。 『十分鐘內的爆文』,共九十篇。
文章的主題是「發錢、紅包、小魏、蔡英文、新年」,這次多了小魏跟蔡英文。小魏是時下熱門,但這小魏相關的十分鐘內爆文,內容也是「發錢」。 如果有發錢求推文,很有可能十分鐘內就會被推爆! 『三十分鐘內的爆文』,共四百六十篇
文章主題又洗了牌:「蔡英文、發錢、柯文哲、中國、韓國、台灣、總統、有沒有、還願、八卦」。 三十分鐘內的爆文,政治味就濃厚許多了。 留言內容共313461則,前十五大字詞:「台灣、中國、真的、XD、笑死、小英、9.2、崩潰、總統、柯粉、美國、垃圾、國民黨、支那、一堆」,基本上可以隨機組合「台灣真的XD」、「中國笑死9.2」,八九不離十就是這些。 『六十分鐘內的爆文』,共九百三十五篇
文章主題:「蔡英文、台灣、柯文哲、中國、韓國、發錢、總統、高雄、還願、華航、柯P、網友、共識、有沒有、習近平」 六十分鐘內,幾乎只剩下政治相關了。 蔡英文地震發錢! 留言內容共313461則,前十五大字詞:「台灣、中國、真的、XD、笑死、9.2、柯粉、崩潰、美國、小英、總統、垃圾、國民黨、一堆、支那」。與三十分鐘內的幾乎無異。


『爆文冷知識─統計數字』


【爆文速度】


平均一篇爆文,用上192.58分鐘,才被推爆。
有一半的爆文,不用到48分鐘,就已經被推爆。
每三篇爆文,其中有一篇會在30分鐘以內,被推爆。

【爆文時間分布】


合計
04:00
1
2
1
4
0
4
3
15
05:00
3
4
4
3
2
3
2
21
06:00
6
9
3
8
10
7
2
45
07:00
7
8
20
7
11
9
16
78
08:00
13
24
18
18
19
13
6
111
09:00
16
16
13
20
20
16
15
116
10:00
18
27
33
19
21
13
20
151
11:00
19
20
30
33
22
16
11
151
12:00
23
39
30
21
24
10
11
158
13:00
19
21
23
23
20
27
12
145
14:00
22
23
20
15
21
18
16
135
15:00
15
27
30
17
27
18
21
155
16:00
32
30
27
14
21
22
14
160
17:00
21
22
27
22
21
27
13
153
18:00
29
18
22
23
22
18
22
154
19:00
20
23
22
26
22
13
11
137
20:00
28
23
24
28
28
24
28
183
21:00
27
15
23
29
22
18
23
157
22:00
24
20
27
19
16
23
24
153
23:00
33
23
23
15
11
20
19
144
00:00
18
26
11
15
19
19
19
127
01:00
10
17
8
11
10
14
8
78
02:00
8
6
6
3
3
6
7
39
03:00
3
4
5
4
6
6
6
34
合計
415
447
450
397
398
364
329
2800


【三十推以上的文章留言時間分布】


合計
04:00
2080
2332
2174
2195
1904
2541
3419
16645
05:00
1436
1864
1786
1906
1683
1900
1105
11680
06:00
2237
2680
2640
2333
2869
2562
1864
17185
07:00
4905
6227
6326
5724
6447
5143
4061
38833
08:00
8273
11296
11264
10523
10792
8044
6600
66792
09:00
10243
13819
12422
11904
12619
10703
9438
81148
10:00
11263
17029
15081
14891
14078
11619
11024
94985
11:00
11936
18383
16294
17384
15013
12302
11129
102441
12:00
16213
20723
21712
18521
16479
12340
12603
118591
13:00
13792
17016
18863
16171
15599
12477
11278
105196
14:00
12319
15159
14949
13404
12816
12393
10562
91602
15:00
12407
15617
15468
13675
14710
11775
10791
94443
16:00
14035
17776
17889
14227
13650
13369
11149
102095
17:00
15012
17633
17650
15348
14908
13864
11763
106178
18:00
16018
16504
16339
13960
16065
12980
12689
104555
19:00
14764
15173
14794
14808
14082
12100
12386
98107
20:00
14258
13773
13475
15302
11787
11598
12043
92236
21:00
14850
12928
13741
15860
13178
12718
11717
94992
22:00
16714
12288
13521
13980
13242
13878
13017
96640
23:00
16874
13710
14418
13459
11578
13558
12074
95671
00:00
10721
16255
11073
11551
12318
10001
12738
84657
01:00
8549
10428
8881
8229
8782
8222
9018
62109
02:00
6229
6330
5093
5490
5415
6282
6208
41047
03:00
4167
3350
3818
3720
2874
3843
4457
26229
合計
259295
298293
289671
274565
262888
236212
223133
1844057

舊家電換節電家電之選購技巧

舊換新划算公式
新家電的價格 – 補助款 <= 舊與新家電每年耗電差距 * 平均每度電費 * 電器平均壽命
※新家電會有許多入選名單,從中選價格越高的越好。

夏天到了,用電量也即將面臨高峰。面對上千多元的電費帳單,一方面抱怨怎麼那麼貴,一方面也在怎麼想著節電。如果家裡有超過十年的老家電,冰箱、冷氣、開飲機、電視、洗衣機等,現在更是時候該好好思考了。

近來JN也想到了節電,開始先調查家裡最耗電的電器。
全年:1.電冰箱。2.開飲機。3.電腦。
前兩名因為是全天運作,所以很容易被注意到,也因為是全天運作,所以節能的效果會更是明顯。

家電會有各自的平均壽命,如冰箱壽命至少要10年以上,熱水壺則是4年以上。在計算完每年能節省多少之後,乘上電器預期壽命,如果能超過省下超過購買時的電費,那就代表現在就換其實相當划算。

像是JN家,家中的舊冰箱已經超過20年,開飲機也已經好幾年了。JN第一個目標就是換掉舊冰箱。舊冰箱除了出廠很久,而且我們家沒有習慣去換過膠條,光是每日冰箱用電,可能就佔4度以上,我猜。看了帳單以後,JN家一天平均用10度電以上,有可能就是舊冰箱佔將近一半的貢獻。

電價是有級距的差別,如果懶得計算平均,計算省電費率時,直接一度電代2.6元計算。不過可以預期是低估,因為夏天時冰箱比較耗電,節能就能剩下更多電費,平均也應該會比2.6元還高。

20年舊冰箱換新冰箱,每天省下3度的話,一年能省下近2850元,十年省下28500元,剛好就能買一台新冰箱。如果未來電費調漲,那就可以預期省下更多錢,所以現在就是個換冰箱的好時候呢!

不過不同家電的耗能會因為一些形式不同而有差異,如容量。換購新節能家電的同時,要記住新家電的容量要大於等於舊家電的容量,這樣子才能確保不會換了反倒不適用。

JN建議可以直接從節能標章的網站看起,除了有產品分類可以快速查到各類節能產品,還有產品比一比可以比較節能效率。最重要的是能從續約間接看出家電出廠時間(出廠越久,價格理論會折舊),續越多代表出廠越久。從這裡開始是最能看得一目了然的。

節能標章網址:http://www.energylabel.org.tw/index.aspx

接下來從產品型號去搜尋價格,預期正常壽命能省下的電費超過售價,就能列入考量,這是最優先的條件。再過濾使用習慣(如:舊家電容量)之後,會有便宜的家電與稍貴的家電,建議選擇較貴的家電,一方面價位高的家電能預期料材好更耐用,或是有更多好用的功能,最重要的,也代表它省下的電更多,如果電費調漲,它帶來的效益就會更多。

近年來智慧家電與節能技術的成熟,10年前更換不划算,5年前更換可能也不划算,然而,現在則是今天不馬上更換才是真的不划算。如果以投資報酬率來看,十年以上老家電換新,能達到10%以上的年報酬率,這比定存或是績優存股還高出許多,換句話說,與其存錢倒還不換新家電來得有利。

Win10下排程執行Python。

Win10下排程執行Python
有時候,人因為有事或是其他因素,無法親自開機並執行程式。JN因為有需求,所以上網學習了要如何定時開機、定時執行程式、定時關機,本文將會分成這三部分教學。

定時開機

能夠持續開機,自然就不會有這問題。但是如果一定要關機的話,定時開機就會被需要。
定時關機需要兩塊的配合:WIN10的設定、BIOS的設定。(JN的主機板是ASUS Z370
必須要把WIN10的快速啟動給取消掉,BIOS的定時啟動才會正常作動
「WIN10的設定」
1.搜尋「電源與睡眠」,進入設定。
2.從右側的相關設定,進入「其他電源設定」。
3.左側控制台首頁下方,點選「選擇按下電源按鈕時的行為」。
4.把「開啟快速啟動」關掉。若無法變更,則選點上方「變更目前無法使用的設定」再嘗試關掉快速啟動。
「BIOS」
1.進入BIOS,找到高級電池管理。(※其他BIOS幾乎也在電池管理
2.開啟「由RTC喚醒」。
3.設定定時喚醒時間。 
※如果沒有先取消「快速啟動」,直接設定此部分可能會無法正常運行。

定時執行程式

定時執行程式會分成兩部分:系統設定、Python程式碼注意事項。尤其是Python程式碼注意事項,常常一個疏漏,就無法如預期地順利執行,但是因為在編寫程式(JN用Visual Studio)上卻是沒有任何問題的。所以,請務必要仔細再仔細地檢查需要定時執行的程式碼。
「系統設定」
1.搜尋「排程工作」,進入排程工作。
2.點選右側的「建立工作」,在「一般」分頁下的安全性設定,勾選「以最高權限執行」。
3.在「觸發程序」,建立自己想要執行程式的時間。
4.在「動作」,「新增」→「瀏覽」自己想要定時執行的程式(.py),按下確定。
※在其他Blog有看到需要設定引數,但是JN此篇沒有設定,因為設定引數方式,是以「python.exe」去執行。如果沒有設定,就是以「cmd」執行。
#2019-07-07:建議輸入引數,在「程式或指令碼」輸入「python」,在「新增引數」輸入完整位置。若不輸入引數,若有用到requests套件則會挑出。只要輸入引數之後,就能正常運作。

兩者的差別在於偵錯與速度,不過會出錯的地方兩者都是一樣的,所以JN會選擇效能較優的「cmd」也就是直接執行.py檔案而不設定引數的方式。
要注意JN有提到的「出錯的地方」,因為使用定時執行程式的環境下,常常是人不在電腦前面的時候,若是有錯,往往只能看到程式已經停止運作而消失在工作列,便無從得知是哪一部份出了問題,建議使用「logging」模組去紀錄程式的運作情形。
「Python程式碼注意事項」
1.不要使用「from XXX import YYY」,也建議不要使用「import YYY as ZZZ」。
※要特別留意到引入的其他自製套件,它們也不能有「from XXX import YYY」
2.不要使用相對路徑,請使用絕對路徑。(Ex: C:\abc\def\mypy.py      不要mypy.py
3.不要包含中文路徑,請使用英文路徑。(Ex: C:\asd\fgh\mypy.py      不要 C:\我的程式\asd
※建議使用「logging」去紀錄程式運作,因為使用排程工作的程式碼出錯會直接終止程式,不會在出錯的地方停住。所以使用logging,萬一程式碼出錯,還能從log去尋找蛛絲馬跡。

定時關機

定時關機有兩種作法,一種是使用「cmd」打上「shutdown -s -c “-s 關機。 -c 顯示提示字串。 -t 設定逾期秒數” -t 300」,然後會在三百秒後關機。另外一種是在python程式碼,引入「os」模組,打上「os.system(‘c:\\windows\\SysWoW64\\shutdown -s -c “-s 關機。 -c 顯示提示字串。 -t 設定逾期秒數” -t 300’)」
使用cmd的方法,可以搭配排程工作,能更精準的在指定時間關機。直接在「排程工作」「動作」「新增」,把關機指令「shutdown -s  -t 300」貼上到指令或程式碼去,它會提示似乎已包含引數,點選「是」。最後在「觸發程序」設定要執行的時程。
使用python的方法,可以搭配「time」模組去取得當前時間,或是在程式結束之前執行關機指令。

後記

這篇文章是已經閱覽過數篇相關,JN覺得可以寫一篇集大成的,給有需要的人直接的參照。JN加註了一些細節,都是JN在嘗試時有用到的,並不是網路教學都有寫到的,也希望能讓人在嘗試時更快找到哪個環節出了問題。



你的「平均餘命」

到底還能活多久呢?你知道你這年紀的人平均還存到幾歲呢?
使用「平均餘命查詢」來查詢看看自己的「平均餘命」還有多少年吧!
此外,也可以關心身旁的長輩還有多少平均餘命能活。

「愛要即時」
資料出處:中華民國內政部統計處 民國105年 簡易生命表

後記

JN最近在想平均壽命的問題,因為平均壽命有越來越高的趨勢,所以等幾十年後,到了會考慮壽命的年紀時,會不會發現我這族群的平均壽命其實也提高了不少,並不像當初看到的那樣低估。

這個問題牽扯到是如何計算平均壽命的,如果只是將該年死亡的平均年齡當作平均壽命,其實就能想像平均壽命是被低估。但是經過查詢後發現,其實平均壽命並不是以該年死亡的平均年齡當作壽命,而是把「零歲族群的平均餘命」當作平均壽命。

以這樣的方式表示「平均壽命」,JN認為是沒有甚麼太大問題的。其產生結果的過程,不論是統計上或邏輯上都是適當地,所以這數值也能被信任能適切地表達結果。

常見統計的問題就是主觀偏差,表現出來的與統計目的不符合,並不是不會算或是算錯這類的問題,JN認為這問題是更嚴重的。光是認真考量的統計就已經有機率會犯錯誤了,萬一,主觀偏差一發生,其實過程可以不用看,直接打個大叉叉,再重新修煉吧。

那,關於平均壽命會不會隨年紀越來越高呢?會的!

為什麼?因為早逝的人,年紀不會再長大了。零歲的人,可能在一歲或是八十歲死去;但是八十歲的人,可能在八十一歲死去,但不可能在一歲時就已經死去,故八十歲的族群至少能保證其平均壽命會是八十歲起跳,早先於八十歲死去的人不會存活到八十歲,故活越久的人其平均壽命當然也就會越高。

我們會想說,現在的生活環境改善很多,再加上醫療進步,所以現代的人們理論上是可以活得比以前人久很多。尤其是新一代的人,其壽命應該能更勝這一代或是之前世代的人們。不過現在這點無法體現在數據中,而我們也無法估計未來這些條件變優所帶來的平均壽命增加,因此如果要得知這樣的差異所造成的影響,我們就等得以後才會知道。

我的爬蟲進化史

JN只有看網路教學,沒有看任何一本書,所以現在自己所寫爬蟲的架構多半是靠自己發想,不知不覺也越做越有組織架構,想來紀錄今天的地步。


一、最初的爬蟲:
執行一次爬取一頁,沒有保存內容。

二、迴圈爬蟲:
可以查取多頁,沒有保存內容,中途斷開又得重來。

三、記事本紀錄之迴圈爬蟲:
用不同名稱之記事本保存爬取到各種內容。

—–分水嶺:斷點重續—-

四、導入「os」,三號之爬蟲:
將保存內容區分,如依文章ID創新資料夾,方便閱覽結果。如果內容已存在,快速跳到下一爬取項目。

—–分水嶺:資料庫—-

五、導入資料庫之爬蟲:
爬取到的內容存去資料庫,不是放到新資料夾。

—–分水嶺:特殊條件排除—-

六、任務資料表之爬蟲:
在爬蟲開始之前,能夠快速地從任務資料表找到斷點並續開,或是將特定狀況(如已爬盡所有內容)從爬蟲任務作排除。不只存放爬取內容,也會與添加主鍵型資訊一起納入資料表。

—–分水嶺:爬蟲內容影響接下來爬蟲—-

七、能操作資料庫之多類爬蟲:
依照爬取的內容,調整資料表,或創建資料表,或修改特定欄位。強化六號爬蟲的限制,爬取內容也不是只有單一種類,並且還能夠影響接下來的爬蟲項目。

—–分水嶺:設定任務後才爬蟲—-

八、任務管理器之爬蟲:
可以設定達到特定條件(如每周一)才進行爬蟲,更具智慧地且減少不必要任務之爬蟲。使用的資料庫超過一個,並且盡量正規化各種資料庫,爬蟲以查詢的方式去找尋所需要的資料,而不是遞迴資料搜尋。


進化史除了是改善爬蟲效率,還有改善其他應用的效率,如資料庫:創建查詢,盡量不開存放大筆數據的資料表。以及沒有寫到的爬蟲內容應用,如統計分析,自動化圖表呈現。

爬蟲只是個蒐集資料的工具,在這一工具內,還能順便將蒐集的資料做整理與清理。但是,如果蒐集到一堆資料不會用,就只是浪費硬碟空間。那麼要如何設計爬蟲?要從後端開始往前規劃,功能決定形式,這樣就能利用爬蟲只得到所要的資訊,也能確保爬蟲得到的是所要的資訊。

python — win32gui 特定程式窗口截圖(教學)

有天想說要用python來追蹤某視窗的畫面,並且使用圖像辨識opencv來辨識狀態,如果異狀則播放音效提醒。

上網google,首先找到這一篇:
https://hutdris.blogspot.com/2016/11/pythonopencv.html

該文作者最後仍未完成,因為功能也不是如想像的那般,可行是可行,不過侷限性太大了。作者也自行提出這個問題,想要找到解決方法。

「目前是抓取該程式的畫面相對位置,如果該程式縮到最小或被其他程式蓋過,還是會持續抓取該位置的畫面。 如果希望持續擷取該程式的畫面該怎麼作」
前提就到這裡了,本文將會「提供程式碼」與「編寫邏輯」,不過JN並非專科出身,可能會有講出錯的理解,希望能夠指正JN講錯的地方。


流程圖

 


關於如何對特定程式窗口截圖,首先要先瞭解到底截的對象是甚麼?

資料型態是寫程式的基本功,這個沒有紮實領會,寫程式就很容易碰壁。
JN透過搜尋另外一種關鍵字,找到了這篇問題。下方有人提供了大神解法與連結,也是本次JN主要參照的文章《Capturing Minimized Window》,運作流程也是照著這篇文章的流程。但是,這文章並不是用python作為程式語言,一開始雖然JN是放棄參照這篇大神邏輯,最後還是回過頭來仔細看這篇文章的概念。
本篇程式碼主要使用 win32gui 去完成,而 win32gui 剛好能找到那篇文章所使用的api,真的很巧。不過win32gui的document還是看得很頭痛,因為物件並不是用常見的python資料型態。
要如何將特定程式窗口截圖?首先要先抓區特定程式的「handle」,中國翻譯叫「句柄」,handle就是一個連結到程式窗口的路。在win32gui中,handle(PyHANDEL)通常是int型態,用int也能通大部分函式的PyHANDEL物件。
#以Name找出特定窗口的handle
win32gui.FindWindow(‘Name’)
Ex:win32gui.FindWindow(‘未命名 – 小畫家’)
用了 win32gui.FindWindow() 函式,就能找到我們目標窗口的handle,接下來要用此 handle 來找出其 handle device content (HDC)。HDC是窗口輸出的內容,各位想必開了瀏覽器來看這篇文章,你所看到的文章(畫面)都是瀏覽器的HDC,這個就是做特定程式窗口截圖的對象。
 
用電腦的時候,不一定只有開瀏覽器,可能還會打開檔案管理員。但是我們只看到瀏覽器的畫面,是因為瀏覽器的圖層比檔案管理員的還要更上方。HDC會輸出成圖層,變成圖層才會有上下之分,上方圖層會擋住下方的。如果我們直接抓取下方圖層的HDC,就不會被上方的圖層擋到的問題,也就能實踐本次的特定程式窗口截圖
 
透過handle,我們可以用 win32gui.GetWindowDC(handle) 來找出該程式窗口的HDC。接下來的工作就是要把HDC轉成常用的np.array型態,這樣就能儲存圖片與圖像辨識。HDC可以轉換成 bitmap 型態,再從 bitmap 又要轉換成 np.array。好像很複雜,你就當作是在 bitmap (畫布)輸出 HDC的內容,然後都是圖樣的東西,彼此(與np.array)互轉就不是難事了。
這邊,JN直接使用這篇範例的部分內容,主要就是將 bitmap 轉換成 np.array 。至於為什麼會這樣寫,JN並不是很瞭解,只是知道怎麼用而已。


”’
import win32con # 各種win32函式的參數
import win32gui
import win32ui
import numpy as np

hwnd = the handle of a window
x = the x coordinate of the window
y = the y coordinate of the window
width = the width of the window
height = the height of the window
”’
# 創造輸出圖層
hwindc = win32gui.GetWindowDC(hwnd)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
# 如果視窗最小化,則移到Z軸最下方
win32gui.SetWindowPos(hwnd, win32con.HWND_BOTTOM, x, y, width, height, win32con.SWP_NOACTIVATE)
# 複製目標圖層,貼上到 bmp
bmp.CreateCompatibleBitmap(srcdc, width, height)
memdc.SelectObject(bmp)
memdc.BitBlt((0 , 0), (width, height), srcdc, (0, 0), win32con.SRCCOPY)
# 將 bitmap 轉換成 np
signedIntsArray = bmp.GetBitmapBits(True)
img = np.fromstring(signedIntsArray, dtype=’uint8′)
img.shape = (height,width,4)
# 釋放device content
srcdc.DeleteDC()
memdc.DeleteDC()
win32gui.ReleaseDC(hwnd, hwindc)
win32gui.DeleteObject(bmp.GetHandle())


如此,我們透過 win32gui 的函式搜尋找到「特定窗口的handle」,然後透過 「handle 找出 HDC」, 再把 「HDC」 轉到 「bitmap」 ,然後換成「 np.array」 。到了np.array型態,用cv2.imshow()就能秀出圖片。主要功能到這裡就完成了。
接下來要修飾主要功能

主要功能只是抓取特定窗口,但是在「最小化」的時候,卻只會抓到 icon。如果窗口不解除最小化,就沒有辦法抓到完整畫面。

依照JN主要參考的文法,它的做法是將圖層透明化、取消最大小化的動畫,最後再把窗口秀出來。因為透明化的窗口圖層不會被看見,就能有「偷偷地截取」的感覺,取消動畫是讓作動加速,而窗口秀出來是避免讓截圖只抓到icon。


到這裡還沒結束,如果我們在程式運作中,又想點開特定程式窗口,如果此時沒有將該圖層透明化給還原,那麼就會發現用滑鼠再怎麼點icon都沒有畫面。但是透明度一還原,就會發現其實程式圖層在上方,擋到其他程式窗口。按照主要參考文章,它的作法會將窗口最小化後,再把圖層透明度還原。但是,依照這樣的概念運作,就會發現工作列實在閃閃發亮很熱鬧,並沒有偷偷地截圖。

所以JN這裡採取將窗口圖層移動到最下方,再把透明度還原,而沒有把窗口最小化。


”’
如果要用 win32gui.SetLayeredWindowAttributes()
hwnd (int) 要變成 WindowLong 的型態
”’

# 將 hwnd 的型態變成 WindowLong
s = win32gui.GetWindowLong(hwnd,win32con.GWL_EXSTYLE)
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, s|win32con.WS_EX_LAYERED)

# 將窗口最大小化動畫給取消
win32gui.SystemParametersInfo(win32con.SPI_SETANIMATION, 0)

# 如果沒有把 hwnd 的型態轉換,代入此函式會報錯
# 第一個 0 是 顏色,第二個 0 是 不透明度

win32gui.SetLayeredWindowAttributes(hwnd, 0, 0, win32con.LWA_ALPHA)
# 讓指定窗口顯示出來,最後一項參數( win32con.SW_…… )可以改變顯示方式
win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
# 將圖層移到最下層
# 最後一項參數,JN使用過 SWP_NOMOVE 及 SWP_NOSIZE 都會導致圖層無法移到最下層
win32gui.SetWindowPos(hwnd, win32con.HWND_BOTTOM, x, y, width, height, win32con.SWP_NOACTIVATE)

”’
此部分程式碼,「不包含」還原圖層透明度。
”’


透過這樣的方式抓取特定窗口截圖,就能解決前提連結的問題,不僅不會被別的窗口蓋過,就連最小化的窗口也能抓取。此外,也改進主要文章的缺陷,JN的方式不會讓工作列不停閃爍。

這也是JN第一篇發在GitHub的程式碼,當了初心者那麼久了,總算有東西值得發布了。


2018.06.20 刪除了冗碼,並以win10校正,避免截圖抓到四周的透明部分。

後記

程式碼發布是JN第一次嘗試,看到別人的網站爾偶會有制式的表格,JN很好奇是怎麼樣產生的。如果有甚麼方法能夠快速產生展示程式碼的表格,也請拜託在下方留言教學。

現在寫程式能寫出以前沒有能力完成的,我想這就是經驗的累積吧。慢慢累積各種方法與技巧,融會貫通就又開啟了一扇門˙,而且是以前認為沒辦法寫出來的東西。

這篇文章也是讓JN第一次接觸win32系列,win32不只存在於python,在C#還是其他的程式語言都有。我想win32系列就是windows的架構,每天從螢幕看到的、鍵盤操作的,都能用win32系列來完成,而且能做到的更強大,但是,卻也更源頭的物件。這次還碰到二進位,之前在寫都沒有注意到位元,也花了一些時間學習如何處理。

最後還有一些詞彙釐清。會用「窗口」是因為這是中國用語,而台灣常講「視窗」,然而用窗口是比較容易找到教學。此次撰寫,也讓JN分清楚「window」、「handle」、「device content」、「layer」的差異,不同的詞都有不同呈現的方式,要瞭解自己操作的是哪一種,才不會混淆或作不出來。

金融職業道德 — 快問快答!

最近要考「金融市場常識與職業道德」,直接從官網下載題庫,想說就靠題庫準備了。

為了要有效率學習,JN認為必須加入一點「刺激」的要素,如時間限制,在適當的壓力之下,答題會更容易保持專注,專注也會讓人更容易記憶。

此外,也為了實踐JN自身對「效率學習」的想像。這套快問快答,會讓答錯的題目更容易出現。即使一回錯,二回錯,到了第三回,就算還不知道題目所述,但至少答案也該背起來了吧!


使用本程式的目的為「通過考試」,但是如果想要變得專業,一定要弄懂每題所要考的概念,不然就會淪為背答案的過度學習者。

以下是示範影片
要如何使用本程式呢?(過關)
(完美路線)
1. 不斷答題,答到兩種題庫的平均每題權重小於 0.5
(效率路線)
2. 最近5次成績的平均 – 最近5次成績的全距 > 70分

希望對於要考「金融市場常識與職業道德」的考生,能透過本程式給予在準備考試上的幫助。考試考60分鐘,但JN一次約在15分鐘內完成,只要玩一個下午的時間,相信每一個人,也能很有信心可以通過考試。

如果周圍親朋好友也有要考的,歡迎轉發本文章或本程式給他們。
如果題目有誤,或是有甚麼建議,請留言在下方,下次更新會一併改進。


更新2018.6.21

身為本程式的作者,JN將考試目標分數設定為拿「滿分」,這也是實際能支持使用這程式的好處。不然要是JN沒拿到滿分,實在很難拿出證據去說服別人,使用這個程式準備真的很有效果。上大學後,也很少拿滿分,手癢,剛好這個考試不難,拿個滿分,緬懷一百分的感覺。

昨天去應試,今天查詢,不意外就是「滿分」。在考試當下,感覺只花了七、八分鐘就寫完100題,而且,寫完就知道會拿100分了。

八分鐘寫完的境界是甚麼?就是看題目外形(不是看字),以及答案外形(不是看字),大概就知道答案是甚麼了。順利的話五秒鐘就能連寫三題。不過JN不會這麼冒險,實際上有刻意拉慢速度好好看仔細,因為考前在用快問快答的時候,發現只要作答速度一快就會犯眼殘的錯。如果犯錯失了一分,就等於任務失敗,不要犯錯比較神速寫完更重要。

100題寫完後,再從頭,穩定又細心地重新讀選項與關鍵字,這完成後,才劃卡,劃卡完又再對劃卡的答案與試卷的答案有沒有一致。總之,這100題被掃過四遍,還剩一點時間讓JN趴著闔眼休息,幸好考官宣布三十分鐘到了,JN急著搶第一名交卷,急著想出去晃一晃,犒賞自己達成考前所設的目標「拿滿分」。

用這套程式準備真的很容易,想考滿分只要多玩個幾十次就能輕鬆記住,不用特別買書還是列印題庫慢慢看,用這程式邊玩邊記。

認真玩個幾遍,你也能及格!認真玩遍題庫數次,你也能拿滿分!考生加油加油!


更新 2018.6.18

1.依照勘誤表勘誤題庫
2.補上職業道德第2題、第579題的缺失文字
3.新增了音樂及音效開關。若要關閉音樂或音效,請從「setting.txt」將Music或Sound的參數改為0


後記

這其實是一隻很簡單的程式,不知道為什麼能變成224MB。裡面也沒有藏著甚麼病毒,因為我的功力還沒有到能寫出病毒呢。如果能寫出,也不會讓程式變成224MB的大小。就安心的玩吧!要是防毒軟體能偵測到有毒,再砍掉程式也沒關係。

怎麼寫出來的?因為這也是JN第一次用python寫出快問快答的遊戲,程式碼也超亂的,所以就不想放上來現醜。如果真有安全上的疑慮,JN也是可以放上整個程式碼,大概不到1MB,供有心學習的人觀摩。

用python,GUI使用tkinter,音樂音效使用pygame。題庫整理,是過去資料分析學到的經驗,用re快速清理乾淨,再用人眼快速確認沒有重大疏漏,不用一小時就弄好了。音樂從youtube無版權素材庫下載,cc是最free的那種,不用特別標註的自由使用,從檔案總管也能看到音樂的各種資訊。音效是從知識+找到的,不過這種廣泛流傳的音效版權很難有歸屬,大多也成了不用特別標註的自由使用。最後使用pyinstaller打包成224MB的exe。

個人使用過後,覺得是很棒的,比起無聊的一題一題看題庫,還是看參考書。因為設計了時間限制,所以逼得JN必須專心快速分析題目,順便動腦思考跟相類的題目差異點與共同點。另外,權重制度也不像一般的快問快答APP是隨機的(每題權重相同)。而將「權重」導入當然是為了補足弱點,也讓你本來就會的不要老是出現送你分。早點將弱點補起來,才是讓表現提升的快速路徑。

臺大學號轉系所 (網頁版)

程式連結如何使用?

1.複製學號:
文字不用整理整齊,亂成一團也沒關係,因為程式會自動找學號
2.貼上到輸入框內
 3.按下送出
4.可以將結果選取並複製到EXCEL或是其他地方





亂數產生的二十個臺大學號,並加入字打亂

d57127062@#$%^
b87850012臺大好棒棒d96409093醉月湖b32B22081YJYGHYUGHJNr03550054TGHBJBJIb02402038$&^JHJIU*(
d11921037NJI02645^&*&^*b89610052,r66454045,r25302083
r36E03069,b57207065,
“b93E04071″,’d25844094”r70612005、r95456020
d43403060FYTFGUYG
d12401000只是展示用
b14141003整理資料好用
d67408000希望派得上用場
r29455047^*(&*(&*(

為什麼會寫這個程式?

因為最近在做統計,有些時候會需要找出樣本的學院或系所,因為我們會關心這場活動的人,是來自於甚麼學院或是甚麼系所比較多。

為了要能快速找出系所,所以最快的想法是紀錄時就是有「系所」一欄,但有人填寫的是簡稱,有人填寫全名,造就同義不同詞的困擾,想做統計前,還得一個個挑選並更改成統一用詞。還有別的方法能知道其就讀系所,如果拿到了「學號」,也幾乎等同於系所。這是因為臺大學號是由「學位 + 入學年度 + 學系代碼 + (學群、組別) + 序號」組成。

從學號判讀出其就讀學系,不僅能去除簡稱全名的困擾,此外,學號也是容易取得之資料,所以大部分都很適合用此方法找到樣本的系所。

唯一缺點,轉系的學生其學號照原就讀系所,用此程式只會找到原就讀系所。


本程式適用甚麼情形呢?

1. 舉辦活動,想知道參加活動的人來自甚麼系所。
2. 拿到一串神祕學號,很想知道那個學號究竟是怎樣的人。
3. 資料格式很亂,想快速整理出統一格式

本程式參考資料來源 臺大各系所必修科目及應修學分資料查詢
整理出來的系所代碼 臺灣大學學號的系所代碼※截至2018.06.02

Pandas.DataFrame之入門九道題目–處理從html讀取的表格

JN想標題很久,想不對甚麼會很貼切,於是勉強這樣下。
 
關於Python的Pandas教學,從Google搜尋就能找到許多中國的解說。不過每次JN想要做的處理,就要再次尋找相關教學,因為分散在各地,實在很麻煩又不容易學習。而且內容詳盡的教學網站都類似教科書一樣死板呈現,然而想學的地方就只是千段中的一段文字,並不能很有效就挖掘出來。JN僅推薦從「pandas 0.22.0 documentation」去尋找如何做你想要的操作。
這篇文章是以網路爬蟲的會用到「Pandas.DataFrame」的一些處理為編寫依據,也是從實戰中有做的處理。JN相信,只要能完成這九道題目,就能整理大多數從網頁讀取的表格。歡迎分享解題過程在下方留言,而JN有天也會補上自己的寫法(可能吧)。

規則:使用「pandas.read_html()」讀取html檔案,找出左欄的表格,並且左欄表格進行整理,最後整理成右欄表格的樣式。下載html表格(dropbox)

表格來源

目標

A. 整齊表格
小明 小華 小美 小倩
鉛筆 1 2 3 4
橡皮擦 5 6 7 8
直尺 9 10 11 12
A1. 各列為一串列(list)
銷售員 = [“小明”, “小華”, “小美”, “小倩”]
鉛筆 = [1, 2, 3, 4]
橡皮擦 = [5, 6, 7, 8]
直尺 = [9, 10, 11, 12]
A2. 轉置表格(DataFrame)
鉛筆 橡皮擦 直尺
小明 1 5 9
小華 2 6 10
小美 3 7 11
小倩 4 8 12
B. 項目歪曲的表格
小明 小華 小美 小倩
鉛筆 1 2 3 4
橡皮擦 5 6 7 8
直尺 9 10 11 12
B. 修復表格(DataFrame)
小明 小華 小美 小倩
鉛筆 1 2 3 4
橡皮擦 5 6 7 8
直尺 9 10 11 12
C. 有非NaN類缺值的表格
小明 小華 小美 小倩
鉛筆 2 3
橡皮擦 5 6 7 8
直尺 9 10 11 12
C.去掉缺值列(DataFrame)
小明 小華 小美 小倩
橡皮擦 5 6 7 8
直尺 9 10 11 12
D. 表格鑲表格
a
b
j
D 小明 小華 小美 小倩
鉛筆 1 2 3 4
橡皮擦 5 6 7 8
直尺 9 10 11 12
D. 小美小倩的橡皮擦與直尺的銷售狀況(DataFrame)
小美 小倩
橡皮擦 7 8
直尺 11 12
E. 有合併欄位的表格
銷售數據
男生
女生
小明 小華 小美 小倩
鉛筆 1 2 3 4
橡皮擦 5 6 7 8
直尺 9 10 11 12
E. 簡化表格(DataFrame)
小明 小華 小美 小倩
鉛筆 1 2 3 4
橡皮擦 5 6 7 8
直尺 9 10 11 12
F. 同類的兩個表格
鉛筆 橡皮擦 直尺
小明 1 5 9
小華 2 6 10
鉛筆 橡皮擦 直尺
小美 3 7 11
小倩 4 8 12
F1. 分別加入”性別”欄位(DataFrame)
性別 鉛筆 橡皮擦 直尺
小明 1 5 9
小華 2 6 10
性別 鉛筆 橡皮擦 直尺
小美 3 7 11
小倩 4 8 12
F2. 合併F1的兩表格(DataFrame) ※性別”女”的表格在上方
性別 鉛筆 橡皮擦 直尺
小美 3 7 11
小倩 4 8 12
小明 1 5 9
小華 2 6 10
F3. 從A2表開始,分離後再進行F1、F2(全程DataFrame)
A2 鉛筆 橡皮擦 直尺
小明 1 5 9
小華 2 6 10
小美 3 7 11
小倩 4 8 12

JN的小訣竅:

A1:使用「pandas.DataFrame.to_csv()」把DF(DataFrame)轉換成csv格式(str),並逐列整理成「list」。
B:創立新的DF,逐欄(df.loc())轉移到新DF。

C:用「.replace(“-“, pandas.np.NaN).dropna(axis=0,how=’any’) 」,先把「”-“」替換成「NaN」,再用「df.dropna()」即可丟掉缺失值。
D:找出內層

,再用「df.loc()」框出所需範圍並複製(.copy())成新的DF。

E:如B。
F1:使用「df.insert()」,在索引1的欄位先插入性別,即「df.insert(1,”性別”, “”)」,之後再統一該欄位的值,即「df[‘性別’] = “男” or “女”」。
F2:用「df.drop()」丟棄男表格的第一列(為:性別, 鉛筆……),再用「df.concat()」合併女表格與男表格。
F3:如D,先切割成男、女表格,即兩新DF。但因為來源DF的index也一同被複製,所以用「df.reset_index()」重置列的編號,再用「del df[‘index’]」刪除舊的index欄。之後如F1、F2步驟。

Excel物品清單原型,掌握所有物品蹤跡

JN最近幾天突然有感而發,腦海不時浮現一種物品清單。這物品清單要能詳盡列出物品以及其所在位置(收納位置),還有各個收納位置裡面會有甚麼物品。物品跟收納位置是雙向箭頭關係,不論從哪一個開頭,最後都能到另外一端,白話來說,從收納位置可以找到有甚麼物品在裡面,而從物品列表也可以找到是在甚麼收納位置。

這份清單的最大優點:任何人只需要搜尋這份清單,就能夠準確找到物品。(前提是做好清點)

在辦公室人來來去去,未必每一個人都清楚辦公室裡面到底有甚麼東西,以及東西在哪裡。有些時候以為沒有的東西,買了新的,才發現其實藏在小角落。或是新來的人對於想要找A4紙補充印表機,卻不知道A4紙放哪裡。最後就是有空間塞甚麼就塞,沒有做好分類,以至於各種類型的物品混雜在一塊,每次要找特定物品時,各種翻箱倒櫃好像要掀開整個辦公室,實在很傷神費工。

年關將近,這時候也是大掃除的時候。趁這時候完成物品清點並且照著填上物品清單,就能享受控管各種物品的狀況。

這份JN自製的範本,用到了函數MATCH、INDEX以及巨集。平面圖與3D圖使用到「Sweet Home 3D」繪製。

範例Excel(dropbox)※轉載須註明出處

「想學習的不是公式的使用,只是Idea」JN這樣說。
在幾天前,JN用這句話把一直真正想學的說出來。函數的使用雖然重要,但是要表達的意思更重要。最重要的就是一個厲害的idea,那能把函數跟所想表達的意思串起,而不會用了一堆函數,卻沒有人看得懂。

在製作本範例的過程中,JN找到一個excel教學部落格,裡面有蠻詳盡的excel教學。不過JN沒有參考裡面的寫法。

本次範例有三個部分:1.位置圖、2.收納位置、3.物品列表。

位置圖

位置圖

使用Sweet Home 3D,盡量照著實際空間與各櫃子位置繪製。不一定要全部的櫃子都要畫出來,用分區概括表示就能簡單化圖示。最低的要求就是不論是誰看到這張圖,就能找到甚麼櫃子位於辦公室哪裡。

旁邊的標示是用Excel插入圖案做的。小訣竅:對標示按右鍵,上超連結,連結到對應「收納位置」資料表。很直覺地就能從位置圖上找到該位置有甚麼物品。

收納位置

收納位置

各收納位置一樣設超連結,連到位置圖該標示的位置,能方便從位置圖上找到該空間。

物品種類其實是過程產物,也代表雜亂程度(?)。物品名稱會對應「物品列表」的物品,只要是在入口鐵櫃A的物品,都會在入口鐵櫃A下方表列。

這部分函數稍微複雜: 以入口鐵櫃A為例
1.用MATCH找出「物品列表」中,物品位於「入口鐵櫃A」,第一個符合的相對座標。
2.用INDEX以及(1)式所得的相對座標,找到第一個符合物品的名稱。
※恭喜找到第一個了,但函數也就只能找到第一個。
3.用COUNTIF,計算「物品列表」中,物品位於「入口鐵櫃A」共有幾項。(物品種類)
如果有六項,則下面還有五項在入口鐵櫃A的物品沒有找到。
4.剩下的物品,仿(2)步驟,在相對座標再+1、+2…找出,但+值不超過(3)式的值。
※這前提是物品列表都要照「位置」排序,沒有排好就會出錯。

接下來,要如何乖乖讓物品列表照位置自動排序,即時排序,是完成這份範例的重點。將使用巨集去實現「即時排序」。

物品列表

巨集是最好用的功能,JN這麼認為。只要程式碼想得到寫得出來,甚麼功能都能實踐。但是!如果前人已經造好輪子(函數),就不要再閉門造車,直接使用前人寫好的就省時省力。

這部分巨集寫法,JN參考這一篇。此外還設了一個核取方塊控制即時排序的開關。

物品列表別忘了財產編號,真的在辦公室以財產編號去翻找東西時,會覺得很困難,因為編號又是許多數字,容易看歪就差肩而過了。

別忘了這份清單是要清點的,清點也是很費工費神。只要有使用到其中的物品就上個異動註記,下次清點如何想偷懶,就去點有異動註記的東西就好了。

最後,在設計時別沉迷於技術而忽略了原意。目的是甚麼,其他簡單好懂易操作就好。寫完此篇之後,JN也許有天會改進這份範例的一些弱點,以及增進功能。
1.收納空間‧物品名稱的函數,並非直接實踐,而是拐了幾個彎。要改成巨集直接找。
2.用巨集自動幫物品位置上超連結。