Python爬虫——使用socket模块进行图片下载

news2024/11/20 14:33:01

Python爬虫——使用socket模块进行图片下载

  • 什么是socket
  • 爬虫的工作流程
  • socket爬取图片
    • 为什么能用socket能下载图片
    • socket下载图片和request下载图片的区别
    • 使用socket下载一张图片
    • 使用socket下载多张图片
      • 方法1
      • 方法2

什么是socket

Socket 是一种通信机制,用于实现网络上的进程间通信。它是一种应用层协议,通常基于 TCP/IP 协议栈,可以在不同的计算机之间进行通信。Socket 本质上是一个文件描述符,它提供了一组用于网络通信的 API 接口,可以进行数据传输、建立连接、监听端口等操作。

使用 Socket 可以实现不同计算机之间的进程间通信,例如客户端和服务器之间的通信,也可以实现同一计算机内不同进程之间的通信。Socket 可以支持不同的传输协议,例如 TCPUDP,可以根据需要选择不同的协议来进行通信。

在 Python 中,使用 socket 模块可以实现 Socket 编程,可以创建客户端和服务器端程序,进行网络通信。Socket 编程可以用于开发网络应用程序,例如网络爬虫、聊天室、文件传输等。
在这里插入图片描述

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

爬虫的工作流程

爬虫的工作流程
在这里插入图片描述

  1. 获取到资源地址:

爬虫首先要做的工作就是获取数据的资源地址,有了准确的地址之后我们才能数据去进行发送请求

  1. 发送请求获取数据

第二步要做的工作就是获取网页,这里就是获取网页的源代码。源代码里包含了网页的部分有用信息,所以 只要把源代码获取下来,就可以从中提取想要的信息了。

  1. 反爬虫处理:

有些网站会采取反爬虫措施,例如设置访问频率限制、验证码等,需要针对这些措施进行处理,以保证爬虫程序的正常运行。可以使用 Python 的验证码识别等技术来处理反爬虫措施。

  1. 提取信息:

获取网页源代码后,接下来就是分析网页源代码,从中提取我们想要的数据。首先,最通用的方法便是采用正则表达式提取,这是一个万能的方法,但是在构造正则表达式时比较复杂且容易出错。 另外,由于网页的结构有一定的规则,所以还有一些根据网页节点属性、CSS选择器或 XPath来提取网页信息的库,如Beautiful Soup、pyquery、lxml 等。使用这些库,我们可以高效快速地从中提取网页信 息,如节点的属性、文本值等。 提取信息是爬虫非常重要的部分,它可以使杂乱的数据变得条理清晰,以便我们后续处理和分析数据。

  1. 保存数据:

提取信息后,我们一般会将提取到的数据保存到某处以便后续使用。这里保存形式有多种多样,如可以简单保 存为 TXT 文本或 JSON 文本,也可以保存到数据库,如 MySQL 和 MongoDB 等,也可保存至远程服务 器,如借助 SFTP 进行操作等。

  1. 爬虫控制:

爬虫程序需要控制爬取的网页数量和频率,以避免对目标网站造成过大的负荷。可以使用 Python 的多线程或者多进程来实现并发爬取,也可以使用时间控制来控制爬取频率。

  1. 数据分析:

获取到数据后,可以进行数据分析和处理,例如数据可视化、机器学习、自然语言处理等,以得到更有价值的信息。

socket爬取图片

为什么能用socket能下载图片

使用 Socket 可以下载图片的原因是因为 HTTP 协议是基于 Socket 的应用层协议,它使用 TCP/IP 协议族来传输数据。在 HTTP 协议中,客户端通过 Socket 建立连接到服务器,发送请求,服务器接收请求并返回响应,客户端接收响应并处理响应数据。

由于 HTTP 协议是基于 Socket 的,所以使用 Socket 可以直接发送 HTTP 请求和接收 HTTP 响应,实现数据的传输和下载。使用 Socket 下载图片需要手动构造 HTTP 请求和解析 HTTP 响应,需要编写更多的代码来处理数据传输和错误处理,但是相对于其他下载方式,使用 Socket 可以更加灵活和自定义,可以实现更多的功能和应用场景。

socket下载图片和request下载图片的区别

Socket 和 Request 都可以用于下载图片,但是它们的实现方式和用途略有不同。

Socket 是一种底层的网络通信协议,它可以在应用层和传输层之间建立连接,进行数据传输。使用 Socket 下载图片需要手动构建 HTTP 请求解析 HTTP 响应,需要编写更多的代码来处理数据传输和错误处理。Socket 更适合于底层网络通信的应用,如实现自定义协议、网络游戏等

