google-code-prettify

星期三, 12月 20, 2017

【QGIS】將 QGIS Server 安裝在 windows 2016 的 IIS 10 手把手教學

口白:
流動的水沒有形狀,漂流的風找不到蹤跡,任何案件的 Coding 都取決於心
唯一看透真相的是,外表看似卜朧共,智慧卻低於常人的 名卜朧共 刻爛
(謎之音:把 Code 刻到爛簡稱刻爛.爛..爛...)
Music:
#表升半音 []表高八度
4 3 2 6 4 2 3 #6 6 5 4 5 4 5 6 4 3 2 5 4 3 4 2 6 4 5 [2] [1] #6 6 5 6
4 3 2 6 4 2 3 #6 6 5 4 5 4 5 6 4 3 2 4 3 2 4 2 6 4 5 [2] #6 6 5 6
口白:
刻爛:真実はいつも一つ!

環境:
Oracle VM VirtualBox 5.1.30
VM 作業系統:Windows 2016、Windows 2012
IIS 版本:10.0.14393、8.5(測試成功)7.x (理論上都一樣未試過)
qgis server:2.14.20 ltr
qgis desktop:2.14.20 ltr

狀況:
1. 台灣的代理商、經銷商,就像是水貨商一樣
賣你東西之前,說的他的東西有多好用…會飛天會遁地…
賣你東西之後,它錢收了爽完…就不理你了…就跟花錢玩的牛郎一樣(因該吧我也沒玩過)
2. 就是喜歡不一樣,要站在巨人的頭頂上(那裡風景好阿),不要塞在水貨商的屁眼裡!
在那兩個禮拜學會寫 python 的日子裡,看了 Mosky Liu youtube 影片 年會:群在故我在,你的簡單信念是什麼 ,為了讓那些像水貨商的代理商、經銷商去呷賽(吃屎、kiss ass hole),
為了著偉大的理想,發了一篇有極微貢獻的 blog 文章,讓 QGIS Server 因使用而產生價值!
更重要的是讓那些像水貨商的代理商、經銷商去呷賽
3. 實現奧卡姆剃刀原則
奧卡姆剃刀(英語:Occam's Razor, Ockham's Razor),又稱「奧卡姆的剃刀」,拉丁文為lex parsimoniae,意思是簡約之法則是由14世紀邏輯學家、聖方濟各會修士奧卡姆的威廉(William of Occam,約1287年至1347年,奧卡姆(Ockham)位於英格蘭的薩里郡)提出的一個解決問題的法則,而其中最流行的「若無必要,勿增實體」(Non sunt multiplicanda entia sine necessitate)
「切勿浪費較多東西,去做『用較少的東西,同樣可以做好的事情』。」
我深深的覺的QGIS SERVER做到了這點…

大綱:
1. 安裝基礎環境
2. QGIS LTR 安裝
2.1 下載 qgis server 安裝包
2.2 安裝程式
3. IIS 相關設定
3.1 在 IIS 安裝 fcgi
3.2 接下來設定系統變數吧
3.3 目錄權限設定
3.4 IIS 設定
4. 建立 qgis 地圖專案
5. 測試

概略說明:
在谷哥庇佑下,遍尋天下文章…找的安裝 QGIS Server 幾乎都是安裝在 Apache 下,
只有極少數的粗略說明,幾乎毫無幫助…
IIS 也一樣有提共網站服務阿,為什麼在 windows 下還要在裝 Apache?
基於奧卡姆剃刀原則,不因該拿牛刀殺雞雞…
我一定要找出方法…

安裝方法:
1. 安裝基礎環境
在 Windows 作業系統上,安裝 iis、DotFramework 2.x 3.x 4.x…

2. QGIS LTR 安裝
2.1 下載 qgis server 安裝包
去官網下載吧

下載存檔


2.2 安裝程式
執行安裝程式吧

選 Advenced Install

挑喜歡的安裝方式吧

下一步…

