環境是 python 2.7 下:
import urllib
#測試初始 unicode 字串物件
strUnicode = u"test data"
#字串型態為 UNICODE
type(strUnicode)
<type 'unicode'>
#開始 url encode,先將 unicode 編碼為 utf-8,再 url encode (quote),得到 utf-8 字串物件
strResult = urllib.quote(strUnicode.encode("utf-8"))
type(srtResult)
<type 'str'>
#開始 url decode,將上面的結果進行 url decode (unquote),再解碼回 unicode 字串物件
strResult = urllib.unquote(urllib.quote(u_str.encode("utf-8"))).decode("utf-8")
type(srtResult)
<type 'unicode'>
2016年7月10日 星期日
2016年7月9日 星期六
ubuntu 下改 mysql 編碼
查詢目前資料庫編碼
mysql> status;
...
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
設定並重啟
$ sudo vi /etc/mysql/conf.d/charset.cnf
[client]
default-character-set=utf8
[mysqld]
character-set-server=utf8
collation-server=utf8_unicode_ci
$ sudo service mysql restart
再查詢一次
mysql> status;
...
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
mysql> status;
...
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
2016年7月8日 星期五
deploy django + mysql + ubuntu + apache
sudo apt-get update
sudo apt-get upgrade
安裝 apache
sudo apt-get install apache2
安裝 Django less than 1.9
sudo apt-get install python3-pip
sudo apt-get install python3-pip
sudo python3 -m pip install "Django<1.9"
安裝 apache 模組 - wsgi
sudo apt-get install libapache2-mod-wsgi-py3
安裝 apache 模組 - wsgi
sudo apt-get install libapache2-mod-wsgi-py3
安裝 mysql 過程會設定 mysql root 密碼
sudo apt-get install mysql-server libapache2-mod-auth-mysql安裝 mysql 官方 python-connector
到 mysql 下載 mysql-connector-python-py3_2.1.3-1ubuntu14.04_all.deb
sudo dpkg -i mysql-connector-python-py3_2.1.3-1ubuntu14.04_all.deb
測試登入 mysql
FLUSH PRIVILEGES;
以上為 mysql shell 內使用的命令
新增 django 專案
django-admin startproject my_proj
同步 django ORM model 到 mysql TABLE
cd my_proj
python3 manage.py makemigrations
python3 manage.py migrate
/etc/apache2/sites-available 下新增 my_proj.conf
<VirtualHost *:80>
WSGIScriptAlias / /home/ubuntu/git_code/my_proj/my_proj/wsgi.py
<Directory /home/ubuntu/git_code/my_proj/my_proj>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
Alias /static /home/ubuntu/git_code/my_proj/static
<Directory /home/ubuntu/git_code/my_proj/static>
Require all granted
</Directory>
WSGIDaemonProcess my_proj python-path=/home/ubuntu/git_code/my_proj:/usr/local/lib/python3.4/dist-packages
WSGIProcessGroup my_proj
</VirtualHost>
套用 site 設定
sudo a2ensite my_proj.conf
sudo service apache2 reload
重啟 apache
sudo service apache2 restart
測試登入 mysql
mysql -u root -p
mysql 設定檔 /etc/mysql/conf.d
修改資料庫編碼 文章連結
新增資料庫
mysql>create datebase db_name;
顯示所有資料庫
mysql>show datebases;
mysql 新增使用者與設定權限
以下為 mysql shell 內使用的命令
use mysql;
INSERT INTO user(host,user,password) VALUES('localhost','user_name',password('user_pwd'));
FLUSH PRIVILEGES;
GRANT ALL ON db_name.* TO 'user_name'@localhost IDENTIFIED BY 'user_pwd';FLUSH PRIVILEGES;
以上為 mysql shell 內使用的命令
新增 django 專案
django-admin startproject my_proj
同步 django ORM model 到 mysql TABLE
cd my_proj
python3 manage.py makemigrations
python3 manage.py migrate
/etc/apache2/sites-available 下新增 my_proj.conf
<VirtualHost *:80>
WSGIScriptAlias / /home/ubuntu/git_code/my_proj/my_proj/wsgi.py
<Directory /home/ubuntu/git_code/my_proj/my_proj>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
Alias /static /home/ubuntu/git_code/my_proj/static
<Directory /home/ubuntu/git_code/my_proj/static>
Require all granted
</Directory>
WSGIDaemonProcess my_proj python-path=/home/ubuntu/git_code/my_proj:/usr/local/lib/python3.4/dist-packages
WSGIProcessGroup my_proj
</VirtualHost>
套用 site 設定
sudo a2ensite my_proj.conf
sudo service apache2 reload
重啟 apache
sudo service apache2 restart
amazon web services 修改主機名稱
在 AWS 申請主機登入後,
bash 的提示符號很醜,ex:
ubuntu@ip-123-456-789-012:~
只要修改 hostname 就可以改為較順眼的顯示方式
sudo hostname bennu.com
重新登入後就變成
ubuntu@bennu.com:~
而如果需要更客製化的提示符
就要去修改 ~/.bashrc 的 PS1 變數了
bash 的提示符號很醜,ex:
ubuntu@ip-123-456-789-012:~
只要修改 hostname 就可以改為較順眼的顯示方式
sudo hostname bennu.com
重新登入後就變成
ubuntu@bennu.com:~
而如果需要更客製化的提示符
就要去修改 ~/.bashrc 的 PS1 變數了
2016年6月4日 星期六
用戶密碼加解密概念-client版
client........................network..................................server
step1
................................................................................create
input rawpwd
salt(fixed) + rawpwd ==sha256==> encode1
salt_encode1... .....................https.........................save salt_encode1 to database
step2
.............................................................................. validate
input rawpwd
salt + rawpwd ==sha256==> encode2
salt_encode2... .... .....................https....................load salt_encode1 from database
...............................................................................test if encode2 equals to encode1
step1
................................................................................create
input rawpwd
salt(fixed) + rawpwd ==sha256==> encode1
salt_encode1... .....................https.........................save salt_encode1 to database
step2
.............................................................................. validate
input rawpwd
salt + rawpwd ==sha256==> encode2
salt_encode2... .... .....................https....................load salt_encode1 from database
...............................................................................test if encode2 equals to encode1
用戶密碼加解密概念-server版
client..........network............................server
step1
.........................................................create
rawpwd.................https...................salt(random) + rawpwd ==sha256==> encode1
.........................................................save salt_encode1 to database
step2
.........................................................validate
rawpwd.................https.. ................load salt from salt_encode1 in database
.........................................................salt + rawpwd ==sha256==> encode2
.........................................................test if encode2 equals to encode1
step1
.........................................................create
rawpwd.................https...................salt(random) + rawpwd ==sha256==> encode1
.........................................................save salt_encode1 to database
step2
.........................................................validate
rawpwd.................https.. ................load salt from salt_encode1 in database
.........................................................salt + rawpwd ==sha256==> encode2
.........................................................test if encode2 equals to encode1
2016年5月23日 星期一
[Django] 設定 Django 使用 MySQL 做為資料庫
首先是版本
MySQL 我使用目前最新 社群版(免費版) 5.6.28
安裝時 附帶一起安裝 mysql-connector-python 2.1.3 模組
這是MySQL官方自己出的 connector 但與 Django 最新版 (1.9.x) 不完全相容
因此,我們必須捨棄最新版本的 Django,pip 安裝時加上:
python3 -m pip install "Django<1.9"
這樣就可以安裝 1.8.x 的最新版本 ,需注意後面的 "Django<1.9" 雙引號不可省略,
完成安裝後,在 Django 的 project 目錄下的 setting.py,資料庫設定的部分:
完成後,執行 Django migrate 命令:
python3 manage.py migrate
若成功就會把 Django 的資料庫移轉到 MySQL 下了。
MySQL 我使用目前最新 社群版(免費版) 5.6.28
安裝時 附帶一起安裝 mysql-connector-python 2.1.3 模組
這是MySQL官方自己出的 connector 但與 Django 最新版 (1.9.x) 不完全相容
因此,我們必須捨棄最新版本的 Django,pip 安裝時加上:
python3 -m pip install "Django<1.9"
這樣就可以安裝 1.8.x 的最新版本 ,需注意後面的 "Django<1.9" 雙引號不可省略,
完成安裝後,在 Django 的 project 目錄下的 setting.py,資料庫設定的部分:
DATABASES = {ENGINE 的部分是設定使用 MySQL 官方的 connector
'default': {
'ENGINE': 'mysql.connector.django',
'NAME': 'datebase_name',
'USER': 'datebase_user_name',
'PASSWORD': 'datebase_user_password',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'autocommit': True,
},
}
}
完成後,執行 Django migrate 命令:
python3 manage.py migrate
若成功就會把 Django 的資料庫移轉到 MySQL 下了。
[python] regex 群組命名表示法
原本我只會
結果為 "123"
學了一下 Django 意外學到
為群組命名,程式碼可以更容易懂,還不錯。
text = "123 is num"
re.match("^(\d+) is num$", text).group(1)
結果為 "123"
學了一下 Django 意外學到
text = "123 is num"可以透過 ?P<variable_name>
re.match("^(?P<num>\d+) is num$", text).group("num")
2016年5月18日 星期三
[python] OAuth 取得 facebook 使用者的 id name email
1. 到 facebook developers頁面 建立一個 WWW APP ,可以得到一組 client id / client secret
href="https://www.facebook.com/dialog/oauth?
下方填入自己的 WebService 網址。ex:
2.在系統的登入頁加入一個超連結,填入 上一步的 client id ,要向使用者索取的資源 scope, 以及使用者同意授權後,facebook 要將授權碼 redirect 的位址,我們填入自己的 WebService 位址。
href="https://www.facebook.com/dialog/oauth?
&client_id=1730077280596052
&scope=public_profile,email
&redirect_uri=http://bennu-aws.ddns.net:5000/fb_oauth"
3. 設計一個 WebService 接收 授權碼 code,使用 python Flask 框架。
@app.route("/fb_oauth", methods=["GET"])
def fbOauth():
#接收授權碼
strAuthCode = request.args.get("code", None, type=str)
4.將授權碼回傳給 facebook 換取 token,需要 client_id、client_secret、第3步得到的授權碼、以及第2步使用的 redircet_uri,facebook 就會回傳 token 回來
strAccessTokenUrlTemplate = "https://graph.facebook.com/oauth/access_token?
&client_id=%s
&redirect_uri=%s
&client_secret=%s
&code=%s"
strAccessTokenUrl = strAccessTokenUrlTemplate%
(strFbClientId,
"http://bennu-aws.ddns.net:5000/fb_oauth",
strFbClientSecret,
strAuthCode)
responseToken = urllib.request.urlopen(strAccessTokenUrl)
strToken = responseToken.read().decode(responseToken.headers.get_content_charset())
5.使用 token 取得使用者的資料
responseUserData = urllib.request.urlopen("https://graph.facebook.com/me?
&fields=id,name,email
&" + strToken)
strUserData = responseUserData.read().decode(responseToken.headers.get_content_charset())
dicUserData = json.loads(strUserData)
return (dicUserData["id"], dicUserData["name"], dicUserData["email"])
3. 設計一個 WebService 接收 授權碼 code,使用 python Flask 框架。
@app.route("/fb_oauth", methods=["GET"])
def fbOauth():
#接收授權碼
strAuthCode = request.args.get("code", None, type=str)
4.將授權碼回傳給 facebook 換取 token,需要 client_id、client_secret、第3步得到的授權碼、以及第2步使用的 redircet_uri,facebook 就會回傳 token 回來
strAccessTokenUrlTemplate = "https://graph.facebook.com/oauth/access_token?
&client_id=%s
&redirect_uri=%s
&client_secret=%s
&code=%s"
strAccessTokenUrl = strAccessTokenUrlTemplate%
(strFbClientId,
"http://bennu-aws.ddns.net:5000/fb_oauth",
strFbClientSecret,
strAuthCode)
responseToken = urllib.request.urlopen(strAccessTokenUrl)
strToken = responseToken.read().decode(responseToken.headers.get_content_charset())
5.使用 token 取得使用者的資料
responseUserData = urllib.request.urlopen("https://graph.facebook.com/me?
&fields=id,name,email
&" + strToken)
strUserData = responseUserData.read().decode(responseToken.headers.get_content_charset())
dicUserData = json.loads(strUserData)
return (dicUserData["id"], dicUserData["name"], dicUserData["email"])
2016年5月15日 星期日
[python] unicode decode encode 的秘密
python 2.7
u"abc中文" == unicode 物件
"abc中文" == str 物件
python 3.x
u"abc中文" == unicode 物件
"abc中文" == unicode 物件
所以大多數問題出現在 python 2.7
以下使用 2.7 的觀點來看:
encode == 把 unicode 物件轉為 str 物件
strUTF8 = u"abc中文".encode("utf-8") == str 物件
strBIG5 = u"abc中文".encode("big5") == str 物件
strCP950 = u"abc中文".encode("cp950") == str 物件
decode == 把 str 物件轉為 unicode 物件
strUTF8 .decode("utf-8") == unicode 物件
strBIG5.decode("big5") == unicode 物件
strCP950.decode("cp950") == unicode 物件
秘密:
如果 str 物件 執行 encode 相當於 "先 decode 為 unicode 再 encode", ex:
u"abc中文" == unicode 物件
"abc中文" == str 物件
python 3.x
u"abc中文" == unicode 物件
"abc中文" == unicode 物件
所以大多數問題出現在 python 2.7
以下使用 2.7 的觀點來看:
encode == 把 unicode 物件轉為 str 物件
strUTF8 = u"abc中文".encode("utf-8") == str 物件
strBIG5 = u"abc中文".encode("big5") == str 物件
strCP950 = u"abc中文".encode("cp950") == str 物件
decode == 把 str 物件轉為 unicode 物件
strUTF8 .decode("utf-8") == unicode 物件
strBIG5.decode("big5") == unicode 物件
strCP950.decode("cp950") == unicode 物件
秘密:
如果 str 物件 執行 encode 相當於 "先 decode 為 unicode 再 encode", ex:
strBIG5.encode("cp950") == strBIG5.decode("ascii").encode("cp950")
重點在於 decode 過程會使用 python 的預設系統編碼 ascii 而不是使用 big5
造成 明明是呼叫 encode 卻報錯 "無法使用 ascii 進行 decode " 之類的奇怪結果
[python] 使用 pkg_resources 模組存取 package 裡面的檔案
import pkg_resources
strPkgFilePath = pkg_resources.resource_filename("package_name", "resource_file")
當資源存放在 package (含有 __init__.py 的資料夾)裡面時,
一但經過封裝上傳 pip install 之後,檔案路徑會與 os.path 取得的路徑不同,
os.path 是根據 "當前執行的目錄 (cwd)" 去做尋找,也就是說:
在 c:\ 下執行 會尋找 c:\package_name\resource_file
在 c:\dir\ 下執行會尋找 c:\dir\package_name\resource_file
不可能因為執行的 cwd 不同而到處搬移 resource_file
於是會將 resource_file 存放在 package 下,pip install 後
resourc_file 會固定放在 C:\Python34\Lib\site-packages\package_name\resource_file
而要取得該位置,只要使用 pkg_resources.resource_filename 即可。
2016年5月14日 星期六
python 設定 setup.py 及 MANIFEST.in 封裝整個專案 並上傳至 pypi 的設定
setup.py
from setuptools import setup,find_packages
with open("README.txt") as file:
long_description = file.read()
setup(
name = "bennu",
version = "0.3.2.dev2",
keywords = ["bennu", "utility", "muchu"],
description = "muchu's utility module",
author = "MuChu Hsu",
author_email = "muchu1983@gmail.com",
license = "BSD 3-Clause License",
url="https://github.com/muchu1983/bennu",
long_description=long_description,
packages = find_packages(),
include_package_data = True,
install_requires = ["Pillow>=3.0.0"],
platforms = "python 3.3",
entry_points = {"console_scripts":["bennu=bennu.launcher:entry_point"]},
classifiers = [
"Programming Language :: Python :: 3.3",
],
)
重點:
name 之後使用 pip install 要用到的名稱
version 每次上傳不得重覆,否則上傳會失敗,數字越大版本越新。
find_packages() 可以自動找出含有 __init__.py 的資料夾,省去一一指定。
install_requires 指定本專案相依的其他 pypi 專案,用 pip 安裝時也會被加入安裝。
entry_points 指定 專案的執行進入點 並建立 可執行檔 ["execuatable_name=package.package:function"]
MANIFEST.in
include LICENSE
recursive-include bennu_res *
recursive-exclude test *
搭配 MANIFEST.in 可以指定其他檔案是否要一起加入封裝
上傳
1. 登入,首次會問你 pypi 上的帳密,之後可以記錄
python setup.py register
2. 包裝,將你的專案包裝成 zip (windows) 或 tar.gz (linux)
python setup.py sdist
3. 上傳至 pypi
python setup.py upload
成功的話,要先移除專案資料夾內生成的 dist/ 還有 .egg-info/
否則 pip 會以為你已經有最新版本了,若是其他電腦就沒差
之後就可以用
pip install name
來安裝專案
安裝後也可以直接執行 executable_name 來執行
ubuntu 下使用 headless browser PhantomJS
PhantomJS 是一個 無畫面 的 browser
非常適合用來與 selenium 配合進行 自動化測試或是爬蟲程式
例如:
#取得 selenium driver 物件
def getDriver(self):
driver = None
if os.name == "nt":
#chromeDriverExeFilePath = os.sep.join(("bennu_res", "chromedriver.exe"))
#driver = webdriver.Chrome(chromeDriverExeFilePath)
phantomjsDriverExeFilePath = os.sep.join(("bennu_res", "phantomjs.exe"))
driver = webdriver.PhantomJS(phantomjsDriverExeFilePath)
if os.name == "posix":
phantomjsDriverExeFilePath = os.sep.join(("bennu_res", "phantomjs"))
driver = webdriver.PhantomJS(phantomjsDriverExeFilePath)
return driver
selenium 用法 本篇暫不介紹
PhantomJS 下載之後只有一個執行檔,將他放在 selenium 可以讀取到的位置即可使用
在 ubuntu 環境下,有幾點要注意的是:
1. 必須 chmod 755 phantomjs 加入執行權限
2. 必須安裝 apt-get install fontconfig 套件
非常適合用來與 selenium 配合進行 自動化測試或是爬蟲程式
例如:
#取得 selenium driver 物件
def getDriver(self):
driver = None
if os.name == "nt":
#chromeDriverExeFilePath = os.sep.join(("bennu_res", "chromedriver.exe"))
#driver = webdriver.Chrome(chromeDriverExeFilePath)
phantomjsDriverExeFilePath = os.sep.join(("bennu_res", "phantomjs.exe"))
driver = webdriver.PhantomJS(phantomjsDriverExeFilePath)
if os.name == "posix":
phantomjsDriverExeFilePath = os.sep.join(("bennu_res", "phantomjs"))
driver = webdriver.PhantomJS(phantomjsDriverExeFilePath)
return driver
selenium 用法 本篇暫不介紹
PhantomJS 下載之後只有一個執行檔,將他放在 selenium 可以讀取到的位置即可使用
在 ubuntu 環境下,有幾點要注意的是:
1. 必須 chmod 755 phantomjs 加入執行權限
2. 必須安裝 apt-get install fontconfig 套件
2016年5月11日 星期三
windows 下安裝 python scrapy 模組
目前 scrapy 僅支援 2.7 版本 python
安裝前準備:
0. 升級 pip
python2 -m pip install pip --upgrade
1. Visual C++ compiler for python 2.7
https://www.microsoft.com/en-us/download/details.aspx?id=44266
2. lxml 用 exe 安裝 (用 pip 直接裝有點問題)
https://pypi.python.org/pypi/lxml/3.6.0
3. pypiwin32 (用 pip 直接裝就可以了)
python2 -m pip install pypiwin32
準備完成:
python2 -m pip install scrapy
安裝前準備:
0. 升級 pip
python2 -m pip install pip --upgrade
1. Visual C++ compiler for python 2.7
https://www.microsoft.com/en-us/download/details.aspx?id=44266
2. lxml 用 exe 安裝 (用 pip 直接裝有點問題)
https://pypi.python.org/pypi/lxml/3.6.0
3. pypiwin32 (用 pip 直接裝就可以了)
python2 -m pip install pypiwin32
準備完成:
python2 -m pip install scrapy
python 使用 global 時機
當 local 區域 要 assign 資料給 外部區域 的變數時,
就必須先在 local 區域 使用 global 宣告一個相同名稱的 區域變數:
g = 1
def func():
g = 1
def func():
就必須先在 local 區域 使用 global 宣告一個相同名稱的 區域變數:
g = 1
def func():
global g
g = 2若是單純取值,沒有 assign 的動作,則可以不宣告:
g = 1
def func():
print(g)完
ssh key 備忘
ssh key 分為 公錀 與 私錀,成雙成對。
擁有私錀可以產生對應的公錀,但擁有公錀無法反推產生私錀。
公錀放在 server
私錀放在 client
linux 上 ssh-keygen 產生的 公錀 檔名為 id_rsa.pub
linux 上 ssh-keygen 產生的 私錀 檔名為 id_rsa
windows server 不支援 ssh 認証,故 公錀 一般只有 linux 格式
windows 由 puttygen 可將 id_rsa 轉為可在 windows 下 putty 使用的 .ppk 檔
也就是說 .ppk 檔 等於 windows 下使用的 私錀,與原本的 id_rsa 格式有些不同,
但功能相同,若要將 .ppk 檔 轉回 linux 下使用的 id_rsa
sudo apt-get install putty-tools
puttygen key.ppk -O private-openssh -o id_rsa
linux 公錀存放位置 ~/.ssh/authorized_keys (可同時放多組公錀)
linux 私錀存放位置 ~/.ssh/id_rsa
存取權限必須設定為
chmod 700 ~/.ssh
chmod 777 ~/.ssh/authorized_keys (可公開)
chmod 600 ~/.ssh/id_rsa (不可公開)
原因是....文章一開頭有說了:擁有.....吧拉吧拉吧拉。
擁有私錀可以產生對應的公錀,但擁有公錀無法反推產生私錀。
公錀放在 server
私錀放在 client
linux 上 ssh-keygen 產生的 公錀 檔名為 id_rsa.pub
linux 上 ssh-keygen 產生的 私錀 檔名為 id_rsa
windows server 不支援 ssh 認証,故 公錀 一般只有 linux 格式
windows 由 puttygen 可將 id_rsa 轉為可在 windows 下 putty 使用的 .ppk 檔
也就是說 .ppk 檔 等於 windows 下使用的 私錀,與原本的 id_rsa 格式有些不同,
但功能相同,若要將 .ppk 檔 轉回 linux 下使用的 id_rsa
sudo apt-get install putty-tools
puttygen key.ppk -O private-openssh -o id_rsa
linux 公錀存放位置 ~/.ssh/authorized_keys (可同時放多組公錀)
linux 私錀存放位置 ~/.ssh/id_rsa
存取權限必須設定為
chmod 700 ~/.ssh
chmod 777 ~/.ssh/authorized_keys (可公開)
chmod 600 ~/.ssh/id_rsa (不可公開)
原因是....文章一開頭有說了:擁有.....吧拉吧拉吧拉。
訂閱:
文章 (Atom)


