Python 網(wǎng)絡(luò)編程

網(wǎng)絡(luò)

  • 理論模型,分為七層

    • 物理層
    • 數(shù)據(jù)鏈路層
    • 傳輸層
    • 會話層
    • 表示層
    • 應(yīng)用層
  • 實際應(yīng)用,分為四層

    • 鏈路層
    • 網(wǎng)絡(luò)層
    • 傳輸層
    • 應(yīng)用層
  • IP地址

    • IPV4 地址族,4個字段組成,每個字段取值0-255

      • 局域網(wǎng)IP,192.168.XXX,XXX

      • 本機本地地址,127.0.0.1

    • IPV6 地址族,8個字段組成,每個字段取值0000-FFFF

  • 端口

    • 設(shè)備上每個應(yīng)用需要與外界通信的地址

    • 范圍是 0-65535

    • 知名端口 0-1023

    • 非知名端口 1024-65535

  • 套接字

    • 我理解的套接字相當于與電話,而人則代表每個設(shè)備;當兩個人需要通信時,需要電話.這就是套接字,而知道電話是不夠的,還需要知道電話號碼,這樣才能確保電話打到你想通話的哪個人去

    • 套接字對象由addr(host,port)地址定義,host是IP地址,port代表端口

    • host主要用來確定是IP地址為哪一個的電腦

    • port主要用來確定是該電腦上的哪個軟件

  • 域名

    • 網(wǎng)絡(luò)上計算名,或計算機組的名稱

    • 瀏覽器根據(jù)域名來查找對應(yīng)的IP地址

      • 查找本地hsot文件,檢查是否有對應(yīng)的IP地址

      • 如果沒有,查找本地DNS服務(wù)器.也就是運營商,檢查是否有對應(yīng)的IP

      • 如果沒有,本地DNS服務(wù)器查找根DNS服務(wù)器,檢查是否有對應(yīng)的IP

      • 如果沒有,根DNS服務(wù)器返回消息給本地DNS服務(wù)器,讓其到域服務(wù)器查找IP

  • DNS 域名服務(wù)器系統(tǒng)

    • DNS將域名映射到對應(yīng)的IP地址

    • DNS查詢

      • 遞歸查詢
      image
      • 迭代查詢
      image
    • DNS 負載均衡

      • 在DNS服務(wù)器中,為域名配置多個IP地址,根據(jù)距離遠近,使用距離較近的IP

socket 庫

  • 協(xié)議家族

    • 基于文件

      • AF_UNIX 同臺機器進程之間的通行
    • 基于網(wǎng)絡(luò)

      • AF__INET IPV4協(xié)議

      • AF_INET6 IPV6協(xié)議

  • 網(wǎng)絡(luò)協(xié)議

    • SOCK_STREAM TCP協(xié)議 , 連接的套接字,只有當服務(wù)器與客戶端連接后,才開始傳輸數(shù)據(jù),可以確定數(shù)據(jù)的先后,也可以確定對方一定能接收到消息

    • SOCK_DGRAM UDP協(xié)議 , 無連接的套接字,服務(wù)器不斷的監(jiān)聽某個套接字,從這個套接字獲取或者發(fā)送數(shù)據(jù),無法確定數(shù)據(jù)的先后順序,也無法確定對方是否收到消息

  • 直接調(diào)用的函數(shù)

    • getfqdn(name) 返回name的域名

    • gethostbyname(hostname) 返回主機名的IPV4地址

    • gethostname() 返回正在執(zhí)行當前解釋器的機器的主機名

    • sethostname(name) 將本機主機名設(shè)置為name

  • socket(family,type) 套接字對象類

    • 函數(shù)

      • 通用函數(shù)

        • bind(addr) 服務(wù)器綁定套接字,addr為(host,port)

        • shuntdown() 關(guān)閉連接

        • setblocking(boolean) 設(shè)置是否為阻塞模式

        • settimeout(second) 設(shè)置超時時間

          • None 阻塞模式
          • 0 非阻塞模式
          • 非0值 在規(guī)定時間后拋出異常
        • close() 關(guān)閉套接字

      • TCP 函數(shù)

        • listen() 監(jiān)聽地址,阻塞式的,不斷循環(huán)監(jiān)聽地址

        • accept() 服務(wù)器接收TCP客戶端連接,返回新的連接的套接字和客戶端的地址

        • send(data) 發(fā)送數(shù)據(jù)

        • sendall(data) 發(fā)送所有數(shù)據(jù)

        • recv(bufsize) 接收TCP指定字節(jié)數(shù)的數(shù)據(jù),一旦超過指定字節(jié),就需要使用循環(huán)接收的方式接收完整的數(shù)據(jù)

          • 短鏈接法,發(fā)送數(shù)據(jù)完畢后關(guān)閉連接,讓recv()函數(shù)獲取連接關(guān)閉后自動取消阻塞模式

          • 末尾標志法,在末尾添加相應(yīng)哨兵值,在recv()函數(shù)接收到哨兵值之后跳出接收數(shù)據(jù)的死循環(huán),進行下一步操作

          • 負載長度法,提前告知長度,后根據(jù)長度判斷是否跳出接收數(shù)據(jù)的死循環(huán)

        • connect(addr) 發(fā)起連接,向addr(host,port)發(fā)起連接

        # 設(shè)置TCP服務(wù)器
        import socket,time
        
        server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        
        server.bind(('127.0.0.1',12345))
        
        server.listen()
        
        con,addr = server.accept()
        
        data = con.recv(1024)
        
        text = data.decode()
        print(text)
        
        data = '{0} : {1}'.format(time.ctime(),text).encode()
        
        con.sendall(data)
        
        con.close()
        
        server.close()
        
        # 設(shè)置TCP客戶端
        import socket
        
        client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        
        client.connect(('127.0.0.1',12345))
        
        text = 'Hello'
        
        client.sendall(text.encode())
        
        data = client.recv(1024)
        
        print(data.decode())
        
        client.close()
        
      • UDP 函數(shù)

        • recvfrom(bufsize) 接收UDP消息,返回連接的套接字地址

        • sendto(data,addr) 將data數(shù)據(jù)發(fā)送到指定addr地址

        # 設(shè)置UDP服務(wù)器
        import socket,time
        
        server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        
        server.bind(('127.0.0.1',12345))
        
        data,addr = server.recvfrom(1024)
        
        text = data.decode()
        print(text)
        
        server.sendto('{0} : {1}'.format(time.ctime(),text).encode(),addr)
        
        server.close()
              
        # 設(shè)置UDP客戶端
        import socket
        
        client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        
        text = 'Hello'
        
        client.sendto(text.encode(),('127.0.0.1',12345))
        
        data,addr = client.recvfrom(1024)
        
        print(data.decode())
        

