解锁豆瓣高清海报(三)从深度爬虫到URL构造,实现极速下载
脚本地址:
项目地址: Gazer
PosterBandit_v2.py
前瞻
之前的 PosterBandit.py 是按照深度爬虫的思路一步步进入海报界面来爬取, 是个值得学习的思路, 但缺点是它爬取慢, 仍然容易碰到豆瓣的 418 错误, 本文也会指出彻底解决旧版 418 错误的方法并提高爬取速度. 现在我将介绍优化版, 这个版本通过直接构造 URL 来实现获取海报原图, 准确识别、更快爬取. 本文会重点讲解动态 headers 及其应用于请求的必要性.
使用方法
- 克隆或下载项目代码.
- 安装依赖:
pip install requests
, 或者克隆项目代码后pip install -r requirements.txt
- 修改脚本内部的常量
DEFAULT_POSTER_PATH
, 设置默认保存路径. - 修改主函数处的
poster_save_path
保存路径. - 修改主函数处的起始日期
target_date_1
和截止日期target_date_2
. 同时修改起始爬取页参数为包含截止日期标记的页数page_id=1
. - 填写你的
cookies
. - 运行脚本
PosterBandit_v2
.
注意
- 起止日期不要写错, 否则判断逻辑会出错.
- 见免责声明.
示例:
target_date_1 = "2024-12-1" # TODO 填写起始日期target_date_2 = "2024-12-31" # TODO 填写截止日期
文件结构
Gazer/
├── DoubanGaze/
│ ├── data/
│ │ └── poster/
│ │ └── 2024_1_1_2025_1_31/
│ └── src/
│ ├── PosterBandit.py
│ └── PosterBandit_v2.py
└──...
脚本构思详解
V2 版本处理了深度为 1 的数据 (缩略图链接) 和深度为 2 的数据 (最终海报 URL), 但它 爬取 的深度仍然是 0. 依然在括号中标记了爬取深度.
-
以默认第一页或指定的页数作为爬取的起始页 (爬取深度 0), 找到所有包含电影条目的 div 元素, 最大为 15 个. ▶️
get_movie_elements
电影条目 CSS 选择器:
#content > div.grid-16-8.clearfix > div.article .item.comment-item
-
在电影条目的 div 元素内找到对应的日期元素和压缩的海报图片链接 ▶️
get_movie_info
-
日期 CSS 选择器:
#content div.info span.date
检查是否在指定的起止日期参数之间 ▶️
compare_date
-
这个页面的海报图片元素 CSS 选择器:
#content div.pic img
-
以 <绝命毒师 第二季> 为例, 在这里
<img>
标签的 source 链接是https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2016505705.webp
(可以认为是数据深度 1, 因为它直接来源于起始页), 高清海报页面https://movie.douban.com/photos/photo/2016505705/
的海报元素 source 链接是https://img9.doubanio.com/view/photo/l/public/p2016505705.webp
(数据深度 2, 因为它需要通过详情页才能获取, 或者说, 如果按照 V1 的"点击"流程, 需要经过两层(收藏页 -> 电影详情页 -> 海报大图)页面跳转才能到达).注意: 这个
div
中放了 2 个可下载图片资源链接. 首先, 后一个 jpg 链接需要通过 JS 动态加载激活, 直接下载是不可用的; 其次, 一般 WebP 文件会更小, 基于 WebP 更先进的压缩算法, 肉眼观察可能会感觉 WebP 更清晰. 所以这里第一个链接是最优选择. -
观察两个链接, 可以知道, 只要在这个页面找到第一个链接, 即可构造第二个:
https://img9.doubanio.com/view/photo/l/public/p{photo_id}.webp
(数据深度 2, 但 V2 版本是直接构造这个 URL, 没有爬取这个深度的页面)
检查是否在指定的起止日期参数之间 ▶️
compare_date
-
-
-
下载图片保存到指定路径, 创建文件夹名称, 根据日期定义, 如
2024_1_1_2024_12_31
▶️create_folder
save_poster
爬虫效率优化
V2 版本 ( PosterBandit_v2.py
) 确实比 V1 版本 ( PosterBandit.py
) 理论上应该更快, 因为减少了不必要的请求 (不再需要进入每个电影的详情页, 直接构造海报 URL). 而且用 save_poster()
函数单独测试海报下载也是成功的, 这说明问题很可能出在 V2 版本的爬虫逻辑上, 而不是 save_poster()
函数本身.
问题:
- V2 版本: 出现高频率 418 错误 (只能下载第一张);
- V1 版本: (深度爬虫) 能正常下载. 但速度慢, 可能会有 418.
V1 和 V2 的主要区别 (请求层面):
-
V1 (深度爬虫):
- 请求豆瓣电影收藏页面 (
https://movie.douban.com/people/{user_id}/collect...
). - 对于页面上的每个电影条目, 获取电影详情页链接.
- 请求每个电影详情页链接 (
https://movie.douban.com/subject/{movie_id}/
). - 从电影详情页中获取海报列表页链接.
- 请求海报列表页链接 (
https://movie.douban.com/subject/{movie_id}/photos...
). - 从海报列表页中获取第一张海报的详情页链接.
- 请求第一张海报的详情页链接 (
https://movie.douban.com/photos/photo/{photo_id}/
). - 从海报详情页中获取最终的海报图片 URL.
- 请求最终的海报图片 URL, 下载海报.
- 请求豆瓣电影收藏页面 (
-
V2 (构造 URL):
- 请求豆瓣电影收藏页面 (
https://movie.douban.com/people/{user_id}/collect...
). - 对于页面上的每个电影条目, 获取电影的 缩略图 链接 (例如
https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2016505705.webp
). - 从缩略图链接中提取 photo ID.
- 直接构造海报图片 URL (
https://img9.doubanio.com/view/photo/l/public/p{photo_id}.webp
). - 请求构造的海报图片 URL, 下载海报.
- 请求豆瓣电影收藏页面 (
V2 版本高频率 418 的原因:
-
请求频率过高:
- V1 的 “缓冲” 作用: V1 版本虽然请求次数多, 但每次请求之间都有一定的 “缓冲”. 它需要逐个进入电影详情页、海报列表页等, 这些页面加载本身就需要时间. 这些 “无意” 的延迟, 反而降低了请求频率, 不容易触发豆瓣的反爬机制.
- V2 的 “集中” 请求: V2 版本大大减少了请求次数, 理论上更快. 但它把对海报图片 URL 的请求 集中 在了一起. 在循环中, 它会快速地、连续地请求多个海报图片 URL, 这很容易被豆瓣服务器识别为爬虫行为, 从而触发 418 错误 (或者其他更严厉的封禁).
-
Referer
头的问题:Referer
: 2 个版本, 当请求最终的海报图片 URL 时,Referer
头理应是海报详情页的 URL, 但实际都是直接请求它. 此时,Referer
头会是豆瓣电影收藏页面 URL (例如https://movie.douban.com/people/{user_id}/collect...
). 服务器可能会认为, 直接从收藏页面请求海报图片 URL 这种行为不太正常, 因为用户通常会先点击海报进入详情页, 然后再查看大图. 因此, 豆瓣可能会对这种Referer
头的请求更加警惕.
解决: 修改后的 V2 版本代码 (重点是增加延迟和修改 Referer):
主要修改:
-
get_headers()
函数修改:- 参数名
viewed_movie_url
改为referer
, 更通用. - 函数内部使用传入的
referer
参数设置Referer
请求头.
- 参数名
-
save_poster()
函数:- 增加了一个
headers
参数. - 在
requests.get()
中使用传入的headers
参数.
- 增加了一个
-
download_poster_images()
函数修改:- 在首次请求豆瓣电影收藏页面时, 使用
viewed_movie_url
作为Referer
. - 在循环内部, 构造好
headers
后, 调用save_poster()
函数时, 传入headers
参数. - 在每次循环请求海报 URL 之前, 增加
time.sleep(random.uniform(2, 6))
, 随机延迟 2-6 秒或更长. 用于降低请求频率.
- 在首次请求豆瓣电影收藏页面时, 使用
V1 版本代码也作了同样的修改, 测试后显著提高了速度以及避免了 418.
性能对比
对比一下, 同样的内容完整爬取, 包括延迟时间, 总耗时:
- 38 张图片: V1 版本 5 分 29 秒, V2 版本 2 分 50 秒.
- 110 张图片: V1 版本 15 分 10 秒, V2 版本 8 分 15 秒.
V1 版本 (深度爬虫) 的速度提升也很明显, 这说明 Referer
头 的正确设置确实非常重要! 豆瓣的反爬机制很可能对 Referer
做了比较严格的检查.
V2 版本 (构造 URL) 会比 V1 快近一倍. 因为 V2 版本减少了大量不必要的请求 (不需要访问每个电影的详情页和海报列表页), 直接构造最终的海报 URL, 所以速度最快.
总结:
- 解决了 418 错误: 通过增加延迟和正确设置
Referer
头. - 优化了 V1 版本: 给 V1 版本增加
Referer
头更新, 提高了 V1 的速度 (从超过 5 分钟缩短到大约 2 分半钟). - 性能对比: 对比了 V1 和 V2 版本的性能, 验证了 V2 版本 (构造 URL) 的速度优势.
相关文章:

解锁豆瓣高清海报(三)从深度爬虫到URL构造,实现极速下载
脚本地址: 项目地址: Gazer PosterBandit_v2.py 前瞻 之前的 PosterBandit.py 是按照深度爬虫的思路一步步进入海报界面来爬取, 是个值得学习的思路, 但缺点是它爬取慢, 仍然容易碰到豆瓣的 418 错误, 本文也会指出彻底解决旧版 418 错误的方法并提高爬取速度. 现在我将介绍…...

IDEA单元测试插件 SquareTest 延长试用期权限
SquareTest是一款强大的IDEA单元测试生成插件工具,具体使用方法就不过多介绍了,这里主要介绍变更试用期,方便大家使用 配置信息 我的电脑安装前提配置条件 IntelliJ IDEA 2023.2windows 系统 软件安装 IntelliJ IDEA 直接安装插件Squar…...
PLC的五个学习步骤
五个学习步骤详解: 1. 夯实电气基础 (第一步) 核心思想: PLC控制技术是建立在传统电气控制技术之上的,因此扎实的电气基础至关重要。学习内容: 电气元件原理: 深入理解继电器、接触器、按钮、三相异步电机等常用电气元件的工作原理。这是理解电气控制回…...

深度学习05 ResNet残差网络
目录 传统卷积神经网络存在的问题 如何解决 批量归一化BatchNormalization, BN 残差连接方式 残差结构 ResNet网络 ResNet 网络是在 2015年 由微软实验室中的何凯明等几位大神提出,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名。获得CO…...

卷积神经网络CNN
目录 一、CNN概述 二、图像基础知识 三、卷积层 3.1 卷积的计算 3.2 Padding 3.3 Stride 3.4 多通道卷积计算 3.5 多卷积核卷积计算 3.6 特征图大小计算 3.7 Pytorch 卷积层API 四、池化层 4.1 池化计算 4.2 Stride 4.3 Padding 4.4 多通道池化计算 4.5 Pytorc…...
Android:播放Rtsp视频流的两种方式
一.SurfaceView Mediaplayer XML中添加SurfaceView: <SurfaceViewandroid:id"id/surface_view"android:layout_width"match_parent"android:layout_height"match_parent"/> Activity代码: package com.android.rtsp;impor…...

web信息泄露 ctfshow-web入门web1-web10
01做题思路 判断做题的思路是读取,写入,还是执行判断大概的类型,有登录逻辑就尝试sql注入,有下载逻辑就尝试文件读取,有源码就做源码审计 02信息泄露及利用 robots.txt 以ctfshow的web1为例,访问robots…...
Log4j在Spring项目中的应用与实践
在现代Java开发中,日志记录是不可或缺的一部分。它不仅帮助开发者调试和监控应用程序的运行状态,还能在出现问题时快速定位原因。今天,我们就来探讨如何在Spring项目中使用Log4j进行日志管理,并通过具体的实例来展示其强大的功能。…...
docker安装mysql:8.0
1.docker源 目前docker国内的源基本上用不了了,建议去淘宝找一找,我整了一个大概是10R一个月。 2.拉取镜像 docker pull mysql:8.0 3.启动容器 命令如下: docker run \-p 3306:3306 \-e MYSQL_ROOT_PASSWORD123456 \-v /home/data/mysq…...

搭建一个 Spring Boot 项目,解决jdk与springboot版本不匹配
搭建一个 Spring Boot 项目 方式一:使用 Spring Initializr Spring Initializr 是一个基于 Web 的工具,用于快速生成 Spring Boot 项目的基础结构。 访问 Spring Initializr 网站:https://start.spring.io/配置项目信息: …...

心心相系:十颗心
心心相系:十颗心 【1】心脏;人心,热心 heart //注:h-通c-或k- warmhearted a.热心的,热心肠的;亲切的a warm-hearted person 为人古道热肠 词根cardi(o)-(heart),例词:cardiology(…...

ChatGPT行业热门应用提示词案例-AI绘画类
AI 绘画指令是一段用于指导 AI 绘画工具(如 DALLE、Midjourney 等)生成特定图像的文本描述。它通常包含场景、主体、风格、色彩、氛围等关键信息,帮助 AI 理解创作者的意图,从而生成符合要求的绘画作品。 ChatGPT 拥有海量的知识…...

前端面试手写--虚拟列表
目录 一.问题背景 二.代码讲解 三.代码改装 四.代码发布 今天我们来学习如何手写一个虚拟列表,本文将把虚拟列表进行拆分并讲解,然后发布到npm网站上. 一.问题背景 为什么需要虚拟列表呢?这是因为在面对大量数据的时候,我们的浏览器会将所有数据都渲染到表格上面,但是渲…...
达梦数据库针对慢SQL,收集统计信息清除执行计划缓存
前言:若遇到以下场景,大概率是SQL走错了执行计划: 1、一条SQL在页面上查询特别慢,但拿到数据库终端执行特别快 2、一条SQL在某种检索条件下查询特别慢,但拿到数据库终端执行特别快 此时,可以尝试按照下述步…...

李沐--动手学深度学习 序列模型
1.使用正弦函数和可加性噪声生成序列数据 import torch from torch import nn from d2l import torch as d2l#使用正弦函数和可加性噪声生成序列数据 T 1000 #总共产生1000个点 time torch.arange(1,T1,dtypetorch.float32) x torch.sin(0.01*time) torch.normal(0,0.2,(…...

数据分析、商业智能、业务分析三者之间的关系
商业智能 (Business Intelligence, BI)、业务分析 (Business Analytics, BA) 和数据分析 (Data Analytics, DA) 三者都与数据密切相关,但在目标、方法和应用上存在差异。为了能够清晰地解释,下面将从定义入手,然后阐述它们之间的联系和区别。…...

【Spring+MyBatis】留言墙的实现
目录 1. 添加依赖 2. 配置数据库 2.1 创建数据库与数据表 2.2 创建与数据库对应的实体类 3. 后端代码 3.1 目录结构 3.2 MessageController类 3.3 MessageService类 3.4 MessageMapper接口 4. 前端代码 5. 单元测试 5.1 后端接口测试 5.2 使用前端页面测试 在Spri…...

让编程变成一种享受-明基RD320U显示器
引言 作为一名有着多年JAVA开发经验的从业者,在工作过程中,显示器的重要性不言而喻。它不仅是我们与代码交互的窗口,更是影响工作效率和体验的关键因素。在多年的编程生涯中,我遇到过各种各样的问题。比如,在进行代码…...
【嵌入式Linux应用开发基础】fork()函数
目录 一、fork 函数概述 1.1. 函数作用 1.2. 函数原型与头文件 1.3. 返回值 1.4. 核心特性 二、父子进程的区别与联系 2.1. 相同点 2.2. 不同点 三、典型应用场景 3.1. 多任务处理 3.2. 守护进程创建 3.3. 执行外部程序 3.4. 并行计算 四、fork 函数的关键注意事…...

2024 年 CSDN 博客之星年度评选:技术创作与影响力的碰撞(统计时间2025-02-17 11:06:06)
摘要:在技术的海洋里,每一位博主都像是一座独特的灯塔,用自己创作的光芒照亮他人前行的道路。2024 年 CSDN 博客之星年度评选活动,正是对这些灯塔的一次盛大检阅,让我们看到了众多优秀博主在技术创作领域的卓越表现以及…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...