由於我選擇的是 Install from Internet ,所以要選擇安裝包的位置

下一步…

下一步…

挑選要裝的套件吧
基本上我只裝了 Desktop、Server

Desktop 選裝 2.14.21-1 ltr

Server 選裝 2.14.21-1 ltr

下一步…

下一步…

安裝中…

在經歷過無腦的下一步攻擊後,終於裝完


3. IIS 相關設定
3.1 在 IIS 安裝 fcgi
預設安裝好的 IIS 是沒有 FastCGI 的喔


開啟 伺服器管理員 > 新增角色及功能

下一步吧

選擇安裝類型 > 角色型或功能型安裝

下一步吧


將 CGI 勾選

我勾了這些

.NET Framework 我裝了這些

安裝

裝好啦

FastCGI 設定 出現啦

3.2 接下來設定系統變數吧
設定環境變數

系統變數 Path 增加:
C:\OSGeo4W64\bin
C:\OSGeo4W64\apps\qgis-ltr\bin
C:\OSGeo4W64\apps\grass\grass-@grassversion@\bin 
C:\OSGeo4W64\apps\grass\grass-@grassversion@\lib
(grass 沒裝應該不用設啦…)

2016 設定界面 長的不一樣…

新增系統變數QGIS_AUTH_DB_DIR_PATH、PYTHONHOME、PYTHONPATH、QGIS_PREFIX_PATH、QT_PLUGIN_PATH、GDAL_CACHEMAX、GDAL_DATA、GDAL_DRIVER_PATH、PDAL_DRIVER_PATH、PROJ_LIB

系統變數增加變數名稱為 QGIS_AUTH_DB_DIR_PATH
值為C:\OSGeo4W64\apps\qgis-ltr\resources

系統變數增加變數名稱為 PYTHONHOME
值為C:\OSGeo4W64\apps\Python27


系統變數增加變數名稱為 PYTHONPATH
值為C:\OSGeo4W64\apps\qgis-ltr\.\python;C:\OSGeo4W64\apps\qgis-ltr\.\python\plugins;C:\OSGeo4W64\apps\Python27\DLLs;C:\OSGeo4W64\apps\Python27\lib;C:\OSGeo4W64\bin;C:\OSGeo4W64\apps\Python27;C:\OSGeo4W64\apps\Python27\lib\site-packages;

系統變數增加變數名稱為 QGIS_PREFIX_PATH
值為 C:\OSGeo4W64\apps\qgis-ltr

系統變數增加變數名稱為 QT_PLUGIN_PATH
值為 C:\OSGeo4W64\apps\qgis-ltr\qtplugins;C:\OSGeo4W64\apps\qt4\plugins

 系統變數增加變數名稱為 GDAL_CACHEMAX
值為 64

 系統變數增加變數名稱為 GDAL_DATA
值為 C:\OSGeo4W64\share\gdal

 系統變數增加變數名稱為 GDAL_DRIVER_PATH
值為 C:\OSGeo4W64\bin

 系統變數增加變數名稱為 PDAL_DRIVER_PATH
值為 C:\OSGeo4W64\bin
(這是啥?我也不知道不要問我…我根據 Apache  環境設定抄來的,因該是沒作用吧)

系統變數增加變數名稱為  PROJ_LIB
值為 C:\OSGeo4W64\share\proj

接下來測試看看 QGIS Server 那隻 FastCGI 程式是否可以正常運作
開啟命令提示字元來測試吧…
基本上 path 設定完,不管在那都可以執行才對…
我測試時是先切換路徑到 qgis server 安裝路徑下,
路徑為 C:\OSGeo4W64\apps\qgis-ltr\bin
如果這隻qgis_mapserv.fcgi.exe,是會正常吐出 xml tag 那就成功一半了

3.3 目錄權限設定
將整個 qgis 安裝的目錄都設定iisuser權限給它
路徑為 C:\OSGeo4W64
使用者包含:IUSR、IIS_IUSRS