socketserver 網(wǎng)絡(luò)服務(wù)器框架模塊

  • 此模塊提供網(wǎng)絡(luò)服務(wù)器框架,可以使開發(fā)者更加快捷的開發(fā)出相應(yīng)的網(wǎng)絡(luò)服務(wù)器

  • 服務(wù)器server對象

    • BaseServer(server_address,RequestHandlerClass) 所有Server對象的超類,同步處理請求,只有當一個請求處理完成之后才能處理下一個請求,每次只能完成一個請求

      • RequestHandlerClass 處理請求類

      • get_request() 接收客戶端請求,并返回一個和客戶端連接的套接字和客戶端地址組成的元組

      • server_bind(addr) 綁定地址

      • serve_forever() 永遠處理請求

      • shutdown() 停止處理請求

      • server_close() 關(guān)閉服務(wù)器

    • TCPServer (server_address,RequestHandlerClass) 繼承于BaseServer,完善了TCP的相關(guān)方法,用于TCP服務(wù)器的創(chuàng)建,需要重寫RequestHandlerClass

    # 改寫的上面采用socket庫編寫的TCP服務(wù)器
    import socketserver,time
    
    class Server(socketserver.TCPServer):
        pass
    
    class MyRequestHandler(socketserver.StreamRequestHandler):
    
        def handle(self):
            data = self.request.recv(1024)
            text = data.decode()
            print(text)
            data = '{0} : {1}'.format(time.ctime(),text).encode()
            self.request.sendall(data)
    
    server = Server(('127.0.0.1',12345),MyRequestHandler)
    server.serve_forever()
    
    # 客戶端
    import socket
    
    with socket.socket(socket.AF_INET,socket.SOCK_STREAM)as client:
    
        client.connect(('127.0.0.1',12345))
    
        client.sendall('hello'.encode())
    
        data = client.recv(1024)
    
        print(data.decode())
    
    • UDPServer (server_address,RequestHandlerClass) 繼承于BaseServer,完善了TCP的相關(guān)方法,用于UDP服務(wù)器的創(chuàng)建,需要重寫RequestHandlerClass
    # 服務(wù)器端
    import socketserver,time
    
    class Server(socketserver.UDPServer):
        pass
    
    class MyRequestHandler(socketserver.DatagramRequestHandler):
    
        def handle(self):
            data,con = self.request
            print(data.decode())
    
            data = '{0} : {1}'.format(time.ctime(),data.decode()).encode()
            con.sendto(data,self.client_address)
    
    server = Server(('127.0.0.1',12345),MyRequestHandler)
    server.serve_forever()
    
    # 客戶端
    import socket
    
    with socket.socket(socket.AF_INET,socket.SOCK_DGRAM)as client:
    
        data = 'hello'.encode()
        client.sendto(data,('127.0.0.1',12345))
    
        data = client.recv(1024)
        print(data.decode())
    
    • 適用于Unix平臺的服務(wù)器,

      • UnixStreamServer (server_address,RequestHandlerClass)

      • UnixDatagramServer (server_address,RequestHandlerClass)

    image
  • 擴展功能的Mixin類

    • ForkingMixIn 多進程MIXIN類 ,可以與其他Server對象進行組合,適用于Linux 平臺

    • ThreadingMixIn 多線程MIXIN類,可以與其他Server對象進行組合

  • 模塊中已組合的擴展功能的服務(wù)器Server類

    • ForkingTCPServer(server_address,RequestHandlerClass) 多進程TCP服務(wù)器類,ForkingMixIn與TCPServer的組合

    • ForkingUDPServer(server_address,RequestHandlerClass) 多進程UDP服務(wù)器類,ForkingMixIn與UDPServer的組合

    • ThreadingTCPServer(server_address,RequestHandlerClass) 多線程TCP服務(wù)器類,ThreadingMixIn與TCPServer的組合

    • ThreadingUDPServer(server_address,RequestHandlerClass) 多線程UDP服務(wù)器類,ThreadingMixIn與UDPServer的組合

  • 請求處理類

    • BaseRequestHandler 處理請求類,其中定義了三個方法:setup、handlefinish,都默認什么都不做,需要進行重寫才能使用,是其他處理請求類的超類

      • setup() 在handle方法之前調(diào)用的操作

      • handle() 處理客戶端請求的方法

        • self.request 在不同Server服務(wù)器對象中具有不同的含義

          • 在TCPServer中,返回的是連接的客戶端的套接字

          • 在UDPServer中,返回的數(shù)據(jù)和連接的客戶端套接字的一個元組

        • self.client_address 返回連接的客戶端的地址

        • self.rfile 可以從此屬性中讀取客戶端發(fā)送的數(shù)據(jù)

        • self.wfile 可以從此屬性中寫入服務(wù)器發(fā)給客戶端的數(shù)據(jù)

      • finish() 在handle方法之后調(diào)用的操作

    • StreamRequestHandler TCP處理請求類,是BaseRequestHandler的子類,實現(xiàn)了關(guān)于TCP的相關(guān)方法,但需要實現(xiàn)handle方法

    • DatagramRequestHandler UDP處理請求類,是BaseRequestHandler的子類,實現(xiàn)了關(guān)于UDP的相關(guān)方法,但需要實現(xiàn)handle方法

ftplib 模塊

  • FTP (FileTransferProtocal) 文件傳輸協(xié)議

  • 用戶

    • Real賬戶 注冊賬戶

    • Guest賬戶 臨時賬戶

    • Anonymous 匿名賬戶

  • 端口

    • 21 端口為控制和命令端口

    • 20 端口為數(shù)據(jù)端口

  • FTP(host,usr,passwd)類

    • 可以使用上下文管理協(xié)議 即with語句

    • connect(host,port) 當沒有在實例化FTP定義host時,則需要調(diào)用connect函數(shù)指定host和port

    • login(usr,passwd) 給定賬號密碼登錄,默認usr為anonymous,密碼為anonymous@

    • abort() 中斷傳輸?shù)奈募?/p>

    • sendcmd(cmd) 向服務(wù)器發(fā)送字符串命令,并返回響應(yīng)代碼

    • retrbinary(cmd,callback) 以二進制形式接收文件,callback為用于接收文件的回調(diào)函數(shù)

    • storbinary(cmd,fp) 以二進制形式上傳文件,fp為二進制流

    • retrlines(cmd,callback) 文本形式接收文件

    • storlines(cmd,fp) 文本形式上傳文件

    • nlst() 返回文件名列表

    • dir() 輸出文件名列表到sys.stdout

    • rename(old,new) 重命名

    • delete(filename) 刪除文件

    • pwd() 返回當前目錄路徑

    • cwd(path) 將path設(shè)置為當前路徑

    • mkd(path) 創(chuàng)建新目錄

    • rmd(dirname) 刪除dirname目錄

    • size(file) 返回文件大小

    • quit() 關(guān)閉連接

import ftplib

