天天看點

python 網絡程式設計學習筆記一. 基礎概念二 urllib 子產品三. Http子產品四. socket五. 郵件處理六. 拓展學習

注:此部落格為《python瘋狂講義》的學習筆記

文章目錄

  • 一. 基礎概念
    • 術語
    • 端口
    • 網絡模型
    • 每層網絡子產品都有對應協定
    • python 網絡子產品
    • URL (Uniform Resource Locator)
  • 二 urllib 子產品
    • urllib.parse
      • urlparse
      • 解析查詢字元串 parse_qs, parse_qsl
      • urljoin
    • urllib.request
      • urlopen
      • Request
  • 三. Http子產品
    • cookie
  • 四. socket
  • 五. 郵件處理
    • 1. 郵件發送
    • 2. 郵件接收
  • 六. 拓展學習
    • 1. 請求封包與相應封包
    • 2. 檢視本機IP
    • 3. 檢視端口
    • 5. UDP協定

一. 基礎概念

術語

  • HTTP協定(HyperText Transfer Protocol,超文本傳輸協定):是一種釋出和接收 HTML頁面的方法。
  • HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)簡單講是HTTP的安全版,在HTTP下加入SSL層。

端口

端口是一個 16 位的整數,用于表示将資料交給哪個通信程式處理。 是以,端口就是應用程式 與外界交流的出入口,它是一種抽象的軟體結構,包括一些資料結構和 I/O (輸入/輸出) 緩沖區。 不同的應用程式處理不同端 口上的資料,在同一台機器中不能有兩個程式使用同一個端口 。 端 口号可以為 0~65535 ,通常将端口分為如下三類。
           
  • 公認端口( Well Known Port) :喘口号為 0~1023 , 它們緊密地綁定(Binding) 一些特定 的服務。
  • 注冊端口(Registered Port):端口号為 1024~49151 ,它們松散地結II定一些服務。應用程式 通常應該使用這個範圍内的端口 。
  • 動态和/或私有端口( Dynamic and/or Private Port) : 端口号為 49152~65535,這些端口是 應用程式使用的動态端口,應用程式一般不會主動使用這些端口 。

網絡模型

python 網絡程式設計學習筆記一. 基礎概念二 urllib 子產品三. Http子產品四. socket五. 郵件處理六. 拓展學習

每層網絡子產品都有對應協定

python 網絡程式設計學習筆記一. 基礎概念二 urllib 子產品三. Http子產品四. socket五. 郵件處理六. 拓展學習

其中 ICMP ( Internet Control Message Protocol 〕、 IGMP Cinternet Group Manage Protocol)、 ARP (Address Resolution Protocol )、 RARP C Reverse Address Resolution Protocol) 等協定都可認為是 IP 協定族的子協定。

python 網絡子產品

傳輸層協定主要是 TCP 和 UDP, Python 提供了 socket 等子產品針對傳輸層協定進行程式設計。

python 網絡程式設計學習筆記一. 基礎概念二 urllib 子產品三. Http子產品四. socket五. 郵件處理六. 拓展學習

URL (Uniform Resource Locator)

URL 可以由協定名 、主機、端口和資源路徑組成,即滿足以下格式:

protocol ://host :port/path/…/[?query-string][#anchor] 
# query-string:參數,發送給http伺服器的資料
# anchor:錨(跳轉到網頁的指定錨點位置)
           

例如如下的 URL 位址:

http://www.crazyit.org/index.php

二 urllib 子產品

urllib 子產品則包含了多個用于處理 URL 的子子產品。 );

  • urllib. request:這是最核心的子子產品,它包含了打開和讀取 URL 的各種函數。 );
  • urllib.error: 主要包含由 urllib.request 子子產品所引發的各種異常。 );
  • urllib.parse: 用于解析 URL。 );
  • urllib.robotparser: 主要用于解析 robots.txt 檔案。

通過使用 urllib 子產品可以打開任意 URL 所指向的資源,就像打開本地檔案一樣,這樣程式就 能完整地下載下傳遠端頁面。如果再與第 10 章介紹的 re 子產品結合使用,那麼程式完全可以提取頁面中 各種資訊,這就是所謂的“網絡爬蟲”的初步原理。

在Python2.x中,urllib分為urllib和urllib2兩個子產品,前者用于簡單下載下傳,後者可用于http驗證,cookie管理

urllib.parse

urlparse