3.4 設定


新增虛擬目錄(其實直接新增應用程式也可以才對)

設定別名:qgis(可以隨便定,差別在於服務的網址路徑不同)
實體路徑:C:\OSGeo4W64\apps\qgis-ltr\bin

轉換成應用程式(好啦…我也違反奧卡姆剃刀原則,我當初測試畫面就是這樣嘛)

在 IIS 最根的那層,也就是電腦名稱那層,去設定 ISAPI及CGI限制
原因是底下都會繼承阿,就懶阿

先把 Active Server Page(ASP),限制設定為不允許

新增 ISAPI 或 CGI 限制
ISAPI 或 CGI 路徑:C:\OSGeo4W64\apps\qgis-ltr\bin\qgis_mapserv.fcgi.exe
描述:QGISSERVER (其實有定義沒定義都沒差啦)

允許延伸路徑執行,要打勾

接下來設定 FastCGI

點選 【FastCGI 設定】

新增 FastCGI 應用程式
完整路徑:C:\OSGeo4W64\apps\qgis-ltr\bin\qgis_mapserv.fcgi.exe

設定【處理常式對應】
點選 【處理常式對應】


新增模組對應
要求路徑:qgis_mapserv.fcgi.exe
(iis 收到要求的路徑或檔案來執行下列定義程式運算 也可叫wms*)

模組:FastCgiModule

執行檔:C:\OSGeo4W64\apps\qgis-ltr\bin\qgis_mapserv.fcgi.exe

名稱:qgis_mapserv.fcgi.exe
(可自行定義 叫 wms,不過要給它一個叫wms的 fcgi 檔案,我是這麼幹的…)

2018-05-30 補充:
我額外設定了一組模組對應,要求路徑叫wms*,模組一樣設定為 FastCgiModule,
執行檔也設為 C:\OSGeo4W64\apps\qgis-ltr\bin\qgis_mapserv.fcgi.exe,
名稱則叫做 wms。
copy qgis_mapserv.fcgi.exe ,檔名叫 wms 。

這麼做是wms server網址,可以改成其他的:
http://192.168.15.62/qgis/wms?...


要求限制 > 對應(看上圖吧)

要求限制 > 指令動詞(看上圖吧)GET,HEAD,POST

要求限制 > 存取(看上圖吧)



接下來~測試是否成功…


見證奇蹟的時刻…看到wms 回應的 xml 囉

4. 建立 qgis 地圖專案
於qgis server 路徑下來建立專案檔
qgis server 所安裝路徑為 C:\OSGeo4W64\apps\qgis-ltr\bin

編輯地圖並儲存專案檔 .qgs
Save paths 設為絕對路徑 absolute (這樣只要把 專案檔與fcgi程式放一起即可)

 Project > Project Properties

圖資設定編好後,來發 wms 服務吧
點選【OWS Server】頁籤
(1) Service Capabilities 勾起來,內容就依實況設吧
(2) WMS Capabilities > Advertised extent 勾起來,Boundary 就讓它自己抓吧
把 Use Current Canbas Extent 按下去就行了
(3) CRS restrictions,可以手動加,懶的話就用 Used 按下去,坐標系統就會長出來了
(4) Exclude composers 勾起來
按下 確定 ,然後儲存專案吧

5. 測試
開一空白專案來測試一下發布成果吧

先建立一個 WMS 連結
Name:  local (隨便定的)
URL:http://192.168.15.62/qgis/qgis_mapserv.fcgi.exe?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities
(192.168.15.62 因為從另一台機器去測試;qgis是剛剛設的應用程式)

連接wms server
根據剛才設定wms 連結 來 Connect連接
按下Add 將圖層加入qgis ,來測試顯示結果


結果
成功,圖例就是 QGIS 設定的

再來一發,網頁上也接的到…
這樣一來…該是讓那些像水貨商的代理商、經銷商去呷賽啦~
很重要~所以說三次…