#定義回調(diào)函數(shù),將retrbinary函數(shù)接收到的數(shù)據(jù)寫入本地文件中
def file(data):
    with open(r'1.txt','wb')as f:
        f.write(data)

# 指定FTP的host,獲得套接字連接
con = ftplib.FTP('ftp.acc.umu.se')

# 連接FTP服務(wù)器
con.connect()

# 匿名賬戶登錄
con.login()

con.dir()

# 下載文件,并調(diào)用file函數(shù),將數(shù)據(jù)寫入本地文件
con.retrbinary('RETR robots.txt',file)

# 關(guān)閉連接
con.close()

email 電子郵件模塊

  • 郵件傳輸模式

    • MUA 客戶端程序

    • MTA (Mail Transfer Agent) 郵件傳輸代理,將發(fā)件人的郵件傳輸?shù)桨l(fā)件人郵箱所在的服務(wù)器

    • MDA (Mail Delivery Agent) 郵件投遞代理,發(fā)件人郵箱所在的服務(wù)器將郵件傳輸?shù)绞占肃]箱所在的服務(wù)器

    • MRA (Mail retrieva Agent) 郵件獲取代理,收件人郵箱所在的服務(wù)器將郵件獲取到收件人的郵箱地址中去

    image
  • 郵件傳輸使用MIME協(xié)議(多用途互聯(lián)網(wǎng)郵件擴展),即電子郵件需要符合相應(yīng)的MIME格式,才能進行發(fā)送

    • MIME協(xié)議中包括郵件標頭、郵件消息體兩個部分

    • 郵件標頭是key-value形式的字符串,每個標頭獨占一行

    • 標頭屬性

      • From 發(fā)件人地址
      • To 收件人地址
      • Cc 抄送地址
      • Subject 主題
      • Content-Type 郵件體中包含的內(nèi)容類型
      • Content-Disposition: "attachment;filename='name.type'" 設(shè)置附件的下載方式和顯示名稱,其中attachment為附件方式打開,inline在郵件中打開
    • 標頭后跟著空行,下面為郵件消息體

    • 消息體為郵件的具體內(nèi)容

Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
From: mine<xxxx@163.com>
To: you<xxx@qq.com>
Subject: =?utf-8?b?6YKu5Lu25qCH6aKY?=

6L+Z5piv5LiA5Lu95paH5pys5raI5oGv6YKu5Lu2
  • mime 構(gòu)造郵件消息模塊

    • 每個MIME類型的郵件消息對象只需要添加標頭就可以作為郵件進行發(fā)送

    • multipart.MIMEMultipart(subtype ='mixed',boundary = None,spartparts = None,policy = compat32) 構(gòu)造多個消息組成的總消息

    • application.MIMEApplication(data,subtype = '八位字節(jié)流',encoder = email.encoders.encode_base64) 構(gòu)造MIME郵件的Application消息

    • audio.MIMEAudio(audiodata,subtype = None,encoder = email.encoders.encode_base64) 構(gòu)造MIME郵件的Audio消息

    • image.MIMEImage(imagedata,subtype = None,encoder = email.encoders.encode_base64) 構(gòu)造MIME郵件的Image消息

    • text.MIMEText(text,subtype ='plain',charset = None,*,policy = compat32) 構(gòu)造一個MIME郵件的文本消息

  • message 郵件消息操作模塊

    • EmailMessage

      • 同下
    • Message

      • as_string() 將消息對象作為字符串返回

      • as_bytes() 將消息對象作為二進制流返回

      • attach(message) 將message消息對象添加到當前消息對象

      • items() 返回消息字段標題和值的元組的列表

      • add_header(name,value) 添加郵件標頭

    • get_payload(i=None, decode=False) 返回郵件消息中每行內(nèi)容所組成的列表,選擇是否解碼,一般需要填入True

    • walk() 迭代器,迭代郵件消息的每一行

  • header 構(gòu)造郵件標頭模塊

    • Header(str=None,charset=None,header_name = NONE) 類 創(chuàng)建符合MIME協(xié)議的標頭

    • 郵件標頭可以通過兩種方式進行構(gòu)造

      1. 使用Header類進行構(gòu)造,使用消息對象的屬性進行賦值
      msg['From'] = Header('xxxx@xx.com') 
      
      1. add_header(name,value)函數(shù),使用消息對象的函數(shù)進行賦值
      msg.add_header('From','xxxx@xx.com')
      
    • 郵件頭的解碼

      • decode_header(_header) 解碼標頭值,返回(decode_string,charset)組成的元組的列表
  • parse 郵件解碼模塊

    • BytesParser 二進制數(shù)據(jù)解析類

      • parse(fp,headersonly = False ) 解析二進制流,生成消息對象

      • parsebytes(bytes,headersonly = False ) 解析二進制數(shù)據(jù),生成消息對象

      • BytesHeaderParser() 解析標頭二進制數(shù)據(jù),返回標頭對象

    • Parser 文本解析類

      • parse(fp,headersonly = False ) 解析文本流,生成消息對象

      • parsestr(text,headersonly = False ) 解析字符串,生成消息對象

      • HeaderParser() 解析標頭文本數(shù)據(jù),返回標頭對象

  • email模塊下直接使用的解析類

    • message_from_bytes(s,_class = None,*,policy = policy.compat32 ) 從二進制數(shù)據(jù)返回消息對象

    • message_from_binary_file(fp,_class = None,*,policy = policy.compat32 ) 從二進制流返回消息對象

    • message_from_string(s,_class = None,*,policy = policy.compat32 ) 從字符串返回消息對象

    • message_from_file(fp,_class = None,*,policy = policy.compat32 ) 從文本流中返回消息對象

