在現代軟體開發中,網路介面整合和資料處理扮演著至關重要的角色。本文將會詳細介紹如何使用 Python 與各種網路介面和資料格式進行互動,包含使用 Requests 函式庫簡化 HTTP 請求、操作 RESTful API、解析 JSON 和 XML 資料,以及使用 lxml 進行網頁資料擷取。此外,文章也涵蓋了資料序列化和壓縮技術,例如使用 pickle 進行 Python 物件序列化、XDR 跨語言資料交換,以及 gzip 壓縮技術。最後,我們將探討 Python 標準函式庫中的高效能網路工具,例如 asyncio,並簡要介紹其在分散式系統中的應用。這些技術的整合運用,能有效提升開發效率,並滿足現代網路應用程式對資料處理和通訊的需求。

網路介面與軟體介面整合

本章節將介紹如何使用Python存取目前廣泛用於組織間資料分享的API,並重點介紹多數Python驅動的組織內部基礎設施中用於支援通訊的工具。我們已經在前面的章節中討論了Python對跨行程的管道和佇列的支援,而電腦之間的通訊則需要雙方遵循一套定義好的協定——網際網路遵循的是TCP/IP協定套件。

網路層與應用層協定

TCP/IP協定套件包含四個概念層:鏈結層、網際網路層、傳輸層和應用層。鏈結層負責電腦與網際網路之間的資訊傳輸;網際網路層(例如IPv4、IPv6)控制資料包從源到目的地的傳遞;傳輸層(例如TCP、UDP)定義了兩個端點之間的通訊方式;而應用層(例如FTP、HTTP)則規定了資料的格式以供特定應用程式使用。

Python的標準函式庫提供了實作最常見協定的模組,包括ftplibpoplibimaplibnntplibsmtplibtelnetlibxmlrpc等,用於實作各種應用層協定。

網頁客戶端與HTTP請求

超文字傳輸協定(HTTP)是分散式、協作式超媒體資訊系統的應用層協定,也是全球資訊網資料通訊的基礎。本文重點介紹如何使用Requests函式庫從網頁上取得資料。

Python的標準urllib模組提供了大部分所需的HTTP功能,但使用起來相對底層,需要進行大量工作才能完成看似簡單的任務,例如從需要驗證的HTTPS伺服器取得資料。Requests函式庫簡化了Python中的HTTP請求,使得與網路服務的整合變得無縫。

安裝Requests函式庫

可以使用pip安裝Requests:

$ pip install requests

網路API與RESTful API

現在幾乎每個人,從美國人口普查局到荷蘭國家圖書館,都提供了API供使用者存取他們想要分享的資料;有些API,如Twitter和Facebook,甚至允許使用者(或他們使用的應用程式)修改這些資料。我們可能會聽到「RESTful API」這個術語,REST代表表述性狀態轉移,它是一種指導HTTP 1.1設計的正規化,但不是標準、協定或要求。

使用Requests存取API

以下程式碼展示瞭如何使用Requests存取API:

import requests
result = requests.get('http://pypi.python.org/pypi/requests/json')

這段程式碼實際上對http://pypi.python.org/pypi/requests/json執行了HTTP請求,這是PyPI的JSON後端介面。

HTTP請求方法

在RESTful API中,API設計者選擇伺服器將執行的動作,並在API檔案中告知使用者。常用的HTTP方法包括GET、POST、PUT和DELETE,通常這些「HTTP動詞」會執行其名稱所暗示的操作,例如取得資料、修改資料或刪除資料。

JSON解析

JavaScript物件表示法(JSON)正是JavaScript中用於定義物件的表示法。Requests函式庫在其Response物件中內建了JSON解析器。Python的json模組可以將JSON字串或檔案解析為Python字典(或列表),也可以將Python字典或列表轉換為JSON字串。

JSON範例

以下是一個包含JSON資料的字串:

json_string = '{"first_name": "Guido", "last_name":"van Rossum"}'

可以使用以下程式碼解析它:

import json
parsed_json = json.loads(json_string)

解析後的JSON可以像普通字典一樣使用:

print(parsed_json['first_name'])
"Guido"

程式碼詳解