Request 是一个 Python 库,它封装了 HTTP 请求和响应的处理,可以方便地进行网络请求。使用 Request 下载图片只需要简单的代码就可以完成,而且可以方便地设置请求头、请求参数等信息。Request 更适合于开发网络爬虫、数据采集等应用。

总的来说,使用 Socket 下载图片更加底层、灵活,但需要编写更多的代码;使用 Request 下载图片更加高层、方便,但可能会有一些限制。选择使用哪种方式,取决于具体的需求和应用场景。

用代码举例说明:

使用 Socket下载图片:

import socket

# 构造 HTTP 请求
request = b"GET /images/test.jpg HTTP/1.1\r\nHost: example.com\r\n\r\n"

# 建立连接并发送请求
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("example.com", 80))
s.send(request)

# 接收响应并保存图片
response = s.recv(4096)
while response:
    if b"Content-Type: image/jpeg" in response:
        with open("test.jpg", "wb") as f:
            f.write(response)
            break
    response = s.recv(4096)

# 关闭连接
s.close()

使用 Request 下载图片:

import requests

# 发送请求并保存图片
response = requests.get("http://example.com/images/test.jpg")
with open("test.jpg", "wb") as f:
    f.write(response.content)

可以看到,使用 Request 下载图片更加简单和方便,而使用 Socket 则需要手动构建 HTTP 请求和解析 HTTP 响应,需要更多的代码和处理过程。

使用socket下载一张图片

以图片http://image11.m1905.cn/uploadfile/2021/0922/thumb_0_647_500_20210922030733993182.jpg为例。
想要使用socket下载这张图片,具体步骤如下:

  1. 获取到资源地址 url。

  2. 创建 Socket 客户端对象 client,并连接到服务器 image11.m1905.cn 的端口 80。

  3. 构造 HTTP 请求,包括请求方法、请求地址、请求协议版本、请求头等信息,并发送请求。

  4. 循环接收服务器响应,并将响应数据添加到二进制对象 result 中。

  5. 使用正则表达式提取响应数据中的图片数据,即去掉响应头部分。

  6. 将图片数据存储到本地文件中,即下载图片到本地。

代码如下:

import socket
import re
import time

# 获取到资源地址
url = 'http://image11.m1905.cn/uploadfile/2021/0922/thumb_0_647_500_20210922030733993182.jpg'

start = time.time()

# 创建套接字对象
client = socket.socket()

# 创建连接
client.connect(('image11.m1905.cn', 80))

# 构造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'
# print(http_res)

# 发送请求
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])

end_time = time.time()  # 记录结束时间
elapsed_time = end_time - start  # 计算代码执行时间
print(f'All images downloaded successfully in {elapsed_time:.2f} seconds')

使用socket下载多张图片

假设我们想使用socket下载多张图片,我这里给出两种实现方法。

方法1

将需要下载的url做成一个列表,再使用split函数将url中的/进行分割,然后通过切片方法得到url中的相对路径和host值,最后通过循环遍历url列表,达到下载多张图片的效果。代码如下

import socket
import re
import time
start = time.time()
# 获取到的资源地址
urls = [
    'https://pic.netbian.com/uploads/allimg/220211/004115-1644511275bc26.jpg',
    'https://pic.netbian.com/uploads/allimg/220215/233510-16449393101c46.jpg',
    'https://pic.netbian.com/uploads/allimg/211120/005250-1637340770807b.jpg'
]

# 创建连接
for url in urls:
    # 解析URL
    parts = url.split('/')  # ['https:', '', 'pic.netbian.com', 'uploads', 'allimg', '220211', '004115-1644511275bc26.jpg']
    host = parts[2]  # pic.netbian.com
    path = '/' + '/'.join(parts[3:])  # /uploads/allimg/220211/004115-1644511275bc26.jpg
    # print(parts)
    # print(host)
    # print(path)

    # 创建套接字对象连接到主机
    client = socket.socket()
    client.connect((host, 80))

    # 构造HTTP请求
    http_req = f'GET {path} HTTP/1.1\r\nHost: {host}\r\nuser-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' \
               f'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\r\nConnection: close\r\n\r\n '
    # print(http_req)
    # 发送请求
    client.sendall(http_req.encode())

    # 接受响应数据
    result = b''
    data = client.recv(1024)
    while data:
        result += data
        data = client.recv(1024)

    # 提取图像数据
    images = re.findall(b'\r\n\r\n(.*)', result, re.S)
    # print(images[0])

    # 写入文件
    if images:
        with open(f'{parts[-1]}', 'wb') as f:
            f.write(images[0])
    else:
        print(f'No image data received for {url}')

    # 关闭连接
    client.close()