PS:
如果裝完發布沒反應…考慮重啟 IIS 服務吧…
在系統管理員身份的命令提示字元下…iisreset 吧…

【參考文獻】
(1) QGIS Server on Windows 10/Server 2012
(2) QGIS Server在IIS 7.0及以上中配置 (廢…勿入)
(2) QGIS Server 2.8 on Windows Server 2012


星期一, 11月 27, 2017

【Python】字典 (dictionary) 裡面再塞字典,值給 unicode ,字典再放入 list

口白:
流動的水沒有形狀,漂流的風找不到蹤跡,任何案件的 Coding 都取決於心
唯一看透真相的是,外表看似卜朧共,智慧卻低於常人的 名卜朧共 刻爛
(謎之音:把 Code 刻到爛簡稱刻爛.爛..爛...)
Music:
#表升半音 []表高八度
4 3 2 6 4 2 3 #6 6 5 4 5 4 5 6 4 3 2 5 4 3 4 2 6 4 5 [2] [1] #6 6 5 6
4 3 2 6 4 2 3 #6 6 5 4 5 4 5 6 4 3 2 4 3 2 4 2 6 4 5 [2] #6 6 5 6
口白:
刻爛:真実はいつも一つ!

環境:
Python 2.7

狀況:
字典 (dictionary),要產生一個字典小 d ,
內容是以數字當 key index,然後在每個 key 給予 另一個字典
第一個 key 的 value 給數字,第二個key 的 value 給字串
就像是 json 的 物件一樣
{0:{'a':10,'b':'b1'},1:{'a':30,'b':'b2'}}

要如何實做?問問谷哥吧…沒有谷哥罩…我就廢了…

定義 一個字典小 d
d={
 0:
 {
  u'類別':10,
  u'日期':'2017-11-21',
  u'GeometryType':u'Point',
  u'Geometry':['155979.548274', '2554388.51285'],
  u'備註':u'unicode 中文字'
 },
 1:
 {
  u'類別':30,
  u'日期':'2017-11-22',
  u'GeometryType':u'LineString',
  u'Geometry':[['170491.901228', '2541243.38286'], ['170511.894158', '2541243.2872']],
  u'備註':u'unicode english word'
 },
 2:
 {
  '類別':20,
  '日期':'2017-11-21',
  'GeometryType':'Point',
  'Geometry':['155989.548274', '2554388.51285'],
  '備註':'中文字'
 },
 3:
 {
  '類別':40,
  '日期':'2017-11-22',
  'GeometryType':'LineString',
  'Geometry':[['170491.901228', '2541343.38286'], ['170511.894158', '2541343.2872']],
  '備註':'english word'
 }
}

基本上 python 字典 (dictionary) ,看起來就是 json 阿…