上述範例中,我們使用了Requests函式庫來傳送HTTP GET請求,並使用json()方法將回應內容解析為JSON格式。這種方式簡化了與網路服務互動的過程,使得開發者能夠更專注於業務邏輯的實作。

程式碼邏輯分析

  1. 匯入必要的函式庫:首先,我們需要匯入requestsjson函式庫。
  2. 傳送HTTP請求:使用requests.get()方法傳送HTTP GET請求到指定的URL。
  3. 處理回應內容:檢查回應是否成功,並使用response.json()方法將回應內容解析為JSON格式。
  4. 存取JSON資料:解析後的JSON資料可以像字典一樣被存取,用於後續的業務邏輯處理。

技術考量

  • 使用Requests函式庫可以簡化HTTP請求的處理,避免手動處理查詢字串或POST資料的編碼問題。
  • JSON是一種輕量級的資料交換格式,易於閱讀和編寫,同時也易於機器解析和生成。
  • 正確處理HTTP請求和回應對於網路應用程式的穩定性和安全性至關重要。

透過上述步驟和技術考量,我們可以有效地使用Python和Requests函式庫來與網路API進行互動,並處理JSON格式的資料。

資料格式轉換與網頁資料擷取

在軟體開發與資料處理的過程中,經常需要處理不同格式的資料,如JSON、XML,以及從網頁中擷取資料等。本文將介紹如何使用Python進行這些操作。

JSON資料處理

JSON(JavaScript Object Notation)是一種輕量級的資料交換格式,廣泛用於網路資料傳輸。Python內建了json模組,可以方便地處理JSON資料。

將Python物件轉換為JSON

可以使用json.dumps()函式將Python物件轉換為JSON格式的字串。例如:

import json

d = {
    'first_name': 'Guido',
    'last_name': 'van Rossum',
    'titles': ['BDFL', 'Developer'],
}

print(json.dumps(d))

#### 內容解密:
此程式碼首先匯入了`json`模組然後定義了一個字典`d`,包含了Guido van Rossum的基本資訊使用`json.dumps(d)`將字典轉換為JSON格式的字串並列印出來。`json.dumps()`函式會將Python物件序列化為JSON格式的字串

對於較早版本的Python,可以使用simplejson函式庫,它提供了與json模組相同的API,但更新更頻繁。

import simplejson as json

#### 內容解密:
此程式碼匯入了`simplejson`函式庫並將其別名設為`json`,以便與標準函式庫中的`json`模組保持一致這樣就可以在較早版本的Python中使用與`json`模組相同的API

XML資料處理

XML(Extensible Markup Language)是一種標記語言,用於儲存和傳輸資料。Python中有多個函式庫可以處理XML資料,如xml.etree.ElementTreeuntanglexmltodict

使用untangle處理XML

untangle函式庫可以將XML檔案轉換為Python物件,其結構與XML節點和屬性相符。

import untangle

obj = untangle.parse('path/to/file.xml')
print(obj.root.child['name'])

#### 內容解密:
此程式碼首先匯入了`untangle`函式庫然後使用`untangle.parse()`函式解析XML檔案並將結果儲存在`obj`變數中最後列印出`child`元素的`name`屬性值

使用xmltodict處理XML

xmltodict函式庫可以將XML檔案轉換為字典,方便存取元素、屬性和值。

import xmltodict

with open('path/to/file.xml') as fd:
    doc = xmltodict.parse(fd.read())

print(doc['mydocument']['@has'])
print(doc['mydocument']['and']['many'])
print(doc['mydocument']['plus']['@a'])
print(doc['mydocument']['plus']['#text'])

#### 內容解密:
此程式碼首先匯入了`xmltodict`函式庫然後開啟XML檔案並使用`xmltodict.parse()`函式解析XML內容將結果儲存在`doc`變數中最後列印出XML檔案中各個元素和屬性的值

網頁資料擷取(Web Scraping)

當網站沒有提供API或CSV、JSON等格式的資料時,可以使用網頁資料擷取技術來取得所需的資料。

使用lxml進行網頁資料擷取

lxml是一個功能強大的函式庫,可以快速解析XML和HTML檔案。

from lxml import html
import requests

page = requests.get('http://econpy.pythonanywhere.com/ex/001.html')
tree = html.fromstring(page.content)

