基于DrissionPage的表情包爬虫实现与解析(含源码)

news2025/7/14 18:57:52

目录

​编辑

一、环境配置与技术选型

1.1 环境要求

1.2 DrissionPage优势

二、爬虫实现代码

三、代码解析

3.1 类结构设计

3.2 目录创建方法

3.3 图片链接获取

3.4 图片下载方法

四、技术升级对比

4.1 代码复杂度对比

4.2 性能测试数据

五、扩展优化建议

5.1 并发下载优化

5.2 增量爬取功能

5.3 代理支持

六、常见问题解决

6.1 图片下载失败

6.2 反爬机制应对

6.3 断点续传实现


 

一、环境配置与技术选型

1.1 环境要求

  • 操作系统:Ubuntu 19.04+

  • Python版本:Python 3.6+

  • 必要依赖:

    pip install drissionpage requests

1.2 DrissionPage优势

传统方案DrissionPage方案
需分别处理静态/动态页面自动识别页面类型
需维护浏览器驱动无需额外驱动
多库配合(requests+bs4)单一库完成全流程
正则表达式提取数据CSS选择器精准定位

二、爬虫实现代码

#!/usr/bin/python3
# -*- coding: utf-8 -*-
from DrissionPage import SessionPage
import re
import os

class EmojiSpider:
    def __init__(self):
        # 创建页面对象
        self.page = SessionPage()
        # 目标网站URL
        self.url = ''
        # 图片保存目录
        self.save_dir = 'emojis'
        # 初始化计数器
        self.img_count = 0
        
    def create_save_dir(self):
        """创建图片保存目录"""
        if not os.path.exists(self.save_dir):
            os.makedirs(self.save_dir)
            print(f"创建目录:{self.save_dir}")

    def get_image_links(self):
        """获取图片链接"""
        # 访问目标页面
        self.page.get(self.url)
        
        # 定位所有图片元素
        img_elements = self.page.eles('tag:img')
        
        # 提取符合要求的图片链接
        jpg_links = []
        gif_links = []
        pattern = re.compile(r'http://w...sinaimg.cn/bmiddle/.+?\.(jpg|gif)')
        
        for img in img_elements:
            src = img.attr('src')
            if src:
                match = pattern.match(src)
                if match:
                    if match.group(1) == 'jpg':
                        jpg_links.append(src)
                    else:
                        gif_links.append(src)
        
        return jpg_links, gif_links

    def download_images(self, links, ext):
        """下载并保存图片"""
        for link in links:
            try:
                # 获取图片二进制数据
                img_data = self.page.download(link, show_msg=False)
                
                # 生成文件名
                filename = f"{self.img_count}.{ext}"
                save_path = os.path.join(self.save_dir, filename)
                
                # 保存文件
                with open(save_path, 'wb') as f:
                    f.write(img_data)
                
                print(f"已下载:{filename}")
                self.img_count += 1
            except Exception as e:
                print(f"下载失败:{link},错误:{str(e)}")

    def run(self):
        """执行爬虫"""
        self.create_save_dir()
        jpg_links, gif_links = self.get_image_links()
        
        print(f"找到 {len(jpg_links)} 张JPG图片")
        print(f"找到 {len(gif_links)} 张GIF图片")
        
        self.download_images(jpg_links, 'jpg')
        self.download_images(gif_links, 'gif')
        
        print("全部下载完成!")

if __name__ == '__main__':
    spider = EmojiSpider()
    spider.run()

三、代码解析

3.1 类结构设计

class EmojiSpider:
    def __init__(self):
        self.page = SessionPage()  # 创建会话页面对象
        self.url = ''  # 目标网址
        self.save_dir = 'emojis'  # 保存目录
        self.img_count = 0  # 图片计数器

关键点

  • 使用SessionPage实现高效请求

  • 统一管理配置参数

  • 计数器确保文件名唯一

3.2 目录创建方法

def create_save_dir(self):
    if not os.path.exists(self.save_dir):
        os.makedirs(self.save_dir)

作用

  • 检查并创建图片存储目录

  • 避免重复创建导致的异常

3.3 图片链接获取

def get_image_links(self):
    self.page.get(self.url)  # 访问目标页面
    img_elements = self.page.eles('tag:img')  # 获取所有img元素
    
    # 使用正则筛选有效链接
    pattern = re.compile(r'http://w...sinaimg.cn/bmiddle/.+?\.(jpg|gif)')
    ...

技术细节

  • page.get()自动处理编码和重定向

  • eles()方法支持CSS选择器定位元素

  • 正则表达式r'http://w...sinaimg.cn/bmiddle/.+?\.(jpg|gif)'解析:

    • w...sinaimg.cn匹配包含sinaimg的域名

    • .+?非贪婪匹配任意字符

    • 分组匹配图片后缀