smtplib SMTP簡單郵件發(fā)送協(xié)議模塊

  • SMTP 是負責(zé)郵件發(fā)送的協(xié)議

  • SMTP(host,port) 未加密的SMTP類

    • 可以使用上下文管理協(xié)議,即with語句

    • connect(host,port) 連接到郵件服務(wù)器

    • login(usr,pwd) 登錄

    • sendmail(from_addr,to_addr,msg) 發(fā)送郵件 msg為字符串,也就是需要通過消息對象調(diào)用as_string()方法

    • quit() 關(guān)閉連接

  • SMTP_SSL(host,port) ssl加密的SMTP類

    • 方法同上
  • 發(fā)送一封純文本格式的郵件

    import smtplib
    from email.mime.text import MIMEText
    
    usr = 'xxx@163.com'
    pwd = 'xxxxx'
    to_mail = 'xxxxx@qq.com'
    
    # 構(gòu)造文本消息郵件
    msg = MIMEText('這是一份文本消息郵件')
    
    # 添加標頭,使之變?yōu)猷]件
    msg['From'] = 'mine<{0}>'.format(usr)
    msg['To'] ='you<{0}>'.format(to_mail)
    msg['Subject'] = '郵件標題'
    
    # 發(fā)送郵件
    with smtplib.SMTP()as con:
    
        # 變?yōu)閐ebug模式,輸出信息到控制臺
        con.set_debuglevel(1)
    
        # 連接郵件服務(wù)器
        con.connect('smtp.163.com',25)
    
        # 登錄
        con.login(usr,pwd)
        
        # 發(fā)送郵件
        con.sendmail(usr,to_mail,msg.as_string()) 
    
  • 發(fā)送一封html格式的郵件

    import smtplib
    from email.mime.text import MIMEText
    
    usr = 'xxx@163.com'
    pwd = 'xxxxx'
    to_mail = 'xxxxx@qq.com'
    
    # 構(gòu)造html
    content ="<html><h1>這是一封html郵件</h1></html>"
    
    # 構(gòu)造文本消息郵件
    msg = MIMEText(content,'html','utf-8')
    
    # 添加標頭,使之變?yōu)猷]件
    msg['From'] = 'mine<{0}>'.format(usr)
    msg['To'] ='you<{0}>'.format(to_mail)
    msg['Subject'] = '郵件標題'
    
    # 發(fā)送郵件
    with smtplib.SMTP()as con:
    
        # 變?yōu)閐ebug模式,輸出信息到控制臺
        con.set_debuglevel(1)
    
        # 連接郵件服務(wù)器
        con.connect('smtp.163.com', 25)
    
        # 登錄
        con.login(usr, pwd)
    
        # 發(fā)送郵件
        con.sendmail(usr, to_mail, msg.as_string())
    
  • 發(fā)送一封帶有附件的郵件

    import smtplib
    from email.mime.multipart import MIMEMultipart
    from email.mime.application import MIMEApplication
    from email.mime.text import MIMEText
    
    usr = 'xxx@163.com'
    pwd = 'xxxxx'
    to_mail = 'xxxxx@qq.com'
    file = r'C:\Users\wudiz\Desktop\BaseServer.png'
    
    # 構(gòu)造文本消息郵件
    msg = MIMEMultipart('組合郵件')
    
    # 添加標頭,使之變?yōu)猷]件
    msg['From'] = 'mine<{0}>'.format(usr)
    msg['To'] ='you<{0}>'.format(to_mail)
    msg['Subject'] = '郵件標題'
    
    # 構(gòu)造文本
    text = MIMEText('這是一封組合郵件')
    
    # 添加到msg組合消息對象中
    msg.attach(text)
       
    # 構(gòu)造附件
    data = MIMEApplication(open(file,'rb').read())
    
    # 添加MIME類型
    data.add_header('Content-Type','application/octet-stream')
    
    # 設(shè)置附件
    data.add_header('Content-Disposition',"attachment;filename='1.png'")
    
    # 添加到msg組合消息對象中
    msg.attach(data)
    
    # 發(fā)送郵件
    with smtplib.SMTP()as con:
    
        # 變?yōu)閐ebug模式,輸出信息到控制臺
        con.set_debuglevel(1)
    
        # 連接郵件服務(wù)器
        con.connect('smtp.163.com', 25)
    
        # 登錄
        con.login(usr, pwd)
    
        # 發(fā)送郵件
        con.sendmail(usr, to_mail, msg.as_string())
    

poplib 郵局協(xié)議模塊

  • POP3 (Post Office Protocol - Version 3) 郵局協(xié)議版本3

  • POP3(host,port) 非加密POP3協(xié)議類

    • set_debuglevel(1) 設(shè)置為調(diào)試模式

    • stls() 以tls驗證服務(wù)器

    • getwelcome() 返回服務(wù)器的問候語字符串

    • capa() 查詢服務(wù)器的功能

    • user(usr) 發(fā)送用戶名

    • pass_(pwd) 發(fā)送密碼

    • apop(usr,pwd) 使用APOP身份驗證登錄郵箱

    • rpop(usr,pwd) 使用RPOP身份驗證登錄郵箱

    • stat() 獲取郵箱狀態(tài),返回(message_count,mailbox_size)的元組

    • list(num) 獲取郵件列表,如果設(shè)置了數(shù)字,則為數(shù)字所在編號郵件的內(nèi)容,返回(response,num,octets)組成的元組 response為響應(yīng)代碼,num為郵件數(shù)量,octets為郵件大小

    • retr(num) 檢索郵件號,返回(response,lines,octets)組成的元組 lines為郵件每行組成的一個二進制列表,需要將其每個一行的組合起來才能變成二進制郵件,二進制郵件解碼才能變?yōu)猷]件

    • dele(num) 標記郵件號,退出登錄后刪除

    • rset() 立即刪除標記的郵件號

    • quit() 關(guān)閉連接

  • POP3_SSL(host,port) SSL加密POP3協(xié)議類

    • 方法同上,現(xiàn)在一般使用該類
    import poplib
    import email.header
    
    # 指定連接POP3服務(wù)器的host和port
    con = poplib.POP3('pop3.163.com',110)
    
    con.set_debuglevel(1)
    
    con.user('xxx')
    
    con.pass_('xxx')
    
    print(con.getwelcome())
    
    # 選定郵箱中的第三封郵件
    list = con.retr(3)
    
    # 設(shè)置二進制對象
    data = b''
    
    # 將二進制郵件的每一行寫入data中,構(gòu)建完整的郵件,按每行進行寫入
    for i in list[1]:
        data = data + i + b'\r\n'
    
    con.quit()
    
    # 解析為MIME消息對象
    mail = email.message_from_bytes(data)
    
    # 解析標頭中的標題
    subject = email.header.decode_header(mail.get('Subject'))
    
    # 解碼Subject標頭值的字符串,并打印
    print(subject[0][0].decode(subject[0][1]))
    
    # 按base64解碼消息中的內(nèi)容
    content = mail.get_payload(decode=True)
    
    # 按UTF-8解碼內(nèi)容
    print(content.decode())
    

