使用socket进行底层请求爬取图片

文章介绍了如何使用socket进行HTTP请求,包括请求的组成部分,并通过示例代码展示了如何使用socket下载HTTP和HTTPS类型的图片。同时,提到了HTTPS的443端口与TLS/SSL加密通信的关系,以及在必要时如何处理HTTPS连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. HTTP请求

2.那什么是socket呢?

 3.使用socket下载图片


在正式讲解实战之前,还得进行一波理论了解,这样才能事半功倍。

1. HTTP请求

首先我们先了解http(https)的请求形式。
请求由客户端向服务端发出,可以分为 4 部分内容:请求方法(Request Method)、请求的网址 (Request URL)、请求头(Request Headers)、请求体(Request Body)

 那么我们该如何构造请求呢?这时候我们就要使用socket了(当然requests请求是最方便的,因为它进行了底层封装)。

2.那什么是socket呢?

默认大家都了解过socket,这里就不加赘述了。当然如果不了解的话,下面也有参考文章帮助大家了解。

参考:socket编程入门:1天玩转socket通信技术(非常详细)

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

三次握手 四次挥手参考: 三次握手和四次挥手知识总结(超详细)-云社区-华为云 (huaweicloud.com)

如下图

方法描述
connect( (host,port) )host代表服务器主机名或IP,port代表服务器进程所绑定的端口号。
send发送请求信息
recv接收数据

 3.使用sockt下载http类型图片

代码如下:

import socket
import re

# 获取到资源地址
url = 'http://image11.m1905.cn/uploadfile/2021/0922/thumb_0_647_500_20210922030733993182.jpg'
# 创建套接字对象
client = socket.socket()
# 创建连接
client.connect(('image11.m1905.cn', 80)) #http默认是80端口,https默认是443端口
# 构造http请求
http_res = 'GET ' + url + ' HTTP/1.0\r\nHost: image11.m1905.cn\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\r\n\r\n'
# 发送请求
client.send(http_res.encode())
# 建立一个二进制对象用来存储我们得到的数据
result = b''
data = client.recv(1024)
# 循环接收响应数据 添加到bytes类型
while data:
    result += data
    data = client.recv(1024)
print(result)
# 提取数据
# re.S使 . 匹配包括换行在内的所有字符 去掉响应头
images = re.findall(b'\r\n\r\n(.*)', result, re.S) #返回一个列表
# print(images[0])
# 打开一个文件,将我们读取到的数据存入进去,即下载到本地我们获取到的图片
with open('小姐姐.png', 'wb')as f:
    f.write(images[0])
client.close() #关闭套接字

其中\r是回车符,\n是换行符。

效果图如下:

 

如果你对HTTP不同版本的协议不清楚,可以参考我的一篇文章。HTTP详解_落花为谁的博客-CSDN博客

注意:HTTP1.0和HTTP1.1协议都支持长连接(Keep-Alive)。在HTTP1.0中,需要在请求头中添加"Connection: keep-alive"字段才能够启用长连接。而在HTTP1.1中,默认启用长连接,也就是说,当客户端发送一个请求后,TCP连接不会立即关闭,而是保持连接状态等待服务器响应。如果客户端想要关闭连接,则需要在HTTP请求报文头部中添加"Connection: close"字段。这样,在服务器发送完响应后,TCP连接会被关闭,客户端就知道响应已经完成了,可以继续发送下一个请求。但是,关闭连接意味着需要重新建立连接,这会对性能产生一定影响。

 4.使用socket下载https类型图片

 代码如下:

import socket
import re


class GetImage:
    def __init__(self):
        pass

    def main(self, url):
        # 创建套接字对象
        client = socket.socket()  # 默认TCP
        # 创建连接
        client.connect(('pic.netbian.com', 80)) 

        # 构造https请求
        http_res = 'GET ' + url + ' HTTP/1.0\r\nHost: pic.netbian.com\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36\r\n\r\n'
        client.send(http_res.encode())
        result = b''
        data = client.recv(1024)
        while data:
            result += data
            data = client.recv(1024)

        # 提取数据
        # re.S使 . 匹配包括换行在内的所有字符 去掉响应头
        image = re.findall(b'\r\n\r\n(.*)', result, re.S)
        filename = url.split('/')[-1]
        # 保存数据
        with open(filename, 'wb') as f:
            f.write(image[0])

        # 关闭套接字
        client.close()


if __name__ == '__main__':
   url_list = ['https://pic.netbian.com/uploads/allimg/230327/194745-16799176658fd9.jpg',
                'https://pic.netbian.com/uploads/allimg/230303/004437-1677775477ee49.jpg',
                'https://pic.netbian.com/uploads/allimg/230411/225955-16812251959808.jpg'
                ]
    getimage = GetImage()
    for url in url_list:
        getimage.main(url)

成功下载

 相信大家已经注意到了,这次我们请求的是https类型图片,但是我们用的还是80端口,不应该用443端口吗,这是为什么呢?

注意:https是兼容http80端口的,所以使用80端口,你会发现是可以正常获取数据的,但是如果直接使用443端口,反而会报错。大家可以自行尝试。

 

这是为什么呢?

因为https需要使用TLS/SSL进行加密通信。因此我们如果一定要使用443端口,可以采取以下办法。

导入ssl包就可正常解决了,具体如下:

import ssl
# 创建套接字对象
client = socket.socket()  # 默认TCP
 # 创建SSL上下文
ssl_context = ssl.create_default_context()
# 建立加密连接
client = ssl_context.wrap_socket(client, server_hostname='pic.netbian.com')
# 连接服务器
client.connect(('pic.netbian.com', 443))

只要加上上述代码,剩下的都是相同的代码逻辑,就可以正常获取到图片了。

拓展:

TLS(Transport Layer Security)SSL(Secure Sockets Layer)是用于保护网络通信安全的协议。TLS是SSL的继任者,TLS和SSL都是在传输层(Transport Layer)提供安全性,用于保护数据在网络中的传输过程中不被窃听、篡改或伪造。

TLS/SSL协议基于公钥加密、私钥解密和数字签名技术,使用 X.509 数字证书进行身份验证和密钥交换,同时还支持对数据进行完整性验证和加密。在TLS/SSL协议下,客户端和服务器之间的通信会被加密并且数据传输是安全的。

TLS/SSL协议广泛应用于Web上的数据传输,如网银交易、电子邮件、在线购物等场景。常见的使用TLS/SSL的应用程序包括HTTPS、FTP、SMTP、POP3等。

需要注意的是,TLS和SSL虽然是不同的协议,但是它们的目标和设计原理基本相同,所以在实际应用中常常被一起提及。

今天的分享就到此,希望能够让你对socket有更深的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值