当前位置: 首页 > java >正文

[p2p-Magnet] 数据模型(GORM) | DHT爬虫 | 分类器

在这里插入图片描述

第3章:数据模型(GORM)

在第2章:搜索查询引擎中,我们探索了系统如何通过高级数据库功能处理搜索请求。现在让我们深入了解这些"书籍"(种子资源)在系统"图书馆"中是如何组织和存储的。

数据模型与GORM解析

数据模型:信息蓝图

如同建筑需要设计图纸,数据模型定义了:

  • 存储内容:种子哈希值、名称、大小等核心字段
  • 结构关系:种子与文件的一对多关系
  • 外部关联:种子与影视元数据的映射关系

GORM:数据库管家

作为Go语言的ORM框架,GORM实现:

  • 对象映射:将Go结构体与数据库表自动关联
  • 关系管理:处理一对多/多对多等复杂关系
  • 语法简化:用db.First()替代复杂SQL语句

核心数据模型

系统主要包含五类核心模型:

  1. 种子模型(Torrent)
type Torrent struct {InfoHash  protocol.ID // 唯一标识Name      string      // 原始名称Size      uint        // 字节大小Files     []TorrentFile // 关联文件
}
  1. 文件模型(TorrentFile)
type TorrentFile {InfoHash protocol.ID // 所属种子Path     string      // 文件路径Size     uint        // 文件大小
}
  1. 标签模型(TorrentTag)
type TorrentTag {InfoHash protocol.ID // 所属种子Name     string      // 标签名称(如"4K")
}
  1. 内容分类模型(TorrentContent)
type TorrentContent {InfoHash    protocol.ID // 所属种子ContentType string      // 内容类型(movie/tv)ContentID   string      // 外部ID(如TMDB ID)
}
  1. 元数据模型(Content)
type Content {ID          string // 外部IDTitle       string // 标准名称ReleaseYear int    // 发布年份
}

数据关联示意图

Torrent
TorrentFile
TorrentTag
TorrentContent
Content

实战示例:存储新种子

当系统发现《黑客帝国》种子时:

  1. 创建种子记录
newTorrent := model.Torrent{InfoHash: "a1b2c3...", Name: "The.Matrix.1999.1080p",Size: 10_000_000_000
}
  1. 添加文件记录
files := []model.TorrentFile{{Path: "The.Matrix.mkv", Size: 9_800_000_000},{Path: "sample.mp4", Size: 200_000_000}
}
  1. 关联元数据
content := model.TorrentContent{ContentType: "movie",ContentID:   "tmdb_603" // TMDB ID
}
  1. 自动生成SQL
/* GORM自动生成 */
INSERT INTO torrents VALUES ('a1b2c3...', 'The.Matrix...', 10000000000);
INSERT INTO torrent_files VALUES ('a1b2c3...', 0, 'The.Matrix.mkv', 9800000000),('a1b2c3...', 1, 'sample.mp4', 200000000);

技术实现细节

模型自动生成

通过gorm.io/gen工具自动创建:

// internal/database/gen/gen.go
g.GenerateModel("torrents",gen.FieldRelate(field.HasMany, "Files", g.GenerateModel("torrent_files"),&field.RelateConfig{GORMTag: field.GormTag{"foreignKey":"InfoHash"}})
)

数据库连接

PostgreSQL连接配置:

// internal/database/gorm.go
gorm.Open(postgres.New(postgres.Config{Conn: sqlDB, // 连接池
}))

总结

数据模型与GORM共同构建了系统的存储架构:

  1. 结构化存储:明确定义各类数据字段
  2. 高效关联:智能管理复杂数据关系
  3. 开发提效:简化数据库操作复杂度

下一章将揭示系统如何发现种子资源:DHT爬虫


第4章:DHT爬虫

在第3章:数据模型(GORM)中,我们了解了系统如何通过"设计蓝图"和"施工队长"来组织存储种子信息。但这些种子最初是如何被发现的?系统如何不依赖传统网站或追踪器就能获取它们?