buyers = tree.xpath('//div[@title="buyer-name"]/text()')
prices = tree.xpath('//span[@class="item-price"]/text()')

print(buyers)
print(prices)

#### 內容解密:
此程式碼首先匯入了必要的函式庫然後使用`requests.get()`函式取得網頁內容並使用`html.fromstring()`函式解析HTML內容將結果儲存在`tree`變數中接著使用XPath查詢取得買家姓名和價格並列印出來

在使用網頁資料擷取技術時,務必遵守網站的服務條款和相關規定,避免對網站造成不必要的負擔。

資料序列化與壓縮技術在Python中的應用

在軟體開發過程中,資料的序列化與壓縮是兩個非常重要的議題。資料序列化是指將結構化的資料轉換成可被儲存或傳輸的格式,並且在接收端能夠還原成原始的資料結構。壓縮技術則是用於減少資料的大小,以節省儲存空間或網路頻寬。

資料序列化

Python提供了多種資料序列化的工具,包括內建的pickle模組,以及支援多種語言的序列化工具如Google的Protobuf和Apache的Avro。

Pickle

pickle是Python的原生序列化模組,可以將Python物件序列化成位元組流,也可以將位元組流還原成Python物件。

import pickle

# 定義一個字典
grades = {'Alice': 89, 'Bob': 72, 'Charles': 87}

# 使用dumps將物件序列化成字串
serial_grades = pickle.dumps(grades)

# 使用loads將字串還原成物件
received_grades = pickle.loads(serial_grades)

print(received_grades)

內容解密:

  1. pickle.dumps()函式用於將Python物件序列化成位元組流。
  2. pickle.loads()函式用於將位元組流還原成Python物件。
  3. 需要注意的是,pickle不支援所有型別的物件,例如函式、方法、類別等。

跨語言序列化

如果需要在不同的程式語言之間交換資料,可以使用支援多種語言的序列化工具,如Google的Protobuf和Apache的Avro。

XDR格式

Python的標準函式庫中包含了xdrlib模組,用於處理Sun的External Data Representation(XDR)格式。XDR是一種與作業系統和傳輸協定無關的資料表示格式。

import socketserver
import xdrlib

class XdrHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request.recv(4)
        unpacker = xdrlib.Unpacker(data)
        message_size = unpacker.unpack_uint()
        data = self.request.recv(message_size)
        unpacker.reset(data)
        print(unpacker.unpack_string())
        print(unpacker.unpack_float())
        self.request.sendall(b'ok')

server = socketserver.TCPServer(('localhost', 12345), XdrHandler)
server.serve_forever()

內容解密:

  1. xdrlib.Unpacker類別用於將XDR格式的資料還原成Python物件。
  2. unpack_uint()unpack_string()unpack_float()方法用於還原不同的資料型別。
  3. 需要事先知道資料的結構和順序,才能正確地還原資料。

資料壓縮

Python的標準函式庫中包含了多種資料壓縮和解壓縮的工具,如zlibgzipbzip2lzma

使用gzip壓縮Pickle資料

import pickle
import gzip

data = "my very big object"

# 將資料壓縮並序列化
with gzip.open('spam.zip', 'wb') as my_zip:
    pickle.dump(data, my_zip)

# 將資料解壓縮並還原
with gzip.open('spam.zip', 'rb') as my_zip:
    unpickled_data = pickle.load(my_zip)

print(unpickled_data)

內容解密:

  1. gzip.open()函式用於開啟一個gzip檔案。
  2. pickle.dump()函式用於將Python物件序列化並寫入檔案。
  3. pickle.load()函式用於從檔案中讀取並還原Python物件。

緩衝區協定

Python的緩衝區協定允許開發者減少記憶體中資料的複製次數,從而提高效能。

分散式系統與網路通訊

分散式電腦系統透過相互傳遞資訊共同完成一項任務,例如遊戲對戰、網際網路聊天室或Hadoop計算。本章首先列出我們最受歡迎的網路任務函式庫,接著討論與此類別通訊密切相關的密碼學。

網路通訊

在Python中,連線網路的通訊通常使用非同步工具或執行緒來處理,以繞過全域直譯器鎖(GIL)的單執行緒限制。表9-1中的所有函式庫都解決了同一個問題——繞過GIL——但具有不同的功能和數量。