屬性名 元組索引 傳回值 屬性名 元組索引 傳回值
scheme fragment 5
netloc 1 主機和端口 username None
path 2 password None
params 3 資源路徑附加參數 hostname None
query 4 查詢字元串 port None
result = urlparse('http://www.crazyit.org:80/index.php;yeeku?name=fkit#frag')
print(result)
# 通過屬性名和索引來擷取URL的各部分
print('資源路徑:', result.path, result[2])
print('參數:', result.params, result[3])
print('查詢字元串:', result.query, result[4])
print('fragment:', result.fragment, result[5])
print(result.geturl())
# 輸出
資源路徑: /index.php /index.php
參數: yeeku yeeku
查詢字元串: name=fkit name=fkit
fragment: frag frag
http://www.crazyit.org:80/index.php;yeeku?name=fkit#frag
           

解析查詢字元串 parse_qs, parse_qsl

# 解析查詢字元串,傳回dict
result = parse_qs('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12')
print(result)
# 解析查詢字元串,傳回list
result = parse_qsl('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12')
print(result)
# 将清單格式的請求參數恢複成請求參數字元串
print(urlencode(result))
# 輸出
{'name': ['fkit', '瘋狂java'], 'age': ['12']}
[('name', 'fkit'), ('name', '瘋狂java'), ('age', '12')]	
name=fkit&name=%E7%96%AF%E7%8B%82java&age=12
           

urljoin

# 被拼接URL不以斜線開頭
result = urljoin('http://www.crazyit.org/users/login.html', 'help.html')
print(result) # http://www.crazyit.org/users/help.html
result = urljoin('http://www.crazyit.org/users/login.html', 'book/list.html')
print(result) # http://www.crazyit.org/users/book/list.html
# 被拼接URL以斜線(代表根路徑path)開頭
result = urljoin('http://www.crazyit.org/users/login.html', '/help.html')
print(result) # http://www.crazyit.org/help.html
# 被拼接URL以雙斜線(代表絕對URL)開頭
result = urljoin('http://www.crazyit.org/users/login.html', '//help.html')
print(result) # http://help.html
           

urllib.request

urlopen

urllib.request.urlopen(url, data=None).

urllib.request.urlopen(urllib.request.Request).

  • 該方法用于打開 url 指定的資源, 并從中讀取資料。根據請求 url 的不同, 該方法的傳回值會發生動 态改變。 如果 url 是一個 HTTP 位址, 那麼該方法傳回一個http.client.HTTP Response 對象。
  • 使用data屬性向被請求的url發送資料
params = urllib.parse.urlencode({'name': 'fkit', 'password': '123888'})

f=urlopen("http://localhost:8080/test/post.jsp", data=params)

## 等價于使用附加參數,如下
#将請求參數添加到URL的後面
url = 'http://localhost:8080/test/get.jsp?%s' % params
f = urlopen(url=url)
           

Request

(1) 發送PUT請求

params = 'put請求資料'.encode('utf-8')
# 建立Request對象,設定使用PUT請求
req = Request(url='http://localhost:8080/test/put',
    data=params, method='PUT')
req.add_header('Referer', 'http://www.crazyit.org/')
with urlopen(req) as f:
	print(f.status)
	print(f.read().decode('utf-8'))
           

三. Http子產品

cookie

例:

import urllib.request as ur
import http.cookiejar as hc, urllib.parse

# 以指定檔案建立CookieJar對象,對象将可以把cookie儲存在檔案中
cookie_jar = hc.MozillaCookieJar('coockie_info.txt')
cookie_processor = ur.HTTPCookieProcessor(cookie_jar)
opener = ur.build_opener(cookie_processor)

# 定義模拟Chrome浏覽器的user_agent
user_agent = r'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36' \
    r' (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
# 定義請求頭
headers = {'User-Agent':user_agent, 'Connection':'keep-alive'}

#-------------下面代碼發送登入的POST請求----------------
# 定義登入系統的請求參數
params = {'name':'crazyit.org', 'pass':'leegang'}
postdata = urllib.parse.urlencode(params).encode()
# 建立向登入頁面發送POST請求的Request
request = ur.Request('http://localhost:8080/test/login.jsp',
    data = postdata, headers = headers)
# 使用OpenerDirector發送POST請求
response = opener.open(request)
print(response.read().decode('utf-8'))

# 将cookie資訊寫入磁盤檔案
cookie_jar.save(ignore_discard=True, ignore_expires=True)  # ①

#-------------下面代碼發送通路被保護資源的GET請求----------------
# 建立向"受保護頁面"發送GET請求的Request
request = ur.Request('http://localhost:8080/test/secret.jsp',
    headers=headers)
response = opener.open(request)
print(response.read().decode())
           

四. socket

server.py示例

s = socket.socket()
# 将socket綁定到本機IP和端口
s.bind(('192.168.43.36', 3000))
# 服務端開始監聽來自用戶端的連接配接
s.listen()
while True:
    # 每當接收到用戶端socket的請求時,該方法傳回對應的socket和遠端位址
    c, addr = s.accept()
    print('連接配接位址:', addr)
    c.send('您好,您收到了伺服器的新年祝福!'.encode('utf-8'))
    # 關閉連接配接
    c.close()
           

