Serverless爬虫:Pixiv爬虫/下载/访问,3分钟免费一键部署你的爬虫!

207 阅读8分钟

一个简单的 Serverless Pixiv 爬虫项目分享

前言

最近把之前用 Python 写的 Pixiv 爬虫用 AI 和 Serverless 架构重新实现了一遍,主要是想实践榨干一下 serverless的免费额度。虽然功能还比较基础,但整个过程学到了不少东西,想和大家分享一下。

声明:这个项目纯粹是为了学习技术,请大家合理使用,遵守相关网站的服务条款。

技术选型思考

为什么选择 Serverless?

说实话,一开始我也在犹豫要不要用 Serverless。传统的服务器部署我比较熟悉,但 Serverless 有几个吸引我的地方:

  • 成本低:对于个人项目来说,免费额度基本够用,这是主要原因

  • 免运维:不用担心服务器宕机、更新等问题,也不用担心替换代码,直接git action自动触发部署

  • 自动扩容:流量大的时候自动处理,不用手动调整

技术栈选择

经过一番调研,最终选择了这套组合:

  • Vercel:主要 API 服务,部署简单,国内访问速度还可以

  • Cloudflare Workers:定时任务,全球节点,稳定性不错

  • Supabase:PostgreSQL 数据库,有免费额度,功能够用

  • TypeScript:类型安全,开发体验比 JavaScript 好很多

系统架构设计

整个系统采用了分布式的设计思路,主要分为几个部分:


┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐

│   Vercel API    │    │ Cloudflare Cron │    │   Supabase DB   │

│   (主要服务)     │◄──►│   (定时调度)     │◄──►│   (数据存储)     │

└─────────────────┘    └─────────────────┘    └─────────────────┘

         │                       │                       │

         ▼                       ▼                       ▼

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐

│  图片代理服务    │    │   任务分发器     │    │   数据分析API   │

│ (免翻墙访问图片)   │    │  (适配多节点)      │    │  (统计查询)      │

└─────────────────┘    └─────────────────┘    └─────────────────┘

核心模块介绍

1. 主服务 (Vercel API)

这是整个系统的核心,提供了所有的 API 接口。主要功能包括:

  • 爬虫服务:负责实际的数据抓取工作

  • 图片代理:免翻墙访问 Pixiv 图片

  • 数据管理:提供 CRUD 操作和统计查询

  • Web 界面:一个简单的管理后台

2. 定时任务 (Cloudflare Cron Worker)

用来做任务调度,比如:

  • 定时抓取排行榜数据

  • 定期请求获取推荐图片

  • 分发任务给多个节点

这部分的设计比较简单,主要是读取数据库中的待处理任务,然后调用主服务的 API。

3. 数据存储 (Supabase)

选择 Supabase 主要是因为它提供了不错的免费额度。数据库设计也比较简单:

  • pic 表:存储作品信息

  • pic_task 表:任务队列管理

核心功能实现

1. 智能推荐算法

这个功能我花了不少时间思考。最初的想法很简单,就是根据一个作品 ID 去找相关的推荐内容。但实际实现时发现,单纯的推荐容易陷入局部最优,所以加了几个策略:

  • 多种推荐类型:支持按插画、作者、首页等不同类型的推荐

  • 热度过滤:设置一个热度阈值,过滤掉质量不高的内容

  • 自动去重:避免重复抓取相同内容

  • 动态调整:根据目标数量自动调整推荐深度

2. 热度计算

这个算法随便想的仅供参考,最终采用了这个公式:


热度 = (点赞数 × 0.55 + 收藏数 × 0.45) ÷ 浏览量

权重的选择主要考虑了:

  • 点赞比收藏更容易,所以权重稍低

  • 浏览量作为分母,避免新作品虚高

  • 整体范围在 0-1 之间,便于设置阈值

3. 防封机制

这部分比较重要,毕竟不想给目标网站造成太大压力:

  • 请求头轮换:每隔一段时间切换不同的浏览器标识

  • 随机延迟:每次请求之间加入随机等待时间

4. 图片代理服务

这个功能主要是为了解决前端访问图片的翻墙问题。实现思路比较直接:

  • 前端请求我们的代理接口

  • 后端用正确的 Referer 去请求原图

  • 将图片数据流直接返回给前端

  • 加上适当的缓存头,提升访问速度

部署和运维

部署流程

整个部署过程还是比较简单的:

  1. 配置环境变量:主要是数据库连接和 Pixiv Cookie

  2. 部署主服务:一条命令部署到 Vercel

  3. 部署定时任务:使用 Wrangler CLI 部署到 Cloudflare

  4. 初始化数据库:执行 SQL 脚本创建表结构

成本控制