http 超文本傳輸協(xié)議模塊

  • http協(xié)議 是Hyper Text Transfer Protocol的縮寫,簡稱為超文本傳輸協(xié)議

    • HTTP 的默認端口為80

    • HTTPS的默認端口為443

    • 永遠是客戶端先發(fā)起請求,然后服務(wù)器響應(yīng)請求

    • 工作模式

      • 建立連接

        • 需要進行三次握手
          • 客戶端發(fā)送一個請求給服務(wù)端要求建立連接,進入等待狀態(tài)(SYN_SEND)
          • 服務(wù)端同意連接,發(fā)送一個響應(yīng)給客戶端,進入等待狀態(tài)(SYN_SEND)
          • 客戶端接收這個響應(yīng),并與之建立連接(ESTABLISHED)
      • 接收數(shù)據(jù)

      • 結(jié)束連接

  • 請求報文 Request

    [圖片上傳失敗...(image-49e11e-1536041654038)]

    • 請求行包括了請求方法,請求的url和http版本

      • 請求方法

        • POST 向服務(wù)器提交數(shù)據(jù) 改

        • GET 請求數(shù)據(jù) 查

        • PUT 向服務(wù)器上傳數(shù)據(jù) 增

        • DELETE 請求服務(wù)器刪除相應(yīng)數(shù)據(jù) 刪

    • 請求頭是key-value形式的,其中有以下屬性

      • Host 請求資源的主機地址(必須存在)
      • User-Agent 客戶端的瀏覽器類型和版本
      • Accept-Language 客戶端申明自己接收的語言
      • Accept 客戶端申明自己想要接收數(shù)據(jù)的類型
        • gzip
        • deflate
      • Accept-Encoding 客戶端申明自己接收的編碼,通常指定壓縮方法
      • Cookie 發(fā)送cookie值
      • Connection 連接方式
        • keep-alive 持久連接,當訪問網(wǎng)頁后連接不會關(guān)閉
        • close 短連接,訪問后就關(guān)閉,下次建立新的連接
      • Keep-Alive 保持連接的時間
      • Referer 表示用戶從該網(wǎng)頁訪問服務(wù)器
      • Date 此報文產(chǎn)生的日期
      • Authorization 客戶端權(quán)限
    • 空行,請求頭和請求體之間必須有一個空行

    • 請求體

  • 響應(yīng)報文 Response

    [圖片上傳失敗...(image-8a1169-1536041654038)]

    • 響應(yīng)行,包括了服務(wù)器軟件的版本號,返回的狀態(tài)碼和相應(yīng)短語

      • 1XX 服務(wù)器已接收請求,繼續(xù)處理
      • 2XX 服務(wù)器請求已被處理
      • 3XX 重定向
      • 4XX 客戶端錯誤
      • 5XX 服務(wù)器錯誤
    • 響應(yīng)頭

      • Location 重定向到另一個位置
      • Server 服務(wù)器軟件
      • Date 此報文產(chǎn)生的日期
      • Content-Length 響應(yīng)體的長度
      • Content-Type 聲明發(fā)送響應(yīng)體的類型和編碼
    • 空行

    • 響應(yīng)體,也就是服務(wù)器返回的請求資源

  • client HTTP客戶端模塊模塊

    • HTTPConnection(host,port = None) 使用http協(xié)議連接服務(wù)器,返回一個HTTPConnection對象

      • request(method,url,body = None,headers = {}) 向服務(wù)器發(fā)送請求

      • getresponse() 返回服務(wù)器相應(yīng)

      • set_debuglevel(1) 設(shè)置調(diào)試,將輸出打印到控制臺

      • close() 關(guān)閉連接

    • HTTPSConnection(host,port = None) 使用https協(xié)議簡介服務(wù)器,返回一個HTTPSConnection對象

      • 同上
    • HTTPResponse對象

      • read() 讀取響應(yīng)內(nèi)容

      • getheaders() 返回(屬性,值)組成的元組列表

      • getheader(name) 返回屬性為name的值

      • version 返回協(xié)議版本

      • status 返回狀態(tài)碼

    from http.client import *
    
    con = HTTPConnection('www.baidu.com')
    con.set_debuglevel(1)
    con.request('GET','http://www.baidu.com')
    response = con.getresponse()
    print(response.read())
    response.close()
    con.close()
    
  • server HTTP服務(wù)器模塊

    • 服務(wù)器框架,此模塊繼承于socketserver.TCPServer

      • HTTPServer(server_address,RequestHandlerClass )

      • ThreadingHTTPServer(server_address,RequestHandlerClass )

    • 處理HTTP請求類

      • BaseHTTPRequestHandler(request,client_address,server ) 處理http請求的基本類

        • command 請求形式

        • path 請求的url

        • request_version 請求的http版本

        • headers 請求報文的標頭

        • rfile 讀取流

        • wfile 寫入流

        • protocol_version 設(shè)置http版本協(xié)議

          • 默認為HTTP/1.0 短連接

          • HTTP/1.1 持久連接

        • send_response(code, message=None) 將響應(yīng)狀態(tài)碼添加到緩沖區(qū)

        • send_header(keyword, value) 將響應(yīng)頭添加到緩沖區(qū)

        • end_headers() 發(fā)送空行

        • version_string() 返回服務(wù)器軟件的版本號

        • date_time_string() 返回當前時間

        • address_string() 返回呼叫的客戶端地址

      # 使用BaseHTTPRequestHandler創(chuàng)建HTTP服務(wù)器
      from http.server import *
      
      html = '''
      <html>   
          <head>   
              <title>Server</title>   
          </head>   
          <body>   
              hello Python!
          </body>   
      </html>
      '''
      
      class myhttpserver(HTTPServer):
          pass
      
      class myhttphandler(BaseHTTPRequestHandler):
      
          def do_GET(self):
      
              url = self.path
              print(url)
      
              self.send_response(200)
              self.send_header('Hello','from server s welcome')
              self.end_headers()
      
              self.wfile.write(html.encode())
      
      server = myhttpserver(('127.0.0.1',8888),myhttphandler)
      server.serve_forever()
      # 現(xiàn)在使用http://127.0.0.1:8888/打開網(wǎng)站吧
      
      • SimpleHTTPRequestHandler(request,client_address,server,directory = None ) 普通HTTP請求處理類

        • 除了和BaseHTTPRequestHandler函數(shù)一致時,還另外定義了directory屬性,do_HEAD(),do_GET()方法

          • directory 屬性: 如果未指定,則代表提供的文件的目錄是當前目錄

          • do_HEAD() 默認給定Server, Date, Connection, Content-Type, Content-Length, Last-Modified的標頭

          • do_GET() 如果代碼所在位置有index.html,則會發(fā)送這個網(wǎng)頁給客戶端,否則將建立一個基于當前目錄的類似于FTP的服務(wù)器

    # 類似于FTP服務(wù)器
    from http.server import *
    
    class myhttpserver(HTTPServer):
        pass
    
    class myhttphandler(SimpleHTTPRequestHandler):
        pass
    
    server = myhttpserver(('127.0.0.1',8888),myhttphandler)
    server.serve_forever()
    
    # 使用index.html
    # 在代碼所在目錄編寫index.html文件
    '''
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>My Page</title>
    </head>
    <body>
        <h1>Hello Python3!</h1>
    </body>
    </html>
    '''
    # 再次運行服務(wù)器,使用瀏覽器訪問,即可以查看結(jié)果
    
    • CGIHTTPRequestHandler(request,client_address,server ) 調(diào)用CGI程序處理請求

      • 修改了SimpleHTTPRequestHandler定義的do_GET和do_HEAD方法,更改為使用CGI程序輸出的方法 如果沒有CGI程序,就會像SimpleHTTPRequestHandler一樣,建立一個類似于FTP的服務(wù)器

      • cgi_directories 包含CGI程序的目錄,默認為當前目錄下的['/cgi-bin', '/htbin']

      • do_POST() 定義了POST方法,允許客戶端發(fā)送信息到服務(wù)器得CGI程序中,如果POST到非CGI程序上,會提示501錯誤

    # 先定義一個能POST請求的html頁面,命名為index.html
    '''
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>請輸入文字</h1>
        <form action="http://127.0.0.1:8888/cgi-bin/cc.py" method="post" id="myform">
            <p><input type="text" name="text"></p>
        </form>
        <button type="submit" form="myform">發(fā)送</button>
    
    </body>
    </html>
    '''
    
    # CGI服務(wù)器
    from http.server import *
    
    class myhttpserver(HTTPServer):
        pass
    
    class myhttphandler(CGIHTTPRequestHandler):
        pass
    
    server = myhttpserver(('127.0.0.1',8888),myhttphandler)
    server.serve_forever()
    
    # 編寫CGI程序,放入cgi-bin目錄下
    import cgi
    import cgitb
    cgitb.enable()
    
    html = '''
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>你提交的是:</h1>
        <h2>{0}</h2>
    </body>
    </html>
    '''.format(cgi.FieldStorage().getfirst('text'))
    
    print(html)
    # 運行程序,會輸出你在頁面上輸入的信息
    
  • cookies HTTP狀態(tài)管理,主要用于服務(wù)器端創(chuàng)建cookie

    • Netscape形式的cookie : Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE

      • NAME為該cookie的名稱,為必填選項
      • Expires為該cookie的終止日期 形式為星期幾,DD-MM-YY HH:MM:SS GMT,GMT表示格林尼治時間,如不填該cookie不會保存在硬盤中,該cookie隨著瀏覽器的關(guān)閉消失
      • Domain為該cookie的作用域,如果不填,則為該服務(wù)器的域名
      • Path為該服務(wù)器下那些頁面可以獲取該cookie,填'/'為該服務(wù)器下所有頁面
      • 加密協(xié)議,當前只有一種,即HTTPS
    • RFC2109中定義的cookie : Set-Cookie: Name = Value; Comment = value; Domain = value; Max-Age = value; Path = Value;Secure; Version = 1 * DIGIT;

      • NAME必須為一個JSESSIONID,必填
      • Domain為該cookie的作用域,必須以.開始
      • Max-Age為該cookie的生存時間,以秒為單位
      • Secure必填
    • BaseCookie(input) 類

      • 該類用于創(chuàng)建cookie,是一個類似于字典的對象,每向其中添加一個key,value值就會創(chuàng)建一個Set-Cookie: key:value的響應(yīng)頭信息,其中key必須是一個字符串,value是一個Morsel對象,可以向其中添加其他頭信息操作

      • 定義的方法:

        • value_decode(val ) 待續(xù)
        • value_encode(val ) 待續(xù)
        • output(attrs = None,header ='Set-Cookie:',sep ='\ r \ n' ) 將cookie對象作為符合html標準的字符串輸出
        • load(rawdata ) 將接收到的字符串對象解析為cookie
    • SimpleCookie(input) 類

      • BaseCookie的子類,重寫實現(xiàn)了value_decode,value_encode方法
    • Morsel 類

      • 常用常量

        • expires
        • path
        • comment
        • domain
        • max-age
        • secure
        • version
        • httponly
      • 常用方法

        • set(key,value,coded_value ) 添加key,設(shè)置value值
        • output(attrs = None,header ='Set-Cookie:' ) 作為html形式輸出
        • update(dict) 將字典中的key和value添加到對象中
