47、Python互联网应用编程指南

Python互联网应用编程指南

1. ftplib模块

ftplib模块实现了FTP协议的客户端功能。虽然urllib包提供了更高级的接口,使得直接使用ftplib的情况较少,但如果需要对FTP连接的底层细节进行更多控制,该模块仍然很有用。使用该模块前,了解Internet RFC 959中描述的FTP协议细节会有所帮助。

  • 建立FTP连接 :使用 FTP 类创建FTP连接对象。
FTP([host [, user [, passwd [, acct [, timeout]]]]])
- `host`:指定主机名的字符串。
- `user`、`passwd`、`acct`:可选参数,分别指定用户名、密码和账户。
- `timeout`:超时时间(秒)。
  • FTP对象方法
    | 方法 | 描述 |
    | — | — |
    | f.abort() | 尝试中止正在进行的文件传输 |
    | f.close() | 关闭FTP连接 |
    | f.connect(host [, port [, timeout]]) | 打开到指定主机和端口的FTP连接 |
    | f.cwd(pathname) | 更改服务器上的当前工作目录 |
    | f.delete(filename) | 从服务器上删除文件 |
    | f.dir([dirname [, ... [, callback]]]) | 生成目录列表 |
    | f.login([user, [passwd [, acct]]]) | 使用指定的用户名、密码和账户登录服务器 |
    | f.mkd(pathname) | 在服务器上创建新目录 |
    | f.ntransfercmd(command [, rest]) | 与 transfercmd() 类似,但返回一个元组 (sock, size) |
    | f.pwd() | 返回服务器上的当前工作目录 |
    | f.quit() | 发送 QUIT 命令关闭FTP连接 |
    | f.rename(oldname,newname) | 重命名服务器上的文件 |
    | f.retrbinary(command, callback [, blocksize [, rest]]) | 使用二进制传输模式执行命令并返回结果 |
    | f.retrlines(command [, callback]) | 使用文本传输模式执行命令并返回结果 |
    | f.rmd(pathname) | 从服务器上删除目录 |
    | f.sendcmd(command) | 向服务器发送简单命令并返回响应 |
    | f.set_pasv(pasv) | 设置被动模式 |
    | f.size(filename) | 返回文件的大小(字节) |
    | f.storbinary(command, file [, blocksize]) | 使用二进制传输模式执行命令并传输数据 |
    | f.storlines(command, file) | 使用文本传输模式执行命令并传输数据 |
    | f.transfercmd(command [, rest]) | 启动FTP数据连接上的传输 |

  • 示例:上传文件到FTP服务器

host     = "ftp.foo.com"
username = "dave"
password = "1235"
filename = "somefile.dat"
import ftplib
ftp_serv = ftplib.FTP(host,username,password)
# Open the file you want to send
f = open(filename,"rb")
# Send it to the FTP server
resp = ftp_serv.storbinary("STOR "+filename, f)
# Close the connection
ftp_serv.close
  • 示例:从FTP服务器获取文档
try:
    from urllib.request import urlopen   # Python 3
except ImportError:
    from urllib2 import urlopen          # Python 2
u = urlopen("ftp://username:password@somehostname/somefile")
contents = u.read()
2. http包

http包包含用于编写HTTP客户端和服务器的模块,以及对状态管理(cookie)的支持。HTTP是一种基于文本的简单协议,其工作流程如下:

graph LR
    A[客户端] --> B[连接到HTTP服务器]
    B --> C[发送请求头]
    C --> D[服务器处理请求]
    D --> E[发送响应]
    E --> A[客户端接收响应]
  • 常见请求方法
    | 方法 | 描述 |
    | — | — |
    | GET | 获取文档 |
    | POST | 向表单提交数据 |
    | HEAD | 仅返回头部信息 |
    | PUT | 上传数据到服务器 |

  • 常见响应代码
    | 代码 | 描述 | 符号常量 |
    | — | — | — |
    | 成功代码 (2xx) | | |
    | 200 | OK | OK |
    | 201 | Created | CREATED |
    | 202 | Accepted | ACCEPTED |
    | 204 | No content | NO_CONTENT |
    | 重定向 (3xx) | | |
    | 300 | Multiple choices | MULTIPLE_CHOICES |
    | 301 | Moved permanently | MOVED_PERMANENTLY |
    | 302 | Moved temporarily | MOVED_TEMPORARILY |
    | 303 | Not modified | NOT_MODIFIED |
    | 客户端错误 (4xx) | | |
    | 400 | Bad request | BAD_REQUEST |
    | 401 | Unauthorized | UNAUTHORIZED |
    | 403 | Forbidden | FORBIDDEN |
    | 404 | Not found | NOT_FOUND |
    | 服务器错误 (5xx) | | |
    | 500 | Internal server error | INTERNAL_SERVER_ERROR |
    | 501 | Not implemented | NOT_IMPLEMENTED |
    | 502 | Bad gateway | BAD_GATEWAY |
    | 503 | Service unavailable | SERVICE_UNAVAILABLE |

