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