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

目录

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有更深的理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android使用Socket进行图片互传的实例可以按照以下步骤进行: 1. 在发送端(Client端)中,首先创建一个Socket对象,并指定服务器的IP地址和端口号。 2. 创建一个用于获取图片的输入流,并将图片数据读取到内存中。 3. 通过Socket的输出流将图片数据发送给服务器。 4. 在接收端(Server端)中,创建一个ServerSocket对象,并指定监听的端口号。 5. 循环等待客户端的连接请求,当有客户端连接时,接受到客户端的Socket对象。 6. 创建一个用于接收图片的输出流,将从客户端接收到的图片数据写入到指定文件中。 7. 当图片数据传输完成后,关闭Socket和ServerSocket对象。 具体的代码实现如下所示: 发送端: ```java try { // 创建客户端Socket,指定服务器IP地址和端口号 Socket clientSocket = new Socket("服务器IP地址", 端口号); // 获取图片文件的输入流 InputStream inputStream = new FileInputStream("图片文件路径"); // 创建Socket的输出流 OutputStream outputStream = clientSocket.getOutputStream(); // 定义一个字节数组用于保存图片数据 byte[] buffer = new byte[1024]; int len; // 从输入流中读取图片数据并发送给服务器 while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } // 关闭输入流、输出流和Socket连接 inputStream.close(); outputStream.close(); clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } ``` 接收端: ```java try { // 创建服务器端的ServerSocket,指定监听端口号 ServerSocket serverSocket = new ServerSocket(端口号); // 等待客户端的连接请求 Socket clientSocket = serverSocket.accept(); // 创建用于接收图片的输出流 OutputStream outputStream = new FileOutputStream("保存图片的路径"); // 获取客户端Socket的输入流 InputStream inputStream = clientSocket.getInputStream(); // 定义一个字节数组用于保存图片数据 byte[] buffer = new byte[1024]; int len; // 从输入流中读取图片数据并写入到文件中 while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } // 关闭输入流、输出流和Socket连接 inputStream.close(); outputStream.close(); clientSocket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } ``` 以上就是使用Socket进行Android图片互传的简单示例。你可以根据实际需求,在发送端和接收端的代码中做相应的修改和扩展。 ### 回答2: Android使用Socket进行图片互传是一种常见的网络通信方式。下面以客户端和服务器端的实例介绍其具体使用方法。 服务端: 1. 创建一个服务器端的Socket对象,并指定监听的端口号。 2. 使用ServerSocket的accept()方法监听客户端连接请求,并获取客户端的Socket对象。 3. 通过InputStream读取客户端发来的图片数据。 4. 将接收到的图片数据保存到本地。 客户端: 1. 创建一个客户端的Socket对象,并指定服务端的IP地址和端口号。 2. 使用OutputStream发送图片数据到服务器端。 3. 关闭Socket。 以上是一个简单的图片传输的示例,具体的实现过程中还可以增加异常处理和代码优化。另外,图片的传输还可以使用HTTP协议,通过在请求头中添加Content-Type字段来传输图片。在服务端,可以使用HTTP服务器框架如Spring Boot等来接收和处理请求,并将图片保存到本地。 总结:使用Socket进行图片互传是一种基于TCP/IP协议的通信方式,通过在服务端和客户端之间建立Socket连接,并传输图片数据实现互传功能。在具体的实现过程中,要注意代码的健壮性和异常处理,以确保通信的稳定和准确。 ### 回答3: android使用socket进行图片互传实例的步骤如下: 1. 创建一个Socket服务器端和一个Socket客户端,通过TCP连接两者之间的通信。 2. 服务器端创建一个ServerSocket来监听客户端的连接请求。 3. 当客户端连接至服务器时,服务器端接受该连接并创建一个Socket对象。 4. 服务器端读取图片文件,并将其转换为字节数组。 5. 服务器端使用Socket的输出流将字节数组发送给客户端。 6. 客户端接收到服务器端发送的字节数组,将其转换为图片文件。 7. 客户端保存接收到的图片文件,并在界面上显示出来。 以下是一个简单的Android使用Socket进行图片互传的示例代码: 服务器端代码: ``` try { // 创建ServerSocket监听指定端口 ServerSocket serverSocket = new ServerSocket(8888); // 等待客户端连接 Socket socket = serverSocket.accept(); // 读取图片文件并转换为字节数组 File file = new File("/path/to/image.jpg"); FileInputStream fileInputStream = new FileInputStream(file); byte[] buffer = new byte[(int) file.length()]; fileInputStream.read(buffer); // 发送字节数组给客户端 OutputStream outputStream = socket.getOutputStream(); outputStream.write(buffer); // 关闭连接 outputStream.flush(); outputStream.close(); fileInputStream.close(); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } ``` 客户端代码: ``` try { // 创建与服务器连接的Socket Socket socket = new Socket("服务器IP地址", 8888); // 读取字节数组并转换为图片文件 InputStream inputStream = socket.getInputStream(); byte[] buffer = new byte[1024]; int bytesRead; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); while ((bytesRead = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, bytesRead); } byte[] imageBytes = byteArrayOutputStream.toByteArray(); // 将字节数组转换为图片文件并保存 Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); File file = new File("/path/to/save/image.jpg"); FileOutputStream fileOutputStream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream); // 关闭连接 fileOutputStream.close(); inputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } ``` 以上是一个基本的Android使用Socket进行图片互传的示例。通过服务器端将图片转换为字节数组并发送给客户端,客户端接收到字节数组后将其转换为图片文件并保存。具体实现可根据项目需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值