3. http.client模块

http.client模块为HTTP客户端提供了底层支持。在Python 2中,该模块名为httplib。通常建议使用urllib包,但在某些情况下,可能需要处理底层细节。

  • 建立HTTP连接

    • HTTPConnection(host [,port]) :创建HTTP连接,默认端口为80。
    • HTTPSConnection(host [, port [, key_file=kfile [, cert_file=cfile ]]]) :创建使用安全套接字的HTTP连接,默认端口为443。
  • HTTPConnection或HTTPSConnection实例方法
    | 方法 | 描述 |
    | — | — |
    | h.connect() | 初始化连接 |
    | h.close() | 关闭连接 |
    | h.send(bytes) | 向服务器发送字节字符串 |
    | h.putrequest(method, selector [, skip_host [, skip_accept_encoding]]) | 向服务器发送请求 |
    | h.putheader(header, value, ...) | 向服务器发送RFC - 822风格的头部 |
    | h.endheaders() | 发送空白行表示头部结束 |
    | h.request(method, url [, body [, headers]]) | 向服务器发送完整的HTTP请求 |
    | h.getresponse() | 获取服务器响应 |

  • HTTPResponse实例方法和属性

    • 方法
      • r.read([size]) :从服务器读取最多 size 字节的数据。
      • r.getheader(name [,default]) :获取响应头部。
      • r.getheaders() :返回头部元组列表。
    • 属性
      • r.version :服务器使用的HTTP版本。
      • r.status :服务器返回的HTTP状态码。
      • r.reason :服务器返回的HTTP错误消息。
      • r.length :响应中剩余的字节数。
  • 异常
    | 异常 | 描述 |
    | — | — |
    | HTTPException | 所有HTTP相关错误的基类 |
    | NotConnected | 请求已发出但未连接 |
    | InvalidURL | 错误的URL或端口号 |
    | UnknownProtocol | 未知的HTTP协议号 |
    | UnknownTransferEncoding | 未知的传输编码 |
    | UnimplementedFileMode | 未实现的文件模式 |
    | IncompleteRead | 接收的数据不完整 |
    | BadStatusLine | 收到未知的状态码 |
    | ImproperConnectionState | 所有HTTP连接状态错误的基类 |
    | CannotSendRequest | 无法发送请求 |
    | CannotSendHeader | 无法发送头部 |
    | ResponseNotReady | 无法读取响应 |

  • 示例:使用HTTPConnection进行文件上传

import os
try:
    from httplib import HTTPConnection      # Python 2
except ImportError:
    from http.client import HTTPConnection  # Python 3
BOUNDARY = "$Python-Essential-Reference$"
CRLF     = '\r\n'
def upload(addr, url, formfields, filefields):
    # Create the sections for form fields
    formsections = []
    for name in formfields:
        section = [
            '--'+BOUNDARY,
            'Content-disposition: form-data; name="%s"' % name,
            '',
            formfields[name]
        ]
        formsections.append(CRLF.join(section)+CRLF)
    # Collect information about all of the files to be uploaded
    fileinfo = [(os.path.getsize(filename), formname, filename)
                for formname, filename in filefields.items()]
    # Create the HTTP headers for each file
    filebytes = 0
    fileheaders = []
    for filesize, formname,filename in fileinfo:
        headers = [
            '--'+BOUNDARY,
            'Content-Disposition: form-data; name="%s"; filename="%s"' % \
            (formname, filename),
            'Content-length: %d' % filesize,
            ''
        ]
        fileheaders.append(CRLF.join(headers)+CRLF)
        filebytes += filesize
    # Closing marker
    closing = "--"+BOUNDARY+"--\r\n"
    # Determine the entire length of the request
    content_size = (sum(len(f) for f in  formsections) + 
                    sum(len(f) for f in  fileheaders) + 
                    filebytes+len(closing))
    # Upload it
    conn = HTTPConnection(*addr)
    conn.putrequest("POST",url)
    conn.putheader("Content-type", 'multipart/form-data; boundary=%s' % BOUNDARY)
    conn.putheader("Content-length", str(content_size))
    conn.endheaders()
    # Send all form sections
    for s in formsections:
        conn.send(s.encode('latin-1'))
    # Send all files
    for head,filename in zip(fileheaders,filefields.values()):
        conn.send(head.encode('latin-1'))
        f = open(filename,"rb")
        while True:
            chunk = f.read(16384)
            if not chunk: break
            conn.send(chunk)
        f.close()
    conn.send(closing.encode('latin-1'))
    r = conn.getresponse()
    responsedata = r.read()
    conn.close()
    return responsedata