表9-1 網路通訊函式庫

函式庫名稱授權協定使用理由
asyncioPSF授權• 提供非同步事件迴圈以管理非阻塞socket和佇列的通訊,以及任何使用者定義的協程。
• 包含非同步socket和佇列。
geventMIT授權• 與非同步I/O的C函式庫libev緊密耦合。
• 提供根據libev的HTTP伺服器的快速WSGI伺服器。
• 包含gevent.monkey模組,該模組具有標準函式庫的修補功能,因此可以使用gevent使用以阻塞socket編寫的第三方模組。
TwistedMIT授權• 提供較新協定的非同步實作,例如GPS、物聯網(IoCP)和Memcached協定。
• 將其事件迴圈與各種其他事件驅動框架(如wxPython或GTK)整合。
• 內建SSH伺服器和客戶端工具。
PyZMQLGPL(ZMQ)和BSD(Python部分)授權• 允許使用類別似socket的API設定和介面非阻塞訊息佇列。
• 提供支援分散式計算的socket行為(請求/回應、發布/訂閱和推播/提取)。
• 當您想要建立自己的通訊基礎設施時使用它;它有“Q”在名稱中,但不像RabbitMQ——可以用來建立像RabbitMQ這樣的東西,或是完全不同的行為(取決於所選擇的socket模式)。
pikaBSD授權• 提供輕量級的AMQP(通訊協定)客戶端,以連線RabbitMQ或其他訊息代理。
• 包含與Tornado或Twisted事件迴圈一起使用的介面卡。
• 當您想要一個較輕量級的函式庫(沒有網頁儀錶板或其他附加功能),讓您將內容推播到外部訊息代理(如RabbitMQ)時使用它。
CeleryBSD授權• 提供AMQP客戶端,以連線RabbitMQ或其他訊息代理。
• 具有將任務狀態儲存在後端中的選項,可以使用不同的流行選項,如透過SQLAlchemy、Memcached等的資料函式庫連線。
• 具有可選的網頁管理和監控工具,稱為Flower。
• 可以與訊息代理(如RabbitMQ)一起使用,以實作開箱即用的訊息代理系統。

內容解密:

上述表格中列出的函式庫都用於解決網路通訊中的GIL限制問題,並提供不同的功能和特性。asyncio是Python標準函式庫的一部分,提供非同步事件迴圈和協程支援。gevent和Twisted則是第三方函式庫,分別提供根據libev的快速WSGI伺服器和非同步實作的新協定。PyZMQ、pika和Celery則用於建立和管理訊息佇列和代理。

Python標準函式庫中的效能網路工具

asyncio在Python 3.4中被引入,包含了從開發者社群(如維護Twisted和gevent的社群)中學習到的經驗。它是一種平行工具,常見的應用是網路伺服器。Python自身的asyncore檔案(在Python 3.4中已被棄用)指出:

在單處理器上,有兩種方法可以讓程式同時做多件事情。多執行緒程式設計是最簡單也是最流行的作法,但還有另一種非常不同的技術,可以讓你擁有幾乎所有的多執行緒優點,而不需要實際使用多個執行緒。這種技術只有在程式大多是I/O密集型時才實用。如果程式是CPU密集型的,那麼搶佔式排程的執行緒可能是你真正需要的。然而,網路伺服器很少是CPU密集型的。

asyncio仍然只是Python標準函式庫中的暫定模組——API可能會以向後不相容的方式更改——所以不要太過依賴它。asyncio並非全部都是新的——asyncore(在Python 3.4中已被棄用)具有事件迴圈、非同步socket和非同步檔案I/O,而asynchat(也在Python 3.4中已被棄用)具有非同步佇列。asyncio新增的最大特點是正式化了協程的實作。在Python中,這被正式定義為協程函式——以async def而非def開頭的函式定義。

內容解密:

asyncio是Python 3.4引入的平行工具,主要用於網路伺服器。它解決了單處理器上同時執行多個任務的問題,並提供了事件迴圈、非同步socket和協程等功能。雖然asyncio仍是暫定模組,但它為網路程式設計提供了重要的支援。