Python 網絡編程

網絡

  • 理論模型,分為七層

    • 物理層
    • 數據鏈路層
    • 傳輸層
    • 會話層
    • 表示層
    • 應用層
  • 實際應用,分為四層

    • 鏈路層
    • 網絡層
    • 傳輸層
    • 應用層
  • IP地址

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

      • 局域網IP,192.168.XXX,XXX

      • 本機本地地址,127.0.0.1

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

  • 端口

    • 設備上每個應用需要與外界通信的地址

    • 范圍是 0-65535

    • 知名端口 0-1023

    • 非知名端口 1024-65535

  • 套接字

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

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

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

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

  • 域名

    • 網絡上計算名,或計算機組的名稱

    • 瀏覽器根據域名來查找對應的IP地址

      • 查找本地hsot文件,檢查是否有對應的IP地址

      • 如果沒有,查找本地DNS服務器.也就是運營商,檢查是否有對應的IP

      • 如果沒有,本地DNS服務器查找根DNS服務器,檢查是否有對應的IP

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

  • DNS 域名服務器系統

    • DNS將域名映射到對應的IP地址

    • DNS查詢

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

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

socket 庫

  • 協議家族

    • 基于文件

      • AF_UNIX 同臺機器進程之間的通行
    • 基于網絡

      • AF__INET IPV4協議

      • AF_INET6 IPV6協議

  • 網絡協議

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

    • SOCK_DGRAM UDP協議 , 無連接的套接字,服務器不斷的監聽某個套接字,從這個套接字獲取或者發送數據,無法確定數據的先后順序,也無法確定對方是否收到消息

  • 直接調用的函數

    • getfqdn(name) 返回name的域名

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

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

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

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

    • 函數

      • 通用函數

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

        • shuntdown() 關閉連接

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

        • settimeout(second) 設置超時時間

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

      • TCP 函數

        • listen() 監聽地址,阻塞式的,不斷循環監聽地址

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

        • send(data) 發送數據

        • sendall(data) 發送所有數據

        • recv(bufsize) 接收TCP指定字節數的數據,一旦超過指定字節,就需要使用循環接收的方式接收完整的數據

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

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

          • 負載長度法,提前告知長度,后根據長度判斷是否跳出接收數據的死循環

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

        # 設置TCP服務器
        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()
        
        # 設置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 函數

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

        • sendto(data,addr) 將data數據發送到指定addr地址

        # 設置UDP服務器
        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()
              
        # 設置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 網絡服務器框架模塊

  • 此模塊提供網絡服務器框架,可以使開發者更加快捷的開發出相應的網絡服務器

  • 服務器server對象

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

      • RequestHandlerClass 處理請求類

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

      • server_bind(addr) 綁定地址

      • serve_forever() 永遠處理請求

      • shutdown() 停止處理請求

      • server_close() 關閉服務器

    • TCPServer (server_address,RequestHandlerClass) 繼承于BaseServer,完善了TCP的相關方法,用于TCP服務器的創建,需要重寫RequestHandlerClass

    # 改寫的上面采用socket庫編寫的TCP服務器
    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的相關方法,用于UDP服務器的創建,需要重寫RequestHandlerClass
    # 服務器端
    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平臺的服務器,

      • UnixStreamServer (server_address,RequestHandlerClass)

      • UnixDatagramServer (server_address,RequestHandlerClass)

    image
  • 擴展功能的Mixin類

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

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

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

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

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

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

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

  • 請求處理類

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

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

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

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

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

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

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

        • self.rfile 可以從此屬性中讀取客戶端發送的數據

        • self.wfile 可以從此屬性中寫入服務器發給客戶端的數據

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

    • StreamRequestHandler TCP處理請求類,是BaseRequestHandler的子類,實現了關于TCP的相關方法,但需要實現handle方法

    • DatagramRequestHandler UDP處理請求類,是BaseRequestHandler的子類,實現了關于UDP的相關方法,但需要實現handle方法