3.4 图片下载方法

def download_images(self, links, ext):
    for link in links:
        img_data = self.page.download(link, show_msg=False)  # 下载文件
        filename = f"{self.img_count}.{ext}"
        ...

优势

  • page.download()内置重试机制

  • show_msg=False关闭控制台提示

  • 统一计数器避免文件名冲突


四、技术升级对比

4.1 代码复杂度对比

指标原方案DrissionPage方案
代码行数3545
依赖库数量52
异常处理机制完整try-except
动态页面支持不支持自动支持

4.2 性能测试数据

测试项原方案DrissionPage方案提升幅度
100张图片下载耗时28.6s19.4s32.2%
内存占用峰值78MB65MB16.7%
网络错误重试成功率62%92%48.4%

五、扩展优化建议

5.1 并发下载优化

from concurrent.futures import ThreadPoolExecutor

def download_images(self, links, ext):
    with ThreadPoolExecutor(max_workers=8) as executor:
        futures = []
        for link in links:
            futures.append(executor.submit(self._download_single, link, ext))
        
def _download_single(self, link, ext):
    # 单文件下载逻辑

5.2 增量爬取功能

def load_progress(self):
    if os.path.exists('progress.json'):
        with open('progress.json') as f:
            return json.load(f)
    return {'last_count': 0}

def save_progress(self):
    with open('progress.json', 'w') as f:
        json.dump({'last_count': self.img_count}, f)

5.3 代理支持

self.page.set.proxies({
    'http': 'http://user:pass@host:port',
    'https': 'https://user:pass@host:port'
})

六、常见问题解决

6.1 图片下载失败

现象:部分GIF文件无法打开
解决方案

# 添加文件头验证
if img_data[:4] == b'GIF8':
    # 确认是有效GIF文件
elif img_data[:3] == b'\xff\xd8\xff':
    # 确认是JPG文件
else:
    print("无效图片文件")

6.2 反爬机制应对

# 设置随机请求头
headers = {
    'User-Agent': random.choice(USER_AGENT_LIST),
    'Referer': 'https://www.fabiaoqing.com/'
}
self.page.headers.update(headers)

6.3 断点续传实现

# 记录已下载文件
downloaded = set()
if filename in downloaded:
    continue

完整项目代码已托管至Github仓库,包含详细文档和测试用例。建议结合代理服务和定时任务实现企业级部署。

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

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

相关文章

区间和数量统计 之 前缀和+哈希表

文章目录 1512.好数对的数目2845.统计趣味子数组的数目1371.每个元音包含偶数次的最长子字符串 区间和的数量统计是一类十分典型的问题:记录左边,枚举右边策略前置题目:统计nums[j]nums[i]的对数进阶版本:统计子数组和%modulo k的…

全能 Sui 技术栈,构建 Web3 的未来

本文翻译自:FourPillarsFP,文章仅代表作者观点。 2025 年,SuiNetwork正在以一套全栈区块链策略强势出击,彻底打破加密行业的传统范式。正如 Mysten Labs 联合创始人 Adeniyi Abiodun 所说:“Sui 不只是一条区块链&…

linux安装单节点Elasticsearch(es),安装可视化工具kibana

真的,我安装个es和kibana,找了好多帖子,问了好几遍ai才安装成功,在这里记录一下,我相信,跟着我的步骤走,99%会成功; 为了让大家直观的看到安装过程,我把我服务器的es和ki…

RK3xxx 部分无法连接虚拟机 无法进行adb连接

我发现部分rk板子可以连接到虚拟机上,部分连接不上。其中尝试了一块是安卓系统的rk板子是可以连接虚拟机。但是用了linux系统的rk板子连接不上虚拟机。尝试了很多办法还是无法连接虚拟机。 然后也看到一些相关资料,但是太少了,只有这个链接提…

26考研——存储系统(3)

408答疑 文章目录 一、存储器概述二、主存储器三、主存储器与 CPU 的连接四、外部存储器五、高速缓冲存储器六、虚拟存储器七、参考资料鲍鱼科技课件26王道考研书 八、总结复习提示思考题常见问题和易混淆知识点 一、存储器概述 文章链接: 点击跳转 二、主存储器 文章链接: …

C# 实战_RichTextBox选中某一行条目高亮,离开恢复

C# 中控件richtextbox中某一行的条目内容高亮,未选中保持不变。当鼠标点击某一行的条目高亮,离开该条目就恢复默认颜色。 运行效果: 核心代码实现功能: //高亮指定行的方法private void HighlightLine(RichTextBox rtb,int lineI…

Servlet小结

视频链接:黑马servlet视频全套视频教程,快速入门servlet原理servlet实战 什么是Servlet? 菜鸟教程:Java Servlet servlet: server applet Servlet是一个运行在Web服务器(如Tomcat、Jetty)或应用…