这套方案的成本控制做得还不错:

| 服务 | 免费额度 | 实际使用 |

|------|----------|----------|

| Vercel | 100GB 带宽/月 | 通常用不到 10GB |

| Supabase | 500MB 数据库 | 存储几十万条记录没问题 |

| Cloudflare Workers | 10万请求/天 | 定时任务用量很少 |

基本上个人使用完全免费。

遇到的问题和解决方案

1. IP 封禁问题

最开始想直接在 Cloudflare Worker 里做爬虫,结果发现 CF 的 IP 已经被封了。后来改成了现在这种架构,定时任务只负责调度,实际爬取在 Vercel 上进行。

2. 图片质量低下问题

最开始的pic_task会无限递归爬取,导致图片质量低下无限扩散,现在采用爬取插画推荐和作者推荐前判断当前图片热度,热度高的图片才进行推荐爬取。

3.  serverless请求超时问题

最初是按照我之前的思路,在edge function中直接递归爬取指定数量图片,后来发现这种实现完全不稳定,爬了几张就停了。后面采用task表记录爬取情况,爬取推荐和爬取图片详细信息单独分配任务给节点去爬取,效率和稳定性都提高了。

功能特色

Web 管理界面

虽然我不是前端出身,但还是做了一个简单的管理界面:

  • 实时监控:显示系统状态和统计数据

  • 任务管理:可以手动启动最初版本的递归爬取任务

  • 日志查看:实时查看系统运行日志

界面比较简单,经典紫色心情的风格。

API 接口

提供了完整的 RESTful API:

GET 接口:

  • /api?action=status - 系统状态检查,返回服务运行状态和环境信息

  • /api?action=stats - 统计信息,返回图片总数、下载数量、平均热度等

  • /api?action=env-check - 环境变量检查,验证配置完整性

  • /api?action=logs&taskId=xxx&limit=100 - 获取日志,支持按任务ID过滤

  • /api?action=get-pic&pid=xxx - 获取指定PID的图片信息

  • /api?action=proxy-image&pid=xxx&size=xxx - 代理访问Pixiv图片,支持指定尺寸

  • /api?action=home - 获取首页推荐PID并入库

  • /api?action=random-pids&count=10 - 从数据库随机获取指定数量的PID

  • /api?action=illust-recommend-pids&pid=xxx&targetNum=30 - 获取插画推荐PID列表

  • /api?action=author-recommend-pids&pid=xxx&targetNum=30 - 获取作者推荐PID列表

  • /api?action=pid-detail-info&pid=xxx - 获取PID详细信息并入库

  • /api?action=daily - 触发日榜抓取任务

  • /api?action=weekly - 触发周榜抓取任务

  • /api?action=monthly - 触发月榜抓取任务

  • /api - 返回Web管理界面

POST 接口:

  • /api (爬虫任务) - 启动爬虫任务,支持单个PID或批量PID

  ```json

  {

    "pid": "123456",  // 单个PID

    "pids": ["123456", "789012"],  // 批量PID

    "targetNum": 1000,  // 目标数量

    "popularityThreshold": 0.22  // 热度阈值

  }

  ```

  • /api (下载任务) - 启动下载任务,需要R2配置

  ```json

  {

    "action": "download",

    "downloadPid": "123456",  // 单个下载

    "downloadPids": ["123456", "789012"]  // 批量下载

  }

  ```

接口设计比较简单,主要是为了方便调用。

多节点爬取

为了提高爬取效率,采用了多节点并行爬取的方式。每个节点负责一部分任务,任务分配采用定时分配策略,不同任务分配频率不一样。

总结

这个项目虽然功能比较简单又是AI实现的,但让我学到了很多东西:

  1. Serverless 架构:体验了无服务器开发的便利性,学习了运维部署方式

  2. 云服务集成:学会了如何组合使用不同的云服务

  3. 系统设计:在成本和功能之间找到平衡点

当然,项目还有很多不足的地方,比如错误处理还不够完善,监控系统也比较简陋。但作为一个学习项目,我觉得还是达到了预期目标。

如果你也对 Serverless 开发感兴趣,希望这个项目能给你一些参考。代码都在 GitHub 上,欢迎交流讨论。


最后再次提醒:这个项目仅供学习使用,请大家合理控制爬取频率,遵守相关网站的服务条款。技术无罪,但使用技术的方式很重要。

项目地址GitHub - serverless_pixiv_crawler

体验前端地址(只有递归爬取功能,大部分功能都在api接口中)pixiv.chaosyn.com

如果觉得有用的话,欢迎给个 Star ⭐

各位佬如果有啥建议和想法,欢迎在项目仓库提 issue 或者 PR,也可以直接在评论区下方交流~