>>> print d
{0: {u'Geometry': ['155979.548274', '2554388.51285'], u'\u65e5\u671f': '2017-11-21', u'GeometryType': u'Point', u'\u985e\u5225': 10, u'\u5099\u8a3b': u'unicode \u4e2d\u6587\u5b57'}, 1: {u'Geometry': [['170491.901228', '2541243.38286'], ['170511.894158', '2541243.2872']], u'\u65e5\u671f': '2017-11-22', u'GeometryType': u'LineString', u'\u985e\u5225': 30, u'\u5099\u8a3b': u'unicode english word'}, 2: {'Geometry': ['155989.548274', '2554388.51285'], 'GeometryType': 'Point', '\xe6\x97\xa5\xe6\x9c\x9f': '2017-11-21', '\xe9\xa1\x9e\xe5\x88\xa5': 20, '\xe5\x82\x99\xe8\xa8\xbb': '\xe4\xb8\xad\xe6\x96\x87\xe5\xad\x97'}, 3: {'Geometry': [['170491.901228', '2541343.38286'], ['170511.894158', '2541343.2872']], 'GeometryType': 'LineString', '\xe6\x97\xa5\xe6\x9c\x9f': '2017-11-22', '\xe9\xa1\x9e\xe5\x88\xa5': 40, '\xe5\x82\x99\xe8\xa8\xbb': 'english word'}}
>>> print d[0]
{u'Geometry': ['155979.548274', '2554388.51285'], u'\u65e5\u671f': '2017-11-21', u'GeometryType': u'Point', u'\u985e\u5225': 10, u'\u5099\u8a3b': u'unicode \u4e2d\u6587\u5b57'}
>>> print d[1]
{u'Geometry': [['170491.901228', '2541243.38286'], ['170511.894158', '2541243.2872']], u'\u65e5\u671f': '2017-11-22', u'GeometryType': u'LineString', u'\u985e\u5225': 30, u'\u5099\u8a3b': u'unicode english word'}
>>> print d[2]
{'Geometry': ['155989.548274', '2554388.51285'], 'GeometryType': 'Point', '\xe6\x97\xa5\xe6\x9c\x9f': '2017-11-21', '\xe9\xa1\x9e\xe5\x88\xa5': 20, '\xe5\x82\x99\xe8\xa8\xbb': '\xe4\xb8\xad\xe6\x96\x87\xe5\xad\x97'}
>>> print d[3]
{'Geometry': [['170491.901228', '2541343.38286'], ['170511.894158', '2541343.2872']], 'GeometryType': 'LineString', '\xe6\x97\xa5\xe6\x9c\x9f': '2017-11-22', '\xe9\xa1\x9e\xe5\x88\xa5': 40, '\xe5\x82\x99\xe8\xa8\xbb': 'english word'}

可以看出 key 一開始定義為 unicode 與 依系統預設編碼定義的差異…
看來定義還是一致比較好…這就是為什麼老秦要統一六國,
一國一種語言、方言、貨幣、度量方法…煩都煩死了…
所以大神谷哥阿…我由衷的請求您出一套幹掉各家程式語言的語法…以後我就跟您混…(GO 有機會嗎?)

話說回來…
但…那看不懂的文字要怎麼解決?

這讓我想起古老的人類歷史中,在那個沒有mpeg、巫毒卡的年代,
玩任天堂時,看著鋸齒狀的超級瑪莉…透過大腦內插運算的獲得圓潤化效果…(現在的人類到底是進化?還是退化了!)
或者是根據人腦智慧,看謎片時,自動解碼技術…(現在的人類到底是進化?還是退化了!)
我這兩種都不會阿…更何況是 unicode 編碼、解碼技術…

>>> print repr(d[0]).decode("unicode-escape")
{u'Geometry': ['155979.548274', '2554388.51285'], u'日期': '2017-11-21', u'GeometryType': u'Point', u'類別': 10, u'備註': u'unicode 中文字'}
>>> print repr(d[1]).decode("unicode-escape")
{u'Geometry': [['170491.901228', '2541243.38286'], ['170511.894158', '2541243.2872']], u'日期': '2017-11-22', u'GeometryType': u'LineString', u'類別': 30, u'備註': u'unicode english word'}
>>> print repr(d[2]).decode("unicode-escape")
{'Geometry': ['155989.548274', '2554388.51285'], 'GeometryType': 'Point', '日期': '2017-11-21', '類別': 20, '備註': '中文字'}
>>> print repr(d[3]).decode("unicode-escape")
{'Geometry': [['170491.901228', '2541343.38286'], ['170511.894158', '2541343.2872']], 'GeometryType': 'LineString', '日期': '2017-11-22', '類別': 40, '備註': 'english word'}

可以透過 repr() 定義編碼給它,這樣就可以在 console 中,
看到 字典 (dictionary) unicode 編碼的文字囉(這只是為了在 console 中看的懂而已)

那…要怎麼取 key 的 value 咧…

>>> print d[0][u'備註']
unicode 中文字
>>> print d[1][u'備註']
unicode english word
>>> print d[2]['備註']
中文字
>>> print d[3]['備註']
english word
>>> print d[0]['備註']
Traceback (most recent call last):
  File "", line 1, in 