# 創(chuàng)建一個cookie,使用了幾種不同的方式
from http.cookies import *

cookie = SimpleCookie()

cookie["name"] = "mycookie"

dict = {'path':'/','comment':'這是cookie'}
cookie['name'].update(dict)

cookie['name']['domain'] = '127.0.0.1'

cookie['whatever'] = 'i dont know'

print(cookie)

  • cookiejar 持久化的cookie操作模塊,主要用于客戶端的操作,如爬蟲

    • 具體應(yīng)用在urllib模塊中

    • CookieJar 類,該類用來操作儲存在內(nèi)存中的cookie

      • MozillaCookieJar(filename,delayload = None,policy = None ) 類 可以從加載和保存的Cookie到磁盤Mozilla的cookies.txt

      • LWPCookieJar(filename,delayload = None,policy = None ) 類 可以從加載和cookie保存到磁盤與的libwww-perl的庫的兼容格式Set-Cookie3的文件格式

      • add_cookie_header(requst) 向request對象中添加一個cookie對象

      • extract_cookies(response,request) 從http的response中提取cookie并儲存在cookieJar對象中

      • make_cookies(response,request) 從http的response中提取cookie

      • set_cookie(cookie) 向cookieJar添加cookie對象

      • clear(keys) 清除名為key的cookie參數(shù)

      # 獲取cookie
      from urllib.request import *
      from http.cookiejar import *
      
      url = 'http://www.baidu.com'
      headers = {
          'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36'
      }
      request = Request(url=url, headers=headers)
      
      response = urlopen(request)
      
      cookie = CookieJar()
      
      cookie.extract_cookies(response,request)
      
      print(cookie)
      
    • FileCookieJar 類,該類主要用于操作已經(jīng)持久到文件中的cookie

      • 具有以上CookieJar的所有函數(shù)之外,額外添加了以下函數(shù)

      • filename 默認保存cookie的文件

      • save(filename = None,ignore_discard = False,ignore_expires = False ) 將cookie保存在文件中,方法未實現(xiàn),但是在CookieJar的子類LWPCookieJar,MozillaCookieJar實現(xiàn)了其方法

      • load(filename = None,ignore_discard = False,ignore_expires = False ) 從文件中加載cookie

      • revert(filename = None,ignore_discard = False,ignore_expires = False ) 清除所有cookie,并從文件中重新加載cookie

    # 以LWPCookieJar為例,將cookie保存到文件中
    from urllib.request import *
    from http.cookiejar import LWPCookieJar
    
    url = 'http://www.baidu.com'
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36'
    }
    request = Request(url=url, headers=headers)
    
    response = urlopen(request)
    
    filecookie = LWPCookieJar()
    
    filecookie.extract_cookies(response,request)
    
    filecookie.save(r'a.txt')
    

cgi 通用網(wǎng)關(guān)接口支持模塊、cgitb CGI腳本的回溯管理器模塊

cgitb用于調(diào)試cgi腳本程序

  • enable() 將錯誤信息輸出到訪問的html頁面

