Skip to content

A set of useful and scalable spiders to crawl data/videos from bilibili, xiaohongshu, etc.

Notifications You must be signed in to change notification settings

iiicebearrr/spiders-for-all

Repository files navigation

爬取、下载哔哩哔哩、小红书等网站数据、视频, 持续更新中...

Warning:

本项目仅供学习交流使用, 请勿用于商业及非法用途, 由此引起的一切后果与作者无关

spiders_for_all.demo.mov

Menu

Quick Preview

根据用户id爬取b站用户主页投稿视频

python -m spiders_for_all bilibili download-by-author -m 用户id -s 保存目录

根据note_id批量爬取小红书笔记内容

python -m spiders_for_all xhs download-by-id -i note_id1,note_id2,note_id3 -s 保存目录

更多用法见Documentation部份

Installation

pip install spiders-for-all # python 版本 >= 3.12

Documentation

点击进入对应平台的使用文档

Roadmap

  • bilibili
    • 综合热门、入站必刷等栏目爬虫
    • 根据bvid爬取/批量爬取视频
    • 根据用户id爬取用户主页投稿视频
    • 爬取用户动态
  • xhs
    • 根据note_id爬取/批量爬取笔记
    • 根据用户id爬取用户主页首页笔记
    • 爬取笔记评论
  • GUI

Customization

如果你想自定义爬虫, 可以参考以下指引

首先需要了解一下项目爬虫的基本结构, 参考下图:

spider_structure

  • spiders_for_all/spiders目录下存放各个平台的爬虫, 每个爬虫都是一个类, 继承自spiders_for_all.core.spider.BaseSpider类, 并实现BaseSpider类的get_items_from_response方法

  • 继承自BaseSpider的爬虫, 会按照以下流程爬取目标网站数据

    • self.__init__: 初始化爬虫
      • 初始化logger
      • 初始化数据库连接
      • 初始化数据库表, 这一步的行为取决于cls.db_action_on_init:
        • spiders_for_all.core.spider.DbActionOnInit.CREATE_IF_NOT_EXISTS: 如果表不存在则创建
        • spiders_for_all.core.spider.DbActionOnInit.DROP_AND_CREATE: 直接删除并创建表
      • 初始化client:
        • client是一个spiders_for_all.core.client.HttpClient对象, 封装了失败重试、日志、以及生成模拟请求头user-agent的功能
    • self.run: 运行爬虫
      • self.before: 运行爬虫前执行的代码, 默认会打印一条日志
      • self.get_items: 从目标网站获取数据
        • self.request_items: 向self.api发送请求, 获取返回。会调用self.get_request_args获取额外的请求参数比如params, data等等
        • self.validate_response: 验证返回体结构, 如果定义了self.response_model, 会调用self.response_model基于pydantic对返回体进行验证。注意这里的验证是业务验证, 不是HTTP状态的验证, self.client会自动验证HTTP状态。 如果没有定义self.response_model, 则不会进行验证,直接返回原始的requests.Response对象
        • self.get_items_from_response: 从验证成功的返回体中取出对应的items, 返回items的数据类型完全取决于cls.item_model, 具体可以参考几个爬虫的实现
        • 需要注意的是, self.request_items(), self.validate_response, self.get_items_from_response均被封装在一个retry的wrapper内,这也就意味着如果出现: HTTP状态码非200, 业务返回体异常, 比如哔哩哔哩的-352业务码, 获取items失败,比如网页没有返回正常的数据这些情况, 均会触发自动重试
      • self.save_items: 将爬取的数据保存到数据库
      • self.after: 运行爬虫后执行的代码, 默认会打印一条日志
  • 除此之外, 需要额外定义一些类属性, 示例如下

    import typing as t
    import logging
    import requests
    from sqlalchemy import orm
    from pydantic import BaseModel
    from spiders_for_all.core.response import Response
    from spiders_for_all.core.spider import BaseSpider, DbActionOnInit, DbActionOnSave
    from spiders_for_all.database.session import SessionManager
    from spiders_for_all.utils.logger import default_logger
    
    class MySpider(BaseSpider):
        api: str  # 目标API, 必须
        name: str # 爬虫名称, 必须
        alias: str # 爬虫别名, 必须
        platform: str # 爬虫所属平台, 必须
        description: str = "" # 爬虫描述, 可选
    
        database_model: t.Type[orm.DeclarativeBase] # 数据库表模型, 必须
        item_model: t.Type[BaseModel] # 爬取的数据模型, 必须
        response_model: t.Type[Response] | None = None # 返回体模型, 可选
    
        logger: logging.Logger = default_logger # 日志对象, 可选
        session_manager: SessionManager # 数据库连接管理器, 必须
    
        insert_batch_size: int = 100 # 批量插入数据库时的批量大小, 可选
    
        db_action_on_init: DbActionOnInit = DbActionOnInit.CREATE_IF_NOT_EXIST # 初始化数据库表时的行为, 可选
        db_action_on_save: DbActionOnSave = DbActionOnSave.DELETE_AND_CREATE # 保存数据时的行为, 可选
    
        def get_items_from_response(self, response: requests.Response | Response) -> t.Iterable[BaseModel]:
            # 从返回体中取出items, 必须
            pass

Find me

Known Issues

  • (已解决)小红书爬取用户投稿的笔记时, 由于小红书签名算法的问题尚未解决, 只能爬取用户投稿的首页数据, 需要下拉加载的数据暂时无法爬取(签名算法借鉴了Spider-XHS)
  • 低版本的sqlite可能不支持ON CONFLICT DO UPDATE语法, 如果遇到该问题请尝试升级sqlite版本
  • 大批量下载视频时可能偶现下载中断导致失败的情况, 这种情况请在所有任务下载完成后, 运行grep ERROR logs/bilibili.log可以查看有哪些视频下载失败, 然后收集bvid重新下载即可。未来会考虑处理这种情况
  • (已解决)bilibili近期(2024-01-20左右)更新了用户投稿接口的反爬策略, 新增了dm_img_inter参数, 目前作者还没有时间实现该参数的生成算法, 所以该接口暂时无法使用, 但是如果你实现了该参数的生成算法, 可以通过修改spiders_for_all.spiders.bilibili.AuthorSpider中的get_request_args方法来继续使用该接口