KeyError: '\xe5\x82\x99\xe8\xa8\xbb'

直接給 key 就可以取得值
不過…當初如果 key 給的是 unicode 就只能用 unicode 的 key(英數則不影響)
不然就會壞掉惹…

另外,不論 key 所存放的 value 是 字典(dictionary)、list、tuple、文字、數字…
取值得方式通通都一樣,直接給 key 就可以取得值
差別在於 list、tuple 取值時,還可以在給予 index 值

所以,跟台式路邊攤大腸包小腸的概念一樣…
大腸灌糯米,再包小腸,小腸又灌豬肉…
這讓我想到,洛哥去面試考警察時,主考官問他為什麼來當差…
洛哥說:為了吃飯…
貪了五億就是為了吃飯阿…我也想…

>>> print d[0]['Geometry']
['155979.548274', '2554388.51285']
>>> print d[0][u'Geometry']
['155979.548274', '2554388.51285']
>>> print d[0]['Geometry'][0]
155979.548274
>>> print d[0]['Geometry'][1]
2554388.51285


上面例子 print d[0]['Geometry']
就是列出 d 字典中 key 為 0 的字典中, key 為 Geometry 的 list

上面例子 print d[0]['Geometry'][0]
就是列出 d 字典中 key 為 0 的字典中, key 為 Geometry 的 list 中,index 為 0 的 值
上面例子 print d[0]['Geometry'][1]
就是列出 d 字典中 key 為 1 的字典中, key 為 Geometry 的 list 中,index 為 1 的 值

編碼設定方式: 設定編碼方式如下
>>> import sys
>>> print 'defaultencoding:', sys.getdefaultencoding()
defaultencoding: ascii
>>> reload(sys)

>>> sys.setdefaultencoding('utf-8')
>>> print 'defaultencoding:', sys.getdefaultencoding()
defaultencoding: utf-8


就算定義了編碼…在 console 中我還是無法用 print 列出字典 (dictionary) 中的中文字…
還是要透過 repr() 來轉

參考文獻:
1. In Python can we add a dictionary inside a dictionary? If yes how can we access the inner dictionary using the key in the primary dictionary?
2.stackoverflow.com:print python dictionary with utf8 values
3.Pythonの日本語処理


星期二, 8月 15, 2017

【大冒險】月入是要多少…才繳的起這樣的電話費

時間:2017-08-14

事件描述:
收到中華電信106年8月電信費用通知單 email
看看帳單吧~

啥尛? 3G 手機網無限瀏覽通信費…12萬5…
不是無限嗎?
這是要月薪賺多少才繳的起阿…

腦中 BI(悲哀) 系統,跳出選項:
1. 去那借?
2. 跑路吧…
3. 看來只能去當牛郎了…(能賣藝不賣身嗎?)

到底這個月是幹了什麼好事?恩﹍
名偵探卜朧共陷入沉思﹍
就是用手機當基地台,然後接了尿袋,
用小米盒子,靠意志力用爆肝模式看了幾十個小時的花千骨﹍
真是一將功成萬骨枯﹍

可是我走得不是後門嗎?怎麼可能那麼高?
再看看清楚帳單﹍先把帳單做了馬賽克處理,電話號碼就留末三碼
還好沒有設定錯誤,的確走得是後門
這樣分析看來,哇塞,這個月我賺了中華電信12萬耶!
這樣看來,我也是月入幾十萬耶,但是為什麼還是買不起阿母給(AMG)、MPower、Polestar

3G看影片會lag嗎?完全不會,因為幾乎全部人通通轉去4G了
這是什麼概念﹍就是全部車通通開上高速公路,然後我獨走省道的概念
所以 3G 頻寬、基地台完善,看HD片一樣順阿
所以阿﹍決定堅守3G 中華 mcool 到它毀滅的那天