cgi是服務(wù)器運行時調(diào)用的外部程序,通過通用CGI接口與服務(wù)器通信,默認放在['/cgi-bin', '/htbin']目錄下

  • 通常由兩個部分組成

    • 第一部分為響應(yīng)頭,用于告知客戶端傳輸數(shù)據(jù)的類型,后面跟空行,用于將響應(yīng)體分開
    print("Content-Type: text/html")
    print()
    
    • 第二部分為響應(yīng)的數(shù)據(jù)
  • 常用的頭部信息

    • Content-type: 請求的資源類型對應(yīng)的MIME信息
    • Content-Disposition: disposition-type;filename-parm 響應(yīng)請求資源的下載方式
      • 其中disposition-type可以為attachment 彈出對話框下載,或者inline 直接顯示在頁面上
      • 其中filename-parm是filename = xx 規(guī)定下載時的文件名,用于規(guī)定下載時的文件名稱
    • Expires: 響應(yīng)過期的日期和時間
    • Location: 重定向到url的新的資源
    • Last-modified: 請求資源的最后修改日期
    • Content-length: 請求的內(nèi)容長度
    • Set-Cookie: 設(shè)置cookie
  • 常用方法

    • parse_header(str) 將MIME標頭解析為字典
    • parse_multipart(fp,pdict,encoding =“utf-8”,errors =“replace” ) 返回{字段名稱:數(shù)據(jù)}的字典
    • print_form(form) 將接收的表格以html形式格式化
    • print_directory() 以html形式格式化當前目錄
    • test() 將cgi作為主程序進行測試
  • FieldStorage(,key,filename,value)

    • 此類用于獲取html中form輸出的表單數(shù)據(jù),僅需要實例化一次
    • FiledStorage()[key] 代表了表單中名為key的標簽整體
    • FiledStorage()[key].value 代表了表單中key標簽的值
    • getvalue(key) 當有多個值時,返回一個字符串列表
    • getlist(key) 返回名key標簽下的所有字符串組成的列表
  • 編寫一個最簡單的CGI程序,如果需要訪問該CGI程序,需要先啟動一個CGI服務(wù)器,在前面已經(jīng)學(xué)到過,在HTTPServer中導(dǎo)入CGIHTTPRequestHandler創(chuàng)建一個最簡單的CGI服務(wù)器
import cgi
import cgitb

cgitb.enable()

print("Content-Type: text/html")
print()

html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>My First Python CGI</h1>
</body>
</html>
'''
print(html)
  • CGI獲取客戶端使用GET方式發(fā)送的數(shù)據(jù)

    • 請求的url為http://127.0.0.1:8888/cgi-bin/cc.py?usr=jack&pwd=123456,可以看出,傳遞的數(shù)據(jù)以明文方式出現(xiàn)在url中

    • 傳遞的數(shù)據(jù)包含在請求頭中

    • 在GET方式中,不應(yīng)包含敏感數(shù)據(jù),敏感數(shù)據(jù)應(yīng)使用POST方式發(fā)送

# index.html中的內(nèi)容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>請輸入文字</h1>
    <form action="http://127.0.0.1:8888/cgi-bin/cc.py" method="GET" id="myform">
        <h2>賬戶:<input type="text" name="usr"></h2>
        <h2>密碼:<input type="text" name="pwd"></h2>
        <button type="submit">發(fā)送</button>
    </form>
</body>
</html>

# CGI程序
import cgi
import cgitb

cgitb.enable()

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
usr = form.getvalue('usr')
pwd = form.getvalue('pwd')
html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>獲取到的數(shù)據(jù)是:</h1>
    <p>{0}</p>
    <p>{1}</p>
</body>
</html>
'''.format(usr,pwd)

print(html)
  • POST方式在上面的CGIHTTPRequestHandler中,不多進行贅述

    • POST方式發(fā)送數(shù)據(jù),不會明文出現(xiàn)在url中,會存在于請求體的form-data中,所以相對于GET方式,要安全的多
  • 傳遞checkbox數(shù)據(jù)
# index.html內(nèi)容是
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>請勾選</h1>
    <form action="/cgi-bin/cc.py" method="POST" id="myform">
        <input type="checkbox" name="usr" value="on" > usr
        <input type="checkbox" name="pwd" value="on" > pwd
        <button type="submit">發(fā)送</button>
    </form>
</body>
</html>

# cgi程序
import cgi
import cgitb

cgitb.enable()

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
google = form.getvalue('google')
if google == on:
    r1 = 'google被選中'
else:
    r1 = 'google沒有被選中'
baidu = form.getvalue('baidu')
if baidu == 'on':
    r2 = 'baidu被選中'
else:
    r2 = 'baidu沒有被選中'
html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>獲取到的數(shù)據(jù)是:</h1>
    <p>{0}</p>
    <p>{1}</p>
</body>
</html>
'''.format(r1,r2)

print(html)
  • 傳遞radio數(shù)據(jù)
# index.html中的內(nèi)容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>請勾選</h1>
    <form action="/cgi-bin/cc.py" method="POST" id="myform">
        <input type="radio" name="site" value="google" > 谷歌
        <input type="radio" name="site" value="baidu" > 百度
        <button type="submit">發(fā)送</button>
    </form>
</body>

# cgi程序內(nèi)容
import cgi
import cgitb

cgitb.enable()

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
value = form.getvalue('site')

html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>獲取到的數(shù)據(jù)是:</h1>
    <p>{0}</p>
</body>
</html>
'''.format(value)

print(html)
  • 傳遞Textatrea數(shù)據(jù)
# index.html中的內(nèi)容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>請輸入內(nèi)容</h1>
    <form action="/cgi-bin/cc.py" method="post">
        <Textarea name="text" cols="40" rows="4" >在這里輸入內(nèi)容....
        </Textarea>
        <input type="submit">
    </form>
</body>
</html>

# cgi程序中的內(nèi)容
import cgi
import cgitb

cgitb.enable()

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
value = form.getvalue('text')

html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>獲取到的數(shù)據(jù)是:</h1>
    <p>{0}</p>
</body>
</html>
'''.format(value)

print(html)
  • 傳遞下拉數(shù)據(jù)
# index.html中的內(nèi)容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>請輸入內(nèi)容</h1>
    <form action="/cgi-bin/cc.py" method="post">
        <select name="sel" >
            <option value="baidu">百度</option>
            <option value="google">谷歌</option>
        </select>
        <input type="submit">
    </form>
</body>
</html>

# cgi程序中的內(nèi)容
import cgi
import cgitb

cgitb.enable()

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
value = form.getvalue('sel')

html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>獲取到的數(shù)據(jù)是:</h1>
    <p>{0}</p>
</body>
</html>
'''.format(value)

print(html)
  • 設(shè)置cookie
# 直接訪問cgi程序,設(shè)置cookie,通過chrome即可查看設(shè)置的cookie
# cgi程序為:
import cgi,datetime
import cgitb
from http.cookies import *

cgitb.enable()