end_time = time.time()  # 记录结束时间
elapsed_time = end_time - start  # 计算代码执行时间
print(f'All images downloaded successfully in {elapsed_time:.2f} seconds')

方法2

通过创建线程池,使用多线程的方式同时下载所有图片。

代码如下:

import socket
import re
import multiprocessing
import time


def download_image(url):
    # 解析URL
    parts = url.split('/')
    host = parts[2]
    path = '/' + '/'.join(parts[3:])

    # 创建套接字对象连接到主机
    client = socket.socket()
    client.connect((host, 80))

    # 构造HTTP请求
    http_req = f'GET {path} HTTP/1.1\r\nHost: {host}\r\nuser-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' \
               f'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36\r\nConnection: close\r\n\r\n '

    # 发送请求
    client.sendall(http_req.encode())

    # 接受响应数据
    result = b''
    data = client.recv(1024)
    while data:
        result += data
        data = client.recv(1024)

    # 提取图像数据
    images = re.findall(b'\r\n\r\n(.*)', result, re.S)

    # 写入文件
    if images:
        with open(f'{parts[-1]}', 'wb') as f:
            f.write(images[0])
    else:
        print(f'No image data received for {url}')

    # 关闭连接
    client.close()


if __name__ == '__main__':
    start = time.time()
    urls = [
        'https://pic.netbian.com/uploads/allimg/220211/004115-1644511275bc26.jpg',
        'https://pic.netbian.com/uploads/allimg/220215/233510-16449393101c46.jpg',
        'https://pic.netbian.com/uploads/allimg/211120/005250-1637340770807b.jpg'
    ]

    # 创建进程池
    pool = multiprocessing.Pool(processes=3)

    # 同时下载所有图片
    pool.map(download_image, urls)

    # 关闭进程池
    pool.close()
    pool.join()

    end = time.time()
    elapsed_time = end - start  # 计算代码执行时间
    print(f'All images downloaded successfully in {elapsed_time:.2f} seconds')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/388051.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AQS为什么用双向链表?