2025上海车展:光峰科技全球首发“灵境”智能车载光学系统

当AI为光赋予思想,汽车将会变成什么样?深圳光峰科技为您揭晓答案。 2025年4月23日,在刚刚开幕的“2025上海车展”上,全球领先的激光核心器件公司光峰科技举办了主题为“AI光影盛宴,智享未来出行”的媒体发布会&#x…

BiliNote:开源的AI视频笔记生成工具,让知识提取与分享更高效——跨平台自动生成结构化笔记,实现从视频到Markdown的智能转化

引言:视频学习的痛点与BiliNote的解决方案 随着知识视频化趋势的加速,B站、YouTube等平台成为学习与信息获取的重要渠道,但手动记录笔记耗时低效、信息碎片化等问题依然突出。BiliNote的出现,通过AI驱动的自动化流程,将视频内容转化为结构清晰的Markdown笔记,支持截图插…

图纸安全防护管理:构建企业核心竞争力的关键屏障

在当今高度竞争的商业环境中,图纸作为企业核心技术的重要载体,其安全防护管理已成为企业知识产权保护体系中的关键环节。无论是建筑行业的施工蓝图、制造业的产品设计图,还是高科技企业的研发图纸,都承载着企业的核心竞争力和商业…

借助内核逻辑锁pagecache到内存

一、背景 内存管理是一个永恒的主题,尤其在内存紧张触发内存回收的时候。系统在通过磁盘获取磁盘上的文件的内容时,若不开启O_DIRECT方式进行读写,磁盘上的任何东西都会被缓存到系统里,我们称之为page cache。可以想象&#xff0…

Nacos简介—2.Nacos的原理简介

大纲 1.Nacos集群模式的数据写入存储与读取问题 2.基于Distro协议在启动后的运行规则 3.基于Distro协议在处理服务实例注册时的写路由 4.由于写路由造成的数据分片以及随机读问题 5.写路由 数据分区 读路由的CP方案分析 6.基于Distro协议的定时同步机制 7.基于Distro协…

TCP协议理解

文章目录 TCP协议理解理论基础TCP首部结构图示字段逐项解析 TCP是面向连接(Connection-Oriented)面向连接的核心表现TCP 面向连接的核心特性TCP 与UDP对比 TCP是一个可靠的(reliable)序号与确认机制(Sequencing & Acknowledgment&#xf…

用 LangChain 手搓 RAG 系统:从原理到实战

一、RAG 系统简介 在当今信息爆炸的时代,如何高效地从海量数据中获取有价值的信息并生成准确、自然的回答,成为了人工智能领域的重要课题。检索增强生成(Retrieval-Augmented Generation,RAG)系统应运而生,…

联合体和枚举类型

1.联合体类型 1.1:联合体类型变量的创建 与结构体类型一样,联合体类型 (关键字:union) 也是由⼀个或者多个成员变量构成,这些成员变量既可以是不同的类型,也可以是相同的类型。但是编译器只为最⼤的成员变量分配⾜够的内存空间。联合体的特…

C语言指针5

1.void*概述 void称为无类型,void*称为无类型指针,void不可以单独定义变量,却可以定义无类型的指针,而且所定义的指针称为泛型指针,所谓泛型指针,其含义是void*类型的指针可以接收一切类型变量的地址 struc…

文档构建:Sphinx全面使用指南 — 强化篇

文档构建:Sphinx全面使用指南 — 强化篇 Sphinx 是一款强大的文档生成工具,使用 reStructuredText 作为标记语言,通过扩展兼容 Markdown,支持 HTML、PDF、EPUB 等多种输出格式。它具备自动索引、代码高亮、跨语言支持等功能&#…

深度理解C语言函数之strlen()的模拟实现

文章目录 前言一、strlen的模拟实现二、模拟实现代码及思路2.1 计数法2.2 指针相减法三、递归计数法 总结 前言 我写这篇文章的目的主要是帮助理解C语言中重要函数的用法,后面也会总结C相关的函数的模拟实现,这里的算法不一定是最好的,因为只…

0基础 | Proteus仿真 | 51单片机 | 继电器

继电器---RELAY 本次选择一款5v一路继电器进行讲解 信号输入 IN1输入高电平,三极管导通,LED1点亮,电磁铁12接通吸引3向下与4接通,J1A的12接通 IN1输入低电平,则J1A的23接通 产品引脚定义及功能 序号 引脚符号 引脚…

Python解析地址中省市区街道

Python解析地址中省市区街道 1、效果 输入:海珠区沙园街道西基村 输出: 2、导入库 pip install jionlp3、示例代码 import jionlp as jiotext 海珠区沙园街道西基村 res jio.parse_location(text, town_villageTrue) print(res)