# 导入socket模块,时间模块
import socket # socket模块是python自带的内置模块,不需要我们去下载
import time
# url为: http://images.gaga.me/photos2/2019/0416/5cb5e9950e25a.jpeg?watermark/1/image/aHR0cDovL3Jlcy5nYWdhLm1lL3dhdGVybWFyay9wYWl4aW4xLnBuZz9pbWFnZVZpZXcyLzIvdy80MDAvaC80MDA=/dissolve/50/gravity/Center/ws/1
# ip远程地址为:113.229.252.244
# 端口为:80
# 我们写的请求头如下:
http_req = b'''GET /photos2/2019/0416/5cb5e9950e25a.jpeg?watermark/1/image\
/aHR0cDovL3Jlcy5nYWdhLm1lL3dhdGVybWFyay9wYWl4aW4xLnBuZz9pbWFnZVZpZXcyLzIvdy80MDAvaC80MDA=\
/dissolve/50/gravity/Center/ws/1 HTTP/1.1\r\n\
Host: images.gaga.me\r\n\
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0\r\n\r\n\
'''
# 建立对象
client = socket.socket()
# 连接,通过(ip,端口)来进行连接
client.connect(("113.229.252.244",80))
# 根据请求头来发送请求信息
client.send(http_req)
# 建立一个二进制对象用来存储我们得到的数据
result = b''
i = 0
# 得到响应数据
while True:
# 每次获得的数据不超过1024字节
http_resp = client.recv(1024)
i = i+1
print("这是我们第{}次获得数据,获得的数据长度是{},获得的数据内容为{}.".format(i,len(http_resp),http_resp))
# 将每次获得的每行数据都添加到该对象中
result += http_resp
# 每获取一行数据便休眠一段时间,避免出现下次获得响应数据,因为速度太快,数据还未加载出来导致的我们获取不到数据的问题
time.sleep(0.3)
# 根据判断每一行获取的数据的字节长度来判断是否还存在数据,当该行数据长度等于0时,即已经获取到最后一行数据,终止循环
if len(http_resp) <= 0:
# 关闭浏览器对象
client.close()
# 终止循环
break
# 由于我们获得的响应文件是包括响应头和图片信息两种的,而响应头是以\r\n\r\n来进行结尾的.
# 所以我们想获得图片信息可以以此来分割,又因为响应头是在前面的,所有我们只需要获得第二部分的图片即可
result = result.split(b"\r\n\r\n")[1]
print("我们获得的图片内容为{}.".format(result))
# 打开一个文件,将我们读取到的数据存入进去,即下载到本地我们获取到的图片
with open("可爱的小姐姐.jpg","wb") as f:
f.write(result)
运行后的结果为:
大概步骤为; 1. 访问一个能看到该图片的网址,我访问的是:https://v.paixin.com/photoplus/10787437
2. 在网页中右击该图片,点击查看元素
3. 如果是使用的img标签,我们可以直接获得它的src属性中的值,即为该图片的网络地址,访问该网络地址,我们可以看到跳转到只有这一张图片的一个网页;如果不是使用img标签,则可以查看它的background属性,该属性中url括号中的网络地址即是图片的网络地址,访问该网络地址,我们可以看到跳转到只有这一张图片的一个网页。
4. 本文中获得到的图片的网络地址为:http://images.gaga.me/photos2/2019/0416/5cb5e9950e25a.jpeg?watermark/1/image/aHR0cDovL3Jlcy5nYWdhLm1lL3dhdGVybWFyay9wYWl4aW4xLnBuZz9pbWFnZVZpZXcyLzIvdy80MDAvaC80MDA=/dissolve/50/gravity/Center/ws/1
5. 此时右键图片打开查看元素,点击出现界面的最上面一行中的网络(或者说network),然后刷新该网页,你会发现网络的下面加载出来一堆的东西,一般来说你点击最上面的第一个文件就是你想要的文件。
6. 然后我们就可以获得域名,IP,请求方式,和http版本号,这样我们就可以写出我们的请求头了。
7. 然后建立client对象,通过IP和端口,以及我们写好的请求头,来通过send函数对服务器发送请求
recv函数来获得服务器响应给我们的数据,需要注意的是,该函数每次只能获取一行数据,如果我们想要获取需要获得的全部数据,就需要使用循环了。
9. client.recv(1024)是指,我们每次获得到的数据不得超过1024字节,即如果该行数据小于1024则直接获取,如果多于1024则分多行进行获取,如果该行没有数据了,那么它的字节长度将会是0,我们也可以依据此来进行结束循环的标志。
10. 需要注意的是,我们获得的数据,包括两部分: 响应头和图片数据,我们只需要图片数据,那么我们可以根据\r\n\r\n来使用split函数来进行分割,来仅仅获取图片部分的内容,因为响应头都是以\r\n\r\n来进行结尾的。
11. 然后将我们获得的图片数据以二进制的形式(wb)来写入文件,这样该图片就下载到本地了。
12. socket 套接字: 几乎所有的网络通信的底层都是由套接字实现.
socket 能够为我们创建TCP连接,可以把自己编写好的请求报文发送给服务器了.
socket 对我们爬虫来说默认只能针对HTTP, 而相对于HTTPS的资源, 该模块不行.