ftplib 模塊

  • FTP (FileTransferProtocal) 文件傳輸協議

  • 用戶

    • Real賬戶 注冊賬戶

    • Guest賬戶 臨時賬戶

    • Anonymous 匿名賬戶

  • 端口

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

    • 20 端口為數據端口

  • FTP(host,usr,passwd)類

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

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

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

    • abort() 中斷傳輸的文件

    • sendcmd(cmd) 向服務器發送字符串命令,并返回響應代碼

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

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

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

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

    • nlst() 返回文件名列表

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

    • rename(old,new) 重命名

    • delete(filename) 刪除文件

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

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

    • mkd(path) 創建新目錄

    • rmd(dirname) 刪除dirname目錄

    • size(file) 返回文件大小

    • quit() 關閉連接

import ftplib

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

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

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

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

con.dir()

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

# 關閉連接
con.close()

email 電子郵件模塊

  • 郵件傳輸模式

    • MUA 客戶端程序

    • MTA (Mail Transfer Agent) 郵件傳輸代理,將發件人的郵件傳輸到發件人郵箱所在的服務器

    • MDA (Mail Delivery Agent) 郵件投遞代理,發件人郵箱所在的服務器將郵件傳輸到收件人郵箱所在的服務器

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

    image
  • 郵件傳輸使用MIME協議(多用途互聯網郵件擴展),即電子郵件需要符合相應的MIME格式,才能進行發送

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

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

    • 標頭屬性

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

    • 消息體為郵件的具體內容

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 構造郵件消息模塊

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

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

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

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

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

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

  • message 郵件消息操作模塊

    • EmailMessage

      • 同下
    • Message

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

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

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

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

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

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

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

  • header 構造郵件標頭模塊

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

    • 郵件標頭可以通過兩種方式進行構造

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

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

    • BytesParser 二進制數據解析類

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

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

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

    • Parser 文本解析類

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

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

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

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

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

    • 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簡單郵件發送協議模塊

  • SMTP 是負責郵件發送的協議

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

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

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

    • login(usr,pwd) 登錄

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

    • quit() 關閉連接

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

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

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

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

    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'
    
    # 構造文本消息郵件
    msg = MIMEMultipart('組合郵件')
    
    # 添加標頭,使之變為郵件
    msg['From'] = 'mine<{0}>'.format(usr)
    msg['To'] ='you<{0}>'.format(to_mail)
    msg['Subject'] = '郵件標題'
    
    # 構造文本
    text = MIMEText('這是一封組合郵件')
    
    # 添加到msg組合消息對象中
    msg.attach(text)
       
    # 構造附件
    data = MIMEApplication(open(file,'rb').read())
    
    # 添加MIME類型
    data.add_header('Content-Type','application/octet-stream')
    
    # 設置附件
    data.add_header('Content-Disposition',"attachment;filename='1.png'")
    
    # 添加到msg組合消息對象中
    msg.attach(data)
    
    # 發送郵件
    with smtplib.SMTP()as con:
    
        # 變為debug模式,輸出信息到控制臺
        con.set_debuglevel(1)
    
        # 連接郵件服務器
        con.connect('smtp.163.com', 25)
    
        # 登錄
        con.login(usr, pwd)
    
        # 發送郵件
        con.sendmail(usr, to_mail, msg.as_string())
    

poplib 郵局協議模塊

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

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

    • set_debuglevel(1) 設置為調試模式

    • stls() 以tls驗證服務器

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

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

    • user(usr) 發送用戶名

    • pass_(pwd) 發送密碼

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

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

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

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

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

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

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

    • quit() 關閉連接

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

    • 方法同上,現在一般使用該類
    import poplib
    import email.header
    
    # 指定連接POP3服務器的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)
    
    # 設置二進制對象
    data = b''
    
    # 將二進制郵件的每一行寫入data中,構建完整的郵件,按每行進行寫入
    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解碼消息中的內容
    content = mail.get_payload(decode=True)
    
    # 按UTF-8解碼內容
    print(content.decode())
    