name = 'cgicookie'
now = datetime.datetime.utcnow()
time = (now + datetime.timedelta(days=10)).strftime('%a,%d-%m-%Y %H:%M:%S')
path = '/'
domain = '127.0.0.1'
cookie = SimpleCookie()
cookie['NAME'] = name
cookie['NAME']['expires'] = time
cookie['NAME']['path'] = path
cookie['NAME']['domain'] = domain

print("Content-Type: text/html")
print(cookie)
print()

html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>cookie已經(jīng)設(shè)置</h1>
</body>
</html>
'''

print(html)
  • 文件上傳
# index.html中的內(nèi)容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>文件上傳</h1>
    <form action="/cgi-bin/cc.py" method="post" enctype="multipart/form-data">
        <p><input type="file" name="upload"></p>
        <p><input type="submit"></p>
    </form>
</body>
</html>

# cgi程序為:
import cgi
import cgitb

cgitb.enable()

form = cgi.FieldStorage()
file = form['upload']
open(file.filename,'wb').write(file.value)

print("Content-Type: text/html")
print()

html ='''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>已接收上傳文件</h1>
</body>
</html>
'''

print(html)
  • 文件下載
# 直接訪問cgi程序,以下為cgi程序的內(nèi)容
import cgi
import cgitb

cgitb.enable()

data = open(r'chromedriver.exe','rb').read()

print("Content-Disposition: attachment;filename=chromedriver.exe")
print()

print(data)

urlib URL處理模塊

  • url 同一資源定位符

    • 格式: prot_sch://net_loc/path;params?query#frag

      • prot_sch 網(wǎng)絡(luò)協(xié)議

      • net_loc 服務(wù)器所在地址 可進一步分割為多個組件

        • user 用戶名
        • passwd 用戶密碼
        • host 服務(wù)器所在地址或服務(wù)器計算機名稱(必須)
        • port 端口號(默認80)
      • path 文件或者CGI應(yīng)用的路徑

      • params 可選參數(shù)

      • query 連接符(&)分割的鍵值對

      • frag 文檔中的特定錨點

  • request 請求url模塊

    • Request(url,data = None,headers = {}) 類 構(gòu)造一個復(fù)雜的請求對象,可以供urlopen函數(shù)使用

      • full_url 返回請求的url

      • host 返回請求的主機地址

      • method 返回請求的方法

      • add_header(key,value) 添加請求標頭

      • has_header(key) 檢查是否有key請求標頭

      • remove_header(key) 刪除名為key的請求標頭

      • get_header(key) 返回名為key的標頭值

      • header_items() 返回所有請求標頭和值

  • urlopen(url,data) 打開一個url,發(fā)送data,返回HTTPResponse對象

    • 在HTTPResponse的基礎(chǔ)上添加了以下方法

    • geturl() 返回請求資源的url

    • info() 返回頁面的元信息

    • getcode() 返回響應(yīng)的狀態(tài)碼

  • build_opener([handler,]) 返回一個OpenerDirector對象

  • install_opener(OpenerDirector對象) 將OpenerDirector對象設(shè)置為全局默認

  • OpenerDirector 類 該類主要用于通過添加相應(yīng)的Handler構(gòu)建一個自定義的urlopen對象,實現(xiàn)各種不同的訪問需求

    • add_handler(Handler) 添加一個處理行為給OpenerDirector對象

    • open(url) 打開URL,返回HTTPResponse對象

    • error(proto,* args) 給定相應(yīng)的參數(shù)處理錯誤

  • HTTPRedirectHandler 類,重定向處理程序

  • HTTPHandler 類,發(fā)送HTTP請求,可以為GET或POST

  • HTTPSHandler(debuglevel = 0,context = None,check_hostname = None ) 類,發(fā)送HTTPS請求,可以為GET或者POST

  • HTTPBasicAuthHandler(password_mgr = None ) 類,請求時需要賬戶密碼登錄

  • ProxyHandler(proxies = None ) 類,代理請求,需要在實例化的時候添加代理字典

  • ProxyBasicAuthHandler(password_mgr = None ) 類,需要用戶名密碼登錄的代理

  • HTTPCookieProcessor(cookiejar) 類,Cookie處理

  • FileHandler 類,打開文件

  • FTPHandler 類,打開FTP文件

  • HTTPErrorProcessor 類,處理HTTP異常

    • http_response(req,reply) 對于錯誤,返回reply對象

    • https_response(req,reply) 對于錯誤,返回reply對象

  • 密碼管理器對象,用于添加到各項需要認證的處理程序中

    • HTTPPasswordMgr 類,映射數(shù)據(jù)庫,通過(realm, uri) -> (user, password)

      • add_password(realm, uri, user, passwd) 添加相應(yīng)的賬戶,密碼到管理器對象中,realm是指主機服務(wù)器的域信息一般為None,uri指服務(wù)器

      • find_user_password(realm, authuri) 返回指定服務(wù)器域中是否有定義的賬戶,如果有返回(賬戶,密碼)元組,沒有返回None

    • HTTPPasswordMgrWithDefaultRealm

      • 同上兩個方法
    • HTTPPasswordMgrWithPriorAuth

    • 同上兩個方法

    • update_authenticated(self, uri, is_authenticated=False)

    • is_authenticated(self, authuri)

使用默認函數(shù)訪問url

from urllib.request import *

url = 'http://www.baidu.com'
response = urlopen(url)
print(response.read().decode())

使用Request對象構(gòu)造請求

from urllib.request import *

url = 'http://www.baidu.com'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36',
'Host': 'www.baidu.com'
}
request = Request(url,headers=headers)
response = urlopen(request)
print(response.read().decode())

構(gòu)造自定的訪問器,獲取cookie

from urllib.request import *
from http.cookiejar import *

url = 'http://www.baidu.com'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36',
'Host': 'www.baidu.com'
}
cookie = CookieJar()
openr = build_opener(HTTPCookieProcessor(cookie))
request = Request(url,headers=headers)
response = openr.open(request)
print(cookie)
print(response.read().decode())

# 或者

from urllib.request import *
from http.cookiejar import *

url = 'http://www.baidu.com'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36',
'Host': 'www.baidu.com'
}
cookie = CookieJar()
openr = OpenerDirector()
openr.add_handler(HTTPCookieProcessor(cookie))
openr.add_handler(HTTPHandler())
request = Request(url,headers=headers)
response = openr.open(request)
print(cookie)

構(gòu)造自定訪問器,使用用戶名、密碼登錄

from urllib.request import *
from urllib.parse import *

login_url = r'https://www.douban.com/accounts/login'

data = urlencode({
'source': 'index_nav',
'form_email': 'XXXXX',
'form_password': 'XXXXX'
}).encode()

request = Request(url=login_url,data=data)
response = urlopen(request)
print(response.read().decode('utf-8','ignore'))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容