美文网首页
Python:网络编程

Python:网络编程

作者: DramaScript | 来源:发表于2018-02-06 20:37 被阅读30次

    在Python中如何实现Http请求?如何实现Scoket连接?以下直接介绍如何使用Python进行网络编程。

    GET与POST请求

    要实现这个功能,需要用到Python的内建模块,就是urllib库。这个库是内置的不需要下载库,可以直接请求,以下直接示例代码演示:

    import urllib
    from urllib import request, parse
    
    # 对链接进行数据的抓取
    with request.urlopen('https://api.douban.com/v2/book/2129650') as f:
        data = f.read()
        print('Status:', f.status, f.reason)
        for k, v in f.getheaders():
            print('%s: %s' % (k, v))
        print('Data:', data.decode('utf-8'))
    
    # 模拟Get请求去请求数据
    req = request.Request('http://www.douban.com/')
    req.add_header('User-Agent',
                   'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
    with request.urlopen(req) as f:
        print('Status:', f.status, f.reason)
        for k, v in f.getheaders():
            print('%s: %s' % (k, v))
        print('Data:', f.read().decode('utf-8'))
    
    # 如果要以POST发送一个请求,只需要把参数data以bytes形式传入。
    print('Login to weibo.cn...')
    email = input('Email: ')
    passwd = input('Password: ')
    login_data = parse.urlencode([
        ('username', email),
        ('password', passwd),
        ('entry', 'mweibo'),
        ('client_id', ''),
        ('savestate', '1'),
        ('ec', ''),
        ('pagerefer', 'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F')
    ])
    
    req = request.Request('https://passport.weibo.cn/sso/login')
    req.add_header('Origin', 'https://passport.weibo.cn')
    req.add_header('User-Agent',
                   'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
    req.add_header('Referer',
                   'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F')
    # 将数据改成byte来传输就是Post请求
    with request.urlopen(req, data=login_data.encode('utf-8')) as f:
        print('Status:', f.status, f.reason)
        for k, v in f.getheaders():
            print('%s: %s' % (k, v))
        print('Data:', f.read().decode('utf-8'))
    
    
    # 如果还需要更复杂的控制,比如通过一个Proxy去访问网站,我们需要利用ProxyHandler来处理,示例代码如下:
    proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
    proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
    proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
    opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
    with opener.open('http://www.example.com/login.html') as f:
        pass
    

    Socket编程

    这个分为两种编程方式,一种是基于TCP编程,一种是基于UDP编程。至于这两种通信的区别这里就不说了,自行问度娘吧。

    TCP编程

    大多数连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。以下实现一个客户端与服务的的示例:

    • 服务端
    import socket
    import threading
    
    import time
    
    # 服务器端,AF_INET表示使用ipv4
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('127.0.0.1', 9999))
    # 设置等待连接的最大数量
    s.listen(5)
    print('Waiting for connection...')
    
    
    def tcplink(sock, addr):
        print('Accept new connection from %s:%s...' % addr)
        sock.send(b'Welcome!')
        # 服务器程序通过一个永久循环来接受来自客户端的连接,accept()会等待并返回一个客户端的连接:
        while True:
            data = sock.recv(1024)
            time.sleep(1)
            if not data or data.decode('utf-8') == 'exit':
                break
            sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
        sock.close()
        print('Connection from %s:%s closed.' % addr)
    
    # 轮询创建接收处理线程
    while True:
        # 接受一个新连接:
        sock, addr = s.accept()
        # 创建新线程来处理TCP连接:
        t = threading.Thread(target=tcplink, args=(sock, addr))
        t.start()
    
    
    • 客户端
    import socket
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 建立连接:
    s.connect(('127.0.0.1', 9999))
    # 接收欢迎消息,每次接收1kb,如果是有不止1k,可以用一个buffer[] 容器装起来,知道recv()接收为空为止算结束
    print(s.recv(1024).decode('utf-8'))
    for data in [b'Michael', b'Tracy', b'Sarah']:
        # 发送数据:
        s.send(data)
        print(s.recv(1024).decode('utf-8'))
    s.send(b'exit')
    s.close()
    
    UDP编程

    使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,能不能到达就不知道了。以下示例分为服务端与客户端示例:

    • 服务端
    import socket
    import threading
    
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 绑定端口:
    s.bind(('127.0.0.1', 9999))
    
    
    def udplink(data, addr):
        # 创建Socket时,SOCK_DGRAM指定了这个Socket的类型是UDP。绑定端口和TCP一样,但是不需要调用listen()方法,而是直接接收来自任何客户端的数据
        print('Bind UDP on 9999...')
        while True:
            print('Received from %s:%s.' % addr)
            # recvfrom()方法返回数据和客户端的地址与端口,这样,服务器收到数据后,直接调用sendto()就可以把数据用UDP发给客户端
            s.sendto(b'Hello, %s!' % data, addr)
    
    
    # 轮询创建接收处理线程
    while True:
        # 接收数据:
        data, addr = s.recvfrom(1024)
        # 创建新线程来处理UDP连接:
        t = threading.Thread(target=udplink, args=(data, addr))
        t.start()
    
    
    • 客户端
    import socket
    
    # 客户端使用UDP时,首先仍然创建基于UDP的Socket,然后,不需要调用connect(),直接通过sendto()给服务器发数据
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    for data in [b'Michael', b'Tracy', b'Sarah']:
        # 发送数据:
        s.sendto(data, ('127.0.0.1', 9999))
        # 接收数据:
        print(s.recv(1024).decode('utf-8'))
    s.close()
    

    相关文章

      网友评论

          本文标题:Python:网络编程

          本文链接:https://www.haomeiwen.com/subject/cpgqzxtx.html