这就是DHT爬虫的职责所在!它如同系统的探险家,持续在去中心化的BitTorrent网络中搜寻新种子,构建独立的种子索引库。

DHT爬虫解析

工作原理

想象互联网是藏满宝藏的岛屿,传统方式依赖可能过时的"藏宝图"(中心化追踪器)。DHT爬虫则像装备声纳的探险船,直接探索**分布式哈希表(DHT)**网络——这个由全体BitTorrent客户端共同维护的"电话簿"。

核心功能:

  • 发现哈希值:通过询问其他客户端"你知道哪些种子?"获取信息哈希(种子的唯一指纹)
  • 获取元数据:请求种子的"配方卡"(包含名称、文件列表等)
  • 处理存储:将元数据传递给分类系统并存入数据库

操作方式

用户主要通过以下方式交互:

  1. 配置调整:可设置爬取强度(scaling_factor)或初始连接节点
  2. 状态监控:通过WebUI仪表盘查看实时指标,如bitmagnet_dht_crawler_persisted_total

技术实现细节

核心处理流程

爬虫DHT网络客户端元处理器数据库请求已知信息哈希返回节点列表和哈希值过滤重复哈希请求指定哈希的元数据返回元数据(名称/文件列表等)处理原始数据结构化数据存储新种子确认存储爬虫DHT网络客户端元处理器数据库

关键代码模块

  1. 控制中心(crawler.go)
type crawler struct {kTable       ktable.Table       // DHT网络节点表client       client.Client      // DHT通信客户端metainfoRequester metainforequester.Requester // 元数据请求器nodesForSampleInfoHashes chan ktable.Node     // 采样节点通道
}func (c *crawler) start() {go c.runSampleInfoHashes() // 启动哈希采样协程go c.runPersistTorrents()  // 启动存储协程// ...其他工作协程...
}
  1. 哈希采样(sample_infohashes.go)