client.py示例

s = socket.socket()

# 連接配接遠端主機
s.connect(('192.168.43.36', 3000))   
rec = s.recv(1024).decode('utf-8')
           

以上a.accept()才用阻塞的方式接收消息。

通過 selectors 可實作監聽消息。

五. 郵件處理

1. 郵件發送

  • 連接配接 SMTP 伺服器,并使用使用者名、密碼登入伺服器。
  • 建立 Emai!Message 對象,該對象代表郵件本身。
  • 調用代表與 SMTP 伺服器連接配接的對象的 sendmail()方法發送郵件
主要用到的子產品:smtplib,email.message.EmailMessage

2. 郵件接收

使用 poplib 收取郵件可分為兩步。

  • 使用 poplib.POP3 或 poplib.POP3_SSL 按 POP3 協定從伺服器端下載下傳郵件。
  • 使用 email.parser.Parser或 email.parser.BytesParser解析郵件件内容,得到 EmailMessage 對象
  • 從 EmailMessage 對象中讀取郵件内容。
主要用到的子產品:poplib,email.parser,email.policy

六. 拓展學習

1. 請求封包與相應封包

詳細參考

  1. 請求封包

執行個體:

python 網絡程式設計學習筆記一. 基礎概念二 urllib 子產品三. Http子產品四. socket五. 郵件處理六. 拓展學習

結構圖:

python 網絡程式設計學習筆記一. 基礎概念二 urllib 子產品三. Http子產品四. socket五. 郵件處理六. 拓展學習

常見封包頭屬性

名稱 說明
Accept 告訴服務端 用戶端接受什麼類型的響應 一個或多個MIME類型
Cookie
Refere 表示這個請求是從哪個URL過來的 url
Cache-Control 是否在客服端緩存
User-Agent
其它
  1. 響應封包

(1)執行個體

python 網絡程式設計學習筆記一. 基礎概念二 urllib 子產品三. Http子產品四. socket五. 郵件處理六. 拓展學習

(2)響應狀态碼

  • 1xx 消息,一般是告訴用戶端,請求已經收到了,正在處理,别急…
  • 2xx 處理成功,一般表示:請求收悉、我明白你要的、請求已受理、已經處理完成等資訊.
  • 3xx 重定向到其它地方。它讓用戶端再發起一個請求以完成整個處理。
  • 4xx 處理發生錯誤,責任在用戶端,如用戶端的請求一個不存在的資源,用戶端未被授權,禁止通路等。
  • 5xx 處理發生錯誤,責任在服務端,如服務端抛出異常,路由出錯,HTTP版本不支援等。

    (3)常見封包頭屬性

說明
Cache-Control: max-age=3600 讓用戶端對響應内容緩存3600秒,也即在3600秒内,如果客戶再次通路該資源,直接從用戶端的緩存中傳回内容給客戶,不要再從服務端擷取
ETag:“…” 當服務端資源發生變化,這個ETag就會相應發生變化。可以讓用戶端“更智能”地處理什麼時候要從服務端取資源,什麼時候可以直接從緩存中傳回響應。
Location: http://www.iteye.com 其實是讓用戶端再發一個請求到A頁面
Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 服務端可以設定用戶端的Cookie

2. 檢視本機IP

cmd: ipconfig/all

3. 檢視端口

目的
檢視所有端口使用情況 netstat -ano
檢視特定端口 netstat -ano

5. UDP協定

  • UDP (User Datagram Protocol,使用者資料報協定〉雖然目前 UDP 協定的應用不如TCP 協定廣泛,但 UDP 依然是一種非常實用和可行的網絡傳輸層協定。 尤其是在一些實時性很強的應用場景中,比如網絡遊戲、視訊會議等, UDP 協定的快速能力更具有獨特的魅力。
  • UDP 是一種面向非連接配接的協定,面向非連接配接指的是在正式通信前不必與對方先建立連接配接,不 管對方狀态就直接發送資料。 至于對方是否可以接收到這些資料, UDP 協定無法控制,是以說 UDP 是一種不可靠的協定。 UDP 協定适用于一次隻傳送少量資料、對可靠性要求不高的應用環境。
  • UDP 協定的主要作用是完成網絡資料流和資料報之間的轉換。在資訊的發送端, UDP 協定 将網絡資料流封裝成資料報,然後将資料報發送出去;在資訊的接收端, UDP 協定将資料報轉換 成實際資料内容。
可以認為 UDP協定的 socket類似于碼頭,資料報則類似于集裝箱。 碼頭的作用就· ‘益,是負責友送、接收集裝箱, 而 socket 的作用則是發送、接收資料報。 是以, 對于基于| UDP 協定的通信雙方而言,沒有所謂的客戶 端和伺服器端的概念。