Python 進階範例集:網際網路篇


http.server

Python 自帶 HTTP 通訊協定的網站伺服器能力,只要切換到想當網站的資料夾,執行1

python -m http.server --bind 0.0.0.0 80

該資料夾就會掛載成網站伺服器,可在網頁瀏覽器輸入 127.0.0.1 或 192.168.x.x 之類的區域位址,以 HTTP 存取資料夾裡面的網頁和檔案。

若想指定資料夾為網站伺服器,可用 --directory 參數,隨後輸入完整路徑的資料夾名稱。

想寫 CGI 的話,可添加 --cgi 參數,並把 Python 原始碼放在 cgi-binhtbin 資料夾裡面即可。

通常會將上述指令寫在批次檔,然後放在想當網站的資料夾裡面,直接雙擊滑鼠執行即可,比較方便。

要結束伺服系統,關閉該 python 處理程序即可。

有時候會發生啟動了 http.server,網頁卻連很久還連不進去的情況,請關閉 python 處理程序,重新啟動一次看看。


範例

假設我臨時想在 Windows 10 架個能執行 CGI 的網頁伺服器,為了方便還把網頁放在桌面。

[USER]\Desktop\index.html

[USER]\Desktop\cgi-bin\hello.py

命令提示字元

Microsoft Windows [版本 10.0.17763.914]
(c) 2018 Microsoft Corporation. 著作權所有,並保留一切權利。

C:\Users\User>CD Desktop

C:\Users\User\Desktop>python -m http.server --bind 0.0.0.0 80 --cgi
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

網頁瀏覽器

msedge('http://127.0.0.1/','_Say hello')
index.html
msedge('http://127.0.0.1/cgi-bin/hello.py','Hello, CGI!')
hello.py

cgitb

載入 cgitb 模組,執行 cgitb.enable() 的話,會追蹤程式錯誤訊息,在發生錯誤時以網頁顯示追蹤結果,方便開發人員除錯。

不想直接顯示錯誤訊息,可以改為 cgitb.enable(display=0, logdir='../logs'),將錯誤訊息保存在伺服器的 logs 資料夾中。


cgi

cgi 模組提供剖析連線狀態和網頁內容的功能,方便 Python 程式設計師開發 CGI 程式。


接收 GET 或 POST 資料

form.html

cgi-bin/request.py


urllib.urlparse, urllib.urlunparse

設計 CGI 時,有些資訊就在網址裡,能快速有效的剖析出資料會很有幫助。

反過來,如何將資料組成網址,將資訊傳出去,也是很有用的技巧。


urllib.urlparse


ParseResult(scheme='http', netloc='serv.loc', path='/chap/sect.html', params='', query='p=123', fragment='article')
p=123


urllib.urlunparse


scheme://netloc/path;params?query#fragment


http.cookies

cookie 是在 HTTP 的 header fields 傳輸,所以儲存資料要寫在 header fields 的部分,再透過 os 取得環境變數中的 HTTP_COOKIE,然後寫在 message body:


重新整理網頁,會顯示 email=twideem@outlook.com; user=Twideem Civs,對它進行剖析就能獲取資料。

不過上述工作可用 http.cookies 模組代勞,降低複雜度。


儲存 cookie


讀取 cookie


codecs

在預設使用 ASCII 編碼系統的 Windows,Python 3 傳輸資料會用 Big5 字元編碼,所以在設定為 UTF-8 字元編碼的網頁會顯示亂碼。

寫上 #-*- coding: UTF-8 -*-print('Content-Type: text/html; charset=utf-8') 是沒用的,因為並不是網頁沒使用 UTF-8 編碼,正是網頁使用 UTF-8 字元編碼,去顯示 Big5 字元編碼,所以才亂碼。問題出在程式未以 UTF-8 傳送資料,不是網頁的問題。

在網路上找到的解決方式是:


寫在另一個 *.py 檔,每次寫 CGI 再 import 就好。反正寫 CGI 一定會自己把功能重新打包成函式庫,放在裡面就好,並不麻煩。


smtplib, smtpd

smtplib 可以在客戶端寄發電子郵件,不過必須透過電子郵件服務供應商、或者電腦架為 SMTP 伺服器,否則程式跑起來正常,實際上電腦並未能把資料送出去。

smtpd 套件可以架設 SMTP 伺服器,其中模組 SMPTServer 需要實作 process_message() 才能動作,而模組 DebuggingServer 已實作好可直接調用,但不會寄發郵件,純粹測試客戶端的動作用。


透過服務供應商寄發電子郵件

根據服務供應商對資料傳輸安全的規定,各有不同做法,但大致上有 SMTP、TLS、SSL 三種。

底下示範的是 Gmail,必須在「具有帳戶存取權的應用程式」開啟「允許安全性較低的應用程式」,才能透過 Python 用 Gmail 寄發電子郵件。

SMTP

TLS

SSL


從本機端寄發電子郵件

如果你的作業系統已裝載電子郵件伺服器,可以更簡單寄發出去。沒有的話,Python 內建的 DebuggingServer,是一個測試用電子郵件伺服器,雖然沒辦法把郵件寄發出去,但能單機模擬郵件收發的動作。

server.py

client.py

output

---------- MESSAGE FOLLOWS ----------
mail options: ['SIZE=157']
b'Content-Type: text/plain; charset="us-ascii"'
b'MIME-Version: 1.0'
b'Content-Transfer-Encoding: 7bit'
b'Subject: To Twideem Civs'
b'To: twideem@outlook.com'
b'X-Peer: 127.0.0.1'
b''
b'Hello!'
------------ END MESSAGE ------------


webbrowser


msedge('http://www.python.org','../../images/overcast/19691205A.png')


urllib.request


直接透過網址取得網頁內容

Python 程式可以直接透過網址請求資料,讓你不用透過網頁瀏覽器,也能取得網頁內容。

http://127.0.0.1/homepage.html

sample1.py


[('Server', 'SimpleHTTP/0.6 Python/3.6.5'), ('Date', 'Tue, 28 Mar 2018 12:34:56 GMT'), ('Content-type', 'text/html'), ('Content-Length', '164'), ('Last-Modified', 'Tue, 28 Mar 2018 12:34:56 GMT')]

b"<html>\n  <head>\n    <title>HOME PAGE</title>\n  </head>\n  <body>\n    <p>WELCOME</p>\n  </body>\n</html>"

200

sample2.py


text/html

<html>
  <head>
    <title>HOME PAGE</title>
  </head>
  <body>
    <p>WELCOM</p>
  </body>
</html>


向 Web Service 送出 SOAP 請求

urllib.request 甚至可以送出 SOAP 向 Web Service 請求服務:


得到的資料當然也是 SOAP,也就是一份 XML,可以自己再用 ElementTree 剖析出資料,在沒能安裝第三方模組時應急一下。

再看一個例子,這次向 http://fhy.wra.gov.tw 線上請求調出「氣象局雨量站基本資料」,然後剖析出所有雨量站的縣市:


臺中市和平區 南投縣水里鄉 南投縣集集鎮 南投縣仁愛鄉 雲林縣北港鎮 高雄市旗山區 屏東縣屏東市 臺東縣鹿野鄉 新北市石碇區 新北市林口區 新北市坪林區 (……省略)


xmlrpc.server, xmlrpc.client

使用 XML 資料格式以及 HTTP 傳輸資料的遠端程式呼叫。


server.py


client.py


579