func (c *crawler) runSampleInfoHashes() {for node := range c.nodesForSampleInfoHashes {res := c.client.SampleInfoHashes(node) // 请求节点采样for _, hash := range res.Samples {if !c.ignoreHashes.testAndAdd(hash) { // 布隆过滤器去重c.infoHashTriage <- hash // 传递新哈希}}}
}
  1. 数据存储(persist.go)
func (c *crawler) runPersistTorrents() {for batch := range c.persistTorrents {c.dao.Transaction(func(tx *dao.Query) error {tx.Torrent.CreateInBatches(batch.torrents, 100) // 批量存储种子tx.TorrentFile.CreateInBatches(batch.files, 100) // 批量存储文件return nil})}
}

总结

DHT爬虫通过:

  1. 主动探索DHT网络
  2. 智能过滤重复项
  3. 高效批量存储
    实现系统的自给自足式种子发现。下一章将揭示如何解析种子内容:分类器

第5章:分类器

在第4章:DHT爬虫中,我们看到系统如何持续探索BitTorrent网络并获取种子基础信息。但面对如"The.Matrix.1999.1080p.x264.DTS-HD.MA.5.1-GROUP"这样的原始数据,系统需要理解其实际含义——这就是分类器的使命。

分类器解析

核心功能

分类器如同智能图书管理员,能够:

  • 内容归类:识别电影/电视剧/音乐等类型
  • 特征提取:解析分辨率/音频编码等信息
  • 元数据增强:通过TMDB等API获取官方信息
  • 自定义标记:添加用户定义标签
  • 内容过滤:自动屏蔽违规资源

规则配置

通过YAML文件定义分类规则,支持:

  1. 工作流(Workflow)
workflows:default:- if_else:condition: "torrent.baseName.matches(keywords.banned)"if_action: delete- if_else:condition: "result.contentType == contentType.unknown"if_action: find_match
  1. 执行动作(Action)
    包含set_content_type/add_tag/delete等操作指令

  2. 条件判断(Condition)
    采用CEL表达式语言,可调用:

  • torrent对象:种子基础信息
  • result对象:当前分类结果
  • 预定义关键词列表
  1. 关键词列表(Keywords)
keywords:music: [music, album]banned: [违禁词1, 违禁词2]

实战案例

案例1:自动过滤内容

# config.yml
classifier:flags:delete_xxx: truekeywords:banned: [暴力内容, 政治敏感]

案例2:自定义标签

# classifier.yml
workflows:my_workflow:- run_workflow: default- if_else:condition: "torrent.baseName.matches(keywords.classic)"if_action: add_tag: 经典老片

技术实现

核心处理流程

处理器分类器规则引擎CEL引擎数据库TMDB请求分类(种子数据)加载YAML规则执行条件判断返回布尔结果查询关联内容返回查询结果请求增强元数据返回影视详情返回分类结果存储最终分类处理器分类器规则引擎CEL引擎数据库TMDB

关键代码

  1. 处理器入口(processor.go)
func (p processor) Process(ctx context.Context, torrent model.Torrent) error {result, err := p.classifier.Run(ctx, torrent) // 调用分类器if err != nil {return err}return p.dao.TorrentContent.Clauses(clause.OnConflict{UpdateAll: true,}).Create(&model.TorrentContent{InfoHash:    torrent.InfoHash,ContentType: result.ContentType,// ...其他字段...})
}
  1. 规则编译(compiler.go)
func (c compiler) Compile(source Source) (Runner, error) {workflows := make(map[string][]Action)for name, workflow := range source.Workflows {for _, action := range workflow.Actions {compiledAction, err := c.compileAction(action)workflows[name] = append(workflows[name], compiledAction)}}return runner{workflows: workflows}, nil
}

总结

分类器通过:

  1. 可定制规则引擎
  2. 多数据源关联
  3. 智能条件判断
    实现种子内容的深度解析。下一章将揭示任务调度机制:队列与处理器
http://www.xdnf.cn/news/19008.html

相关文章:

  • React Hook+Ts+Antd+SpringBoot实现分片上传(前端)
  • 数据湖与数据仓库
  • Qt 中日志级别
  • ArcGIS+Fragstats:土地利用统计分析、景观格局指数计算与地图制图
  • Android Keystore签名文件详解与安全防护
  • AI视频生成工具全景对比:元宝AI、即梦AI、清影AI和Vidu AI
  • 【贪心 单调栈】P10334 [UESTCPC 2024] 饮料|普及+
  • 工业 5G + AI:智能制造的未来引擎
  • Day16_【机器学习建模流程】
  • 【Rust】 3. 语句与表达式笔记
  • Java HTTP 请求:Unirest 使用指南及与 HttpClient 对比
  • .Net Core Web 架构(Request Pipeline)的底层实现
  • 自己定义的模型如何用hf的from_pretrained
  • Linux(一) | 初识Linux与目录管理基础命令掌握
  • 测试题ansible临时命令模块
  • CuTe C++ 简介01,从示例开始
  • imx6ull-驱动开发篇47——Linux SPI 驱动实验
  • Electron解压缩文件
  • hive on tez为什么写表时,要写临时文件到hdfs目录
  • docker 1分钟 快速搭建 redis 哨兵集群
  • 配置nginx.conf (增加21001端口实例操作)
  • 医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(三)
  • [灵动微电子 MM32BIN560CN MM32SPIN0280]读懂电机MCU之比较器
  • jQuery 从入门到实践:基础语法、事件与元素操作全解析
  • mac电脑双屏显示时程序坞跑到副屏的解决方法
  • 机器视觉学习-day10-图像添加水印
  • Mybatis 与 Springboot 集成过程详解
  • Kubernetes一EFK日志架构
  • Ovis2.5技术解密:原生分辨率与“反思模式”如何铸就新一代MLLM王者
  • 嵌入式学习日志————实验:串口发送串口发送+接收