首先,在AQS中,等待队列是通过Node类来表示的,每个Node节点包含了等待线程的信息以及等待状态。下面是Node类的部分源码:static final class Node {// 等待状态volatile int waitStatus;// 前驱节点volatile Node prev;// 后继节点…

【AI绘图学习笔记】深度学习相关数学原理总结(持续更新)

如题,这是一篇深度学习相关数学原理总结文,由于深度学习中涉及到较多的概率论知识(包括随机过程,信息论,概率与统计啥啥啥的),而笔者概率知识储备属实不行,因此特意开一章来总结(大部…

Jackson CVE-2017-17485 反序列化漏洞

0x00 前言 同CVE-2017-15095一样,是CVE-2017-7525黑名单绕过的漏洞,主要还是看一下绕过的调用链利用方式。 可以先看: Jackson 反序列化漏洞原理 或者直接看总结也可以: Jackson总结 涉及版本:2.8.10和2.9.x至2.…

leetcode_贪心算法

贪心算法相关题简单题目455.分发饼干1005.K次取反后最大化的数组和860.柠檬水找零序列问题376.摆动序列法一:贪心法法二:动态规划单调递增的数字简化版本有点难度53.最大子序和贪心算法动态规划134.加油站968.监控二叉树两个维度权衡问题分发糖果406.根据…

MATLAB——系统环境

MATLAB概述MATLAB的发展MATLAB:MATrix LABoratory1980年前后,Cleve Moler教授编写的Linpack 和Eispack的接口程序。1984年,MATLAB第1版(DOS版)1992年,MATLAB4.0版1994年,MATLAB 4.2版1997年,MATLAB 5.0版1999年&#x…

12-Trie树

Trie树(又称字典树、单词查找树)是一种树型的数据结构,常用于保存和查找字符串,是一种十分高效率的存储和检索方式。 Trie树原理 我们先假设有六个字符串需要存储:abc、abcd、abef、cfgh、bc、bcd。Trie树的存储原理…

Scala04 方法与函数

Scala04 方法与函数 Scala 中的也有方法和函数的概念。 Scala中的 方法 是类的一部分。 Scala中的 函数 是一个对象,可以赋值给变量。 在类中定义的函数就是方法 4.1 方法 Scala 中方法 与 Java 中类似,是组成类的一部分 4.1.1 语法结构 格式&#x…

数据库“啃”不动?CnosDB带你轻松阅读十万行源码!

最近一直有社区的小伙伴问,我们很感兴趣CnosDB,但从何开始阅读CnosDB的代码呢,其实这个问题在之前的CnosDB HiTea直播时就有聊到,今天我们就再来回顾一下。CnosDB的源代码主要分为Query Engine和Storage Engine。Query Engine在qu…

JOSN数据转换和解析

文章目录JOSN数据转换和解析内容回顾Map 集合转成 JSON 字符串List 集合转换成 JSON 字符串Ajax 异步和同步异步概念同步概念异步和同步区别异步请求案例同步请求时间格式化旧时间 api 格式化格式化和解析的工具类JSTL 时间格式化JSTL 使用JOSN数据转换和解析 内容回顾 ajax …

指针的进阶续(笔试题强化练习)

写在前面:在上次我们学习了指针的相关类型的知识,对指针家族的成员基本有了了解,这次让我们跟着一些题目来练习和补充一些知识,这有助于我们强化理解这些知识。 话不多说,我们马上开始: 1.指针和数组的笔…

Vue基础学习 第一个Vue程序 el挂载点 v-指令(1)

Vue简介 Vue是一个Javascript框架Vue框架可以简化Dom操作响应式数据驱动 : 页面是由数据生成的,当数据出现改动,页面也会即时改变 第一个Vue程序 Vue中文文档官网:https://v2.cn.vuejs.org/v2/guide/ 根据官方文档的说法&#…

缓存与数据库的双写一致性

背景 在高并发的业务场景下,系统的性能瓶颈往往是出现在数据库上,用户并发访问过大,压力都打到数据库上。所以一般都会用redis做缓存层,起到一个缓冲作用,让请求先访问到缓存层,而不是直接去访问数据库&am…

Web3D发展趋势以及Web3D应用场景

1,Web3D发展趋势随着互联网的快速发展,Web3D技术也日渐成熟,未来发展趋势也值得关注。以下是Web3D未来发展趋势的七个方面:可视化和可交互性的增强:Web3D可以为三维数据提供可视化和可交互性的增强,将极大地…

CCNP350-401学习笔记(补充题目101-186)

101、 enable the https service 102、fabric edge node 103、 104、 105、 16113 106、filter access-group 10 107、 108、VETP 109、 110、 111、the server and the database can inititate communication 112、 113、 114、 115、 116、WAN edge&#xf…

【教程】去水印开源工具Lama Cleaner在Windows的安装和使用

一、Lama Cleaner是什么? Lama Cleaner是一款开源且免费的人工学习图片去水印程序(个人主要学习用途),没有图片分辨率限制(个人使用暂未发现),并且保存的图片质量很高(个人觉得跟原…

MSTP多进程讲解与实验配置

目录 MSTP多进程 专业术语 MSTP多进程配置 在MSTP域配置 MSTP多进程 多进程的作用 将设备上的端口绑定到不同的进程中,以进程为单位进行MSTP计算,不在同一进程内的端口不参与此进程中的MSTP协议计算,实现各个进程之间的生成树计算相互独立…

【算法】DFS与BFS

作者:指针不指南吗 专栏:算法篇 🐾题目的模拟很重要!!🐾 文章目录1.区别2.DFS2.1 排列数字2.2 n-皇后问题3.BFS3.1走迷宫1.区别 搜索类型数据结构空间用途过程DFSstackO( n )不能用于最短路搜索到最深处&a…

leetcode打卡-深度优先遍历和广度优先遍历

200.岛屿数量 leetcode题目链接:https://leetcode.cn/problems/number-of-islands leetcode AC记录: 思路:深度优先遍历,从0,0开始遍历数组,使用boolean类型数组used记录是否被访问过,进行一…

28个案例问题分析---014课程推送页面逻辑整理--vue

一&#xff1a;背景介绍 项目开发过程中&#xff0c;前端出现以下几类问题&#xff1a; 代码结构混乱代码逻辑不清晰页面细节问题 二&#xff1a;问题分析 代码结构混乱问题 <template><top/><div style"position: absolute;top: 10px"><C…

SpringBoot监听机制-以及使用

11-SpringBoot事件监听 Java中的事件监听机制定义了以下几个角色&#xff1a; ①事件&#xff1a;Event&#xff0c;继承 java.util.EventObject 类的对象 ②事件源&#xff1a;Source &#xff0c;任意对象Object ③监听器&#xff1a;Listener&#xff0c;实现 java.util…