# Sample: Upload some files.  The form fields 'name', 'email'
# 'file_1','file_2', and so forth are what the remote server
# is expecting (obviously this will vary).
server      = ('localhost', 8080)
url         = '/cgi-bin/upload.py'
formfields = {
    'name' : 'Dave',
    'email' : 'dave@dabeaz.com'
}
filefields = {
    'file_1' : 'IMG_1008.JPG',
    'file_2' : 'IMG_1757.JPG'
}
resp = upload(server, url,formfields,filefields)
print(resp)
4. http.server模块

http.server模块提供了用于实现HTTP服务器的各种类。在Python 2中,该模块的内容分布在BaseHTTPServer、CGIHTTPServer和SimpleHTTPServer三个库模块中。

  • HTTPServer类 :实现基本的HTTP服务器。
HTTPServer(server_address, request_handler)
- `server_address`:一个元组`(host, port)`,服务器将监听该地址。
- `request_handler`:一个继承自`BaseHTTPRequestHandler`的处理类。

示例:定义一个多线程HTTP服务器,只接受特定子网的连接。
try:
    from http.server import HTTPServer         # Python 3
    from socketserver import ThreadingMixIn
except ImportError:
    from BaseHTTPServer import HTTPServer      # Python 2
    from SocketServer import ThreadingMixIn

class MyHTTPServer(ThreadingMixIn,HTTPServer):
    def __init__(self,addr,handler,subnet):
        HTTPServer.__init__(self,addr,handler)
        self.subnet = subnet

    def verify_request(self, request, client_address):
        host, port = client_address
        if not host.startswith(subnet):
            return False
        return HTTPServer.verify_request(self,request,client_address)

# Example of how the server runs
serv = MyHTTPServer(('',8080), SomeHandler, '192.168.69.')
serv.serve_forever()
  • 预建的处理类

    • CGIHTTPRequestHandler :从当前目录及其子目录提供文件服务。如果文件位于特殊的CGI目录(默认是 /cgi-bin /htbin ),则将其作为CGI脚本运行。支持 GET HEAD POST 方法,但不支持HTTP重定向。
    • SimpleHTTPRequestHandler :从当前目录及其子目录提供文件服务。支持 HEAD GET 请求。

    这两个处理类定义了以下可通过继承更改的类变量:
    | 变量 | 描述 |
    | — | — |
    | handler.server_version | 返回给客户端的服务器版本字符串 |
    | handler.extensions_map | 后缀到MIME类型的映射 |

    示例:使用 CGIHTTPRequestHandler 启动一个独立的Web服务器。

try:
    from http.server import HTTPServer, CGIHTTPRequestHandler  # Python 3
except ImportError:
    from BaseHTTPServer import HTTPServer             # Python 2
    from CGIHTTPServer import CGIHTTPRequestHandler
import os

# Change to the document root
os.chdir("/home/httpd/html")

# Start the CGIHTTP server on port 8080
serv = HTTPServer(("",8080),CGIHTTPRequestHandler)
serv.serve_forever()
  • BaseHTTPRequestHandler类 :用于定义自定义HTTP服务器处理的基类。
BaseHTTPRequestHandler(request, client_address, server)
- 类变量:
    - `server_version`:服务器报告给客户端的软件版本字符串。
    - `sys_version`:Python系统版本。
    - `error_message_format`:用于构建发送给客户端的错误消息的格式字符串。
    - `protocol_version`:响应中使用的HTTP协议版本。
    - `responses`:整数HTTP错误代码到描述问题的二元组`(message, explain)`的映射。