http 超文本傳輸協議模塊

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

    • HTTP 的默認端口為80

    • HTTPS的默認端口為443

    • 永遠是客戶端先發起請求,然后服務器響應請求

    • 工作模式

      • 建立連接

        • 需要進行三次握手
          • 客戶端發送一個請求給服務端要求建立連接,進入等待狀態(SYN_SEND)
          • 服務端同意連接,發送一個響應給客戶端,進入等待狀態(SYN_SEND)
          • 客戶端接收這個響應,并與之建立連接(ESTABLISHED)
      • 接收數據

      • 結束連接

  • 請求報文 Request

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

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

      • 請求方法

        • POST 向服務器提交數據 改

        • GET 請求數據 查

        • PUT 向服務器上傳數據 增

        • DELETE 請求服務器刪除相應數據 刪

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

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

    • 請求體

  • 響應報文 Response

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

    • 響應行,包括了服務器軟件的版本號,返回的狀態碼和相應短語

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

      • Location 重定向到另一個位置
      • Server 服務器軟件
      • Date 此報文產生的日期
      • Content-Length 響應體的長度
      • Content-Type 聲明發送響應體的類型和編碼
    • 空行

    • 響應體,也就是服務器返回的請求資源

  • client HTTP客戶端模塊模塊

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

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

      • getresponse() 返回服務器相應

      • set_debuglevel(1) 設置調試,將輸出打印到控制臺

      • close() 關閉連接

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

      • 同上
    • HTTPResponse對象

      • read() 讀取響應內容

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

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

      • version 返回協議版本

      • status 返回狀態碼

    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服務器模塊

    • 服務器框架,此模塊繼承于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 設置http版本協議

          • 默認為HTTP/1.0 短連接

          • HTTP/1.1 持久連接

        • send_response(code, message=None) 將響應狀態碼添加到緩沖區

        • send_header(keyword, value) 將響應頭添加到緩沖區

        • end_headers() 發送空行

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

        • date_time_string() 返回當前時間

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

      # 使用BaseHTTPRequestHandler創建HTTP服務器
      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()
      # 現在使用http://127.0.0.1:8888/打開網站吧
      
      • SimpleHTTPRequestHandler(request,client_address,server,directory = None ) 普通HTTP請求處理類

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

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

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

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

    # 類似于FTP服務器
    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>
    '''
    # 再次運行服務器,使用瀏覽器訪問,即可以查看結果
    
    • CGIHTTPRequestHandler(request,client_address,server ) 調用CGI程序處理請求

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

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

      • do_POST() 定義了POST方法,允許客戶端發送信息到服務器得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">發送</button>
    
    </body>
    </html>
    '''
    
    # CGI服務器
    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狀態管理,主要用于服務器端創建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隨著瀏覽器的關閉消失
      • Domain為該cookie的作用域,如果不填,則為該服務器的域名
      • Path為該服務器下那些頁面可以獲取該cookie,填'/'為該服務器下所有頁面
      • 加密協議,當前只有一種,即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) 類

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

      • 定義的方法:

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

      • BaseCookie的子類,重寫實現了value_decode,value_encode方法
    • Morsel 類

      • 常用常量

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

        • set(key,value,coded_value ) 添加key,設置value值
        • output(attrs = None,header ='Set-Cookie:' ) 作為html形式輸出
        • update(dict) 將字典中的key和value添加到對象中
# 創建一個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操作模塊,主要用于客戶端的操作,如爬蟲

    • 具體應用在urllib模塊中

    • CookieJar 類,該類用來操作儲存在內存中的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參數

      # 獲取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 類,該類主要用于操作已經持久到文件中的cookie

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

      • filename 默認保存cookie的文件

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

      • 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 通用網關接口支持模塊、cgitb CGI腳本的回溯管理器模塊

cgitb用于調試cgi腳本程序

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

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

  • 通常由兩個部分組成

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

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

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

    • 此類用于獲取html中form輸出的表單數據,僅需要實例化一次
    • FiledStorage()[key] 代表了表單中名為key的標簽整體
    • FiledStorage()[key].value 代表了表單中key標簽的值
    • getvalue(key) 當有多個值時,返回一個字符串列表
    • getlist(key) 返回名key標簽下的所有字符串組成的列表
  • 編寫一個最簡單的CGI程序,如果需要訪問該CGI程序,需要先啟動一個CGI服務器,在前面已經學到過,在HTTPServer中導入CGIHTTPRequestHandler創建一個最簡單的CGI服務器
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方式發送的數據

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

    • 傳遞的數據包含在請求頭中

    • 在GET方式中,不應包含敏感數據,敏感數據應使用POST方式發送

