SSLError: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:748)

使用HTTP协议访问需要HTTPS协议访问的网页是,会返回302 Found

表示需要重定向到使用HTTPS访问

socket使用HTTPS需要import ssl模块

import ssl

然后对socket对象进行包装

sock = ssl.wrap_socket(socket.socket())

此时出现错误

SSLError: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:748)

上网查找后发现自己没有修改访问对应的端口号,仍然用80端口号connect服务器,因此出错,需要将端口号改为https服务对应的443

下面为一个简单的通过socket方法实现get请求的代码,输出为访问的网页的response。此代码未根据指定的protocol分配对应端口号,有待修改。

# _*_ coding:utf-8 _*_
import socket
import ssl
"""
2017/02/16
作业 1


资料:
在 Python3 中,bytes 和 str 的互相转换方式是
str.encode('utf-8')
bytes.decode('utf-8')

send 函数的参数和 recv 函数的返回值都是 bytes 类型
其他请参考上课内容, 不懂在群里发问, 不要憋着
"""


# 1
# 补全函数
def protocol_of_url(url):
    '''
    url 是字符串, 可能的值如下
    'g.cn'
    'g.cn/'
    'g.cn:3000'
    'g.cn:3000/search'
    'http://g.cn'
    'https://g.cn'
    'http://g.cn/'

    返回代表协议的字符串, 'http' 或者 'https'
    '''
    parts = url.split('://')
    if len(parts)>1:
        return parts[0]
    else:
        return 'http'


# 2
# 补全函数
def host_of_url(url):
    '''
    url 是字符串, 可能的值如下
    'g.cn'
    'g.cn/'
    'g.cn:3000'
    'g.cn:3000/search'
    'http://g.cn'
    'https://g.cn'
    'http://g.cn/'

    返回代表主机的字符串, 比如 'g.cn'
    '''
    parts = url.split('://')
    if len(parts)>1:
        url = parts[1]
    parts = url.split('/')
    
    url = parts[0]
    
    parts = url.split(':')
    return parts[0]


# 3
# 补全函数
def port_of_url(url):
    '''
    url 是字符串, 可能的值如下
    'g.cn'
    'g.cn/'
    'g.cn:3000'
    'g.cn:3000/search'
    'http://g.cn'
    'https://g.cn'
    'http://g.cn/'

    返回代表端口的字符串, 比如 '80' 或者 '3000'
    注意, 如上课资料所述, 80 是默认端口
    '''
    parts = url.split('://')
    if len(parts)>1:
        url = parts[1]
    parts = url.split('/')
    
    url = parts[0]
    
    parts = url.split(':')
    if len(parts)>1:
        return parts[1]
    else:
        return '443'

# 4
# 补全函数
def path_of_url(url):
    '''
    url 是字符串, 可能的值如下
    'g.cn'
    'g.cn/'
    'g.cn:3000'
    'g.cn:3000/search'
    'http://g.cn'
    'https://g.cn'
    'http://g.cn/'

    返回代表路径的字符串, 比如 '/' 或者 '/search'
    注意, 如上课资料所述, 当没有给出路径的时候, 默认路径是 '/'
    '''
    parts = url.split('://')
    if len(parts)>1:
        url = parts[1]
    parts = url.split('/')
    if len(parts) == 1:
        return '/'
    else:
        return url.replace(parts[0],'')
    



# 4
# 补全函数
def parsed_url(url):
    '''
    url 是字符串, 可能的值如下
    'g.cn'
    'g.cn/'
    'g.cn:3000'
    'g.cn:3000/search'
    'http://g.cn'
    'https://g.cn'
    'http://g.cn/'
    返回一个 tuple, 内容如下 (protocol, host, port, path)
    '''
    protocol = protocol_of_url(url)
    host = host_of_url(url)
    port = port_of_url(url)
    path = path_of_url(url)
    return (protocol, host, port, path)


# 5
# 把向服务器发送 HTTP 请求并且获得数据这个过程封装成函数
# 定义如下
def get(url):
    '''
    本函数使用上课代码 client.py 中的方式使用 socket 连接服务器
    获取服务器返回的数据并返回
    注意, 返回的数据类型为 bytes
    '''
    protocol,host,port,path = parsed_url(url)
    
    sock = ssl.wrap_socket(socket.socket())
    #sock = socket.socket()
    sock.connect((host,int(port)))
     
     
    req = 'GET '+path+' HTTP/1.1\r\nHost: '+host+'\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
   
    print(req)
    sock.send(req.encode('utf-8'))
     
    buffer_size = 1024
    response = ''
    while True:
        temp=sock.recv(buffer_size)
        response = response + temp.decode('utf-8','ignore')
        if len(temp) < buffer_size:
            sock.close()
            break
    return response

# 使用
def main():
    url = 'https://movie.douban.com/top250'
    
    r = get(url)
    print(r)


if __name__ == '__main__':
    main()

 

你可能感兴趣的:(学习过程中出现的问题)