- 实例属性:
    | 属性 | 描述 |
    | --- | --- |
    | `b.client_address` | 客户端地址,元组`(host, port)` |
    | `b.command` | 请求类型,如`GET`、`POST`等 |
    | `b.path` | 请求路径,如`/index.html` |
    | `b.request_version` | 请求中的HTTP版本字符串 |
    | `b.headers` | HTTP头部,存储在映射对象中 |
    | `b.rfile` | 用于读取可选输入数据的输入流 |
    | `b.wfile` | 用于向客户端写响应的输出流 |

- 常用方法:
    | 方法 | 描述 |
    | --- | --- |
    | `b.send_error(code [, message])` | 发送不成功请求的响应 |
    | `b.send_response(code [, message])` | 发送成功请求的响应 |
    | `b.send_header(keyword, value)` | 向输出流写入MIME头部条目 |
    | `b.end_headers()` | 发送空白行表示MIME头部结束 |
    | `b.log_request([code [, size]])` | 记录成功请求 |
    | `b.log_error(format, ...)` | 记录错误消息 |
    | `b.log_message(format, ...)` | 向`sys.stderr`记录任意消息 |

示例:创建一个自定义HTTP服务器,在单独的线程中运行,监控字典内容。
try:
    from http.server import BaseHTTPRequestHandler, HTTPServer      # Py 3
except ImportError:
    from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer   # Py 2

class DictRequestHandler(BaseHTTPRequestHandler):
    def __init__(self,thedict,*args,**kwargs):
        self.thedict = thedict
        BaseHTTPRequestHandler.__init__(self,*args,**kwargs)

    def do_GET(self):
        key = self.path[1:]       # Strip the leading '/'
        if not key in self.thedict:
            self.send_error(404, "No such key")
        else:
            self.send_response(200)
            self.send_header('content-type','text/plain')
            self.end_headers()
            resp  = "Key  : %s\n" % key
            resp += "Value: %s\n" % self.thedict[key]
            self.wfile.write(resp.encode('latin-1'))

# Example use
d = {
    'name' : 'Dave',
    'values' : [1,2,3,4,5],
    'email' : 'dave@dabeaz.com'
}
from functools import partial
serv = HTTPServer(("",9000), partial(DictRequestHandler,d))
import threading
d_mon = threading.Thread(target=serv.serve_forever)
d_mon.start()
5. http.cookies模块

http.cookies模块为处理HTTP cookie提供服务器端支持。在Python 2中,该模块名为 Cookie

  • Cookie的基本概念 :Cookie用于在实现会话、用户登录等功能的服务器中进行状态管理。服务器通过在HTTP响应中添加类似以下的头部来设置Cookie:
Set-Cookie: session=8273612; expires=Sun, 18-Feb-2001 15:00:00 GMT; path=/; domain=foo.bar.com
  • SimpleCookie类
SimpleCookie([input])
- 方法:
    | 方法 | 描述 |
    | --- | --- |
    | `c.output([attrs [,header [,sep]]])` | 生成适合在HTTP头部设置Cookie值的字符串 |
    | `c.js_output([attrs])` | 生成包含JavaScript代码的字符串,在支持JavaScript的浏览器上执行时设置Cookie |
    | `c.load(rawdata)` | 使用`rawdata`中的数据加载Cookie |

- `Morsel`类实例的方法和属性:
    | 方法/属性 | 描述 |
    | --- | --- |
    | `m.value` | 包含Cookie原始值的字符串 |
    | `m.coded_value` | 包含将发送到或从浏览器接收的编码后的Cookie值的字符串 |
    | `m.key` | Cookie名称 |
    | `m.set(key,value,coded_value)` | 设置`m.key`、`m.value`和`m.coded_value`的值 |
    | `m.isReservedKey(k)` | 测试`k`是否为保留关键字 |
    | `m.output([attrs [,header]])` | 生成此Cookie的HTTP头部字符串 |
    | `m.js_output([attrs])` | 输出执行时设置Cookie的JavaScript代码 |

示例:创建和使用Cookie。
c = SimpleCookie()
c["session"] = 8273612
c["user"] = "beazley"
c["session"]["path"] = "/"
c["session"]["domain"] = "foo.bar.com"
c["session"]["expires"] = "18-Feb-2001 15:00:00 GMT"
print(c.output())

# 从环境变量中恢复Cookie值
import os
c = SimpleCookie(os.environ["HTTP_COOKIE"])
session = c["session"].value
user    = c["user"].value

综上所述,Python提供了丰富的模块和类来处理FTP和HTTP协议,无论是客户端还是服务器端的开发,都能找到合适的工具。通过这些工具,开发者可以轻松实现文件上传、下载、状态管理等功能。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值