# 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="GET" id="myform">
        <h2>賬戶:<input type="text" name="usr"></h2>
        <h2>密碼:<input type="text" name="pwd"></h2>
        <button type="submit">發送</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>獲取到的數據是:</h1>
    <p>{0}</p>
    <p>{1}</p>
</body>
</html>
'''.format(usr,pwd)

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

    • POST方式發送數據,不會明文出現在url中,會存在于請求體的form-data中,所以相對于GET方式,要安全的多
  • 傳遞checkbox數據
# index.html內容是
<!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">發送</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>獲取到的數據是:</h1>
    <p>{0}</p>
    <p>{1}</p>
</body>
</html>
'''.format(r1,r2)

print(html)
  • 傳遞radio數據
# index.html中的內容
<!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">發送</button>
    </form>
</body>

# cgi程序內容
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>獲取到的數據是:</h1>
    <p>{0}</p>
</body>
</html>
'''.format(value)

print(html)
  • 傳遞Textatrea數據
# index.html中的內容
<!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">
        <Textarea name="text" cols="40" rows="4" >在這里輸入內容....
        </Textarea>
        <input type="submit">
    </form>
</body>
</html>

# cgi程序中的內容
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>獲取到的數據是:</h1>
    <p>{0}</p>
</body>
</html>
'''.format(value)

print(html)
  • 傳遞下拉數據
# index.html中的內容
<!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">
        <select name="sel" >
            <option value="baidu">百度</option>
            <option value="google">谷歌</option>
        </select>
        <input type="submit">
    </form>
</body>
</html>

# cgi程序中的內容
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>獲取到的數據是:</h1>
    <p>{0}</p>
</body>
</html>
'''.format(value)

print(html)
  • 設置cookie
# 直接訪問cgi程序,設置cookie,通過chrome即可查看設置的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已經設置</h1>
</body>
</html>
'''

print(html)
  • 文件上傳
# index.html中的內容
<!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程序的內容
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 網絡協議

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

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

      • params 可選參數

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

      • frag 文檔中的特定錨點

  • request 請求url模塊

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

      • 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,發送data,返回HTTPResponse對象

    • 在HTTPResponse的基礎上添加了以下方法

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

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

    • getcode() 返回響應的狀態碼

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

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

  • OpenerDirector 類 該類主要用于通過添加相應的Handler構建一個自定義的urlopen對象,實現各種不同的訪問需求

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

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

    • error(proto,* args) 給定相應的參數處理錯誤

  • HTTPRedirectHandler 類,重定向處理程序

  • HTTPHandler 類,發送HTTP請求,可以為GET或POST

  • HTTPSHandler(debuglevel = 0,context = None,check_hostname = None ) 類,發送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 類,映射數據庫,通過(realm, uri) -> (user, password)

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

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

    • HTTPPasswordMgrWithDefaultRealm

      • 同上兩個方法
    • HTTPPasswordMgrWithPriorAuth

    • 同上兩個方法

    • update_authenticated(self, uri, is_authenticated=False)

    • is_authenticated(self, authuri)

使用默認函數訪問url

from urllib.request import *

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

使用Request對象構造請求

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())

構造自定的訪問器,獲取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)

構造自定訪問器,使用用戶名、密碼登錄

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'))

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容

  • Python 面向對象Python從設計之初就已經是一門面向對象的語言,正因為如此,在Python中創建一個類和對...
    順毛閱讀 4,231評論 4 16
  • 要說python優雅在何處,與其他語言相比最為明顯的,那一定是網絡操作了。python可以讓我們用最少的語句寫出功...
    zhile_doing閱讀 3,495評論 1 10
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,776評論 18 139
  • python****網絡編程常用庫使用手冊 一、urllib3 ** Urllib3****是一個功能強大,條理清...
    奕劍聽雨閱讀 224評論 0 0
  • 2018年7月31日 星期二 雨 我是韶憶,日記星球417 號星寶寶,我正在參加日記星球第十九期蛻變之旅,這是我的...
    韶憶_d45a閱讀 765評論 0 0