磁力搜索网站搭建
需求来源
爬虫
之前偶然间看见这篇文章(20230211现在已经访问不了了),就想着自己也整一个。

现有问题
现有的BT搜索网站存在关键词匹配问题,导致搜索结果与关键词关联度不高。
需求
为了搭建DHT爬虫、改进现有网站搜索准确率、测试MySQL数据库性能、测试网站并发量、对大量数据进行数据分析,需要搭建一个完整的磁力链接搜索引擎网站。
需求分析
搜集相关信息,分析现有的磁力链接搜索网站信息。对需求进行细化。
一个磁力链接网站应该包括:
- 支持前端页面显示
- 支持搜索引擎页面显示,类似于百度首页
- 支持搜索引擎页面热词显示
- 支持搜索结果整合显示
- 支持显示某个磁力链接的详细信息
- 支持搜索引擎功能
- 支持获取搜索引擎页面输入的关键词
- 支持关键词拆分
- 支持通过关键词搜索数据库
- 支持获取数据库数据
- 支持数据库功能
- 保存从DHT网络获取的数据
- 支持对搜索引擎提供数据
- 支持爬虫功能
- 支持DHT原理获取磁力链接和磁力链接的详细信息
- 支持将获取的数据保存到数据库
数据保存
数据怎么获取取决于数据怎么保存,以什么格式保存,所以先说保存。一旦数据开始获取想要修改就很麻烦了,所有要先规划好。
首先数据库分为两类(当然,肯定在在同一个数据库中保存)简要信息(显示在搜索结果中的信息)和详细信息(点击搜索结果中的某一个)。磁力链接本质上是十六进制字符串,每类表都有16个。热词表用于显示搜索关键词热度。
数据库相关
在通过搜索引擎进行搜索时,只需要显示磁力链接的部分信息就可以了。
和这个类似

字段包括:文件名、热度、文件大小、创建时间、文件格式
而显示详细信息时

字段包括:文件名、热度、磁力链接、文件大小、创建时间、文件数量、文件列表
文件列表这个字段,它的数量未知。我的处理是独立一个表。
表创建:
- 简要信息一个表,详细信息中保存除简要信息的字段
- 还有一种方法是详细信息保存所有字段,简要信息从详细信息中提取此部分信息,不知道两者有何差别,待网站搭建完成后再测试。
现在网站属于测试阶段,所以就先只保存在详细信息中,然后以索引的方式生成简要信息。
简要信息表
此表用于储存种子对应的信息。
1 | |
这样的表有16个。
详细信息表
此表储存种子所表示的所有文件
1 | |
此表同样有16个
至此数据保存的格式确定了,下一步是获取数据并保存到数据库中
数据获取
磁力链接是获取不完的
我做不到从0开始,只能从之前的代码修改,之前的两个项目都是用Python,那就一条路走到黑。
原计划是打算基于别人的代码修改,经过测试,别人的代码无法实现获取数据和保存到数据库。数据库部分的代码与DHT部分代码有冲突,两者一起导致程序无法运行。
所以本系列采用的方式是别人的Python代码(就是保存到Redis的方式,毕竟已经用它获取了170万条数据了),然后用Python脚本将其解析保存到MySQL数据库中。
下面简单介绍一下Python版的原理和流程,后期会用C++写一个直接获取保存到MySQL的版本。
从GitHub上面找了现成的:
asyncDHT使用MySQL数据库存储数据,但是我在Ubuntu20.04+MySQL+Python3.8.5上面没有没有成功运行。magnet-dht可以使用,并且跑满带宽,但是使用Redis存储数据,而我不会使用Redis。

asyncDHT作者在阿里云ECS(1核、1G、100M/s)上跑了66小时。获取get_peers请求的info_hash 21,313,390条记录(不重复),announce_peer请求的info_hash 849,355条记录(不重复),get_peers和announce_peer请求的info_hash 76,411,582条记录(含重复)。
模块流程图为
flowchart LR
A[utils] --> B[crawler]
A[utils] --> C[metadata]
C[metadata] --> D[crawler]
E[bencode] --> C[metadata]
F[mysqlpool] --> C[metadata]
F[mysqlpool] --> B[crawler]
数据流为
flowchart TD
A(开始) --> B[receive_response_forever]
B[receive_response_forever] --> C[bootstrap]
C[bootstrap] --> D[send_find_node]
C[bootstrap] --> E[on_message]
E[on_message] --> F[on_find_node_response]
E[on_message] --> G[on_get_peers_request]
E[on_message] --> H[on_announce_peer_request]
G[on_get_peers_request] --> I[save_magnet]
H[on_announce_peer_request] --> I[save_magnet]
运行程序

这样就会有源源不断的数据填充到数据库表里面,除了本系列之外,MySQL入门、测试也会用到这些表、数据。
数据爬取
爬虫环境为:2xCPU + 8G RAM + 80G HD + Ubuntu LTS 20.04 + Apache2 2.4.41 + PHP 7.4.3 + MySQL 8.0.26 + Python3 3.8.10
经过接近两个月的爬取。获取到了大约3GB的数据,共计5051203条



我在腾讯云ECS(2核,4G,5M/s)上运行接近两周(运行时间太长我忘了具体时间),获取记录get_peers类型info_hash为8488890条,announce_peer类型info_hash为129条。

爬了那么长时间我才意识到链接是永远爬不完的。

get_peers中0-f开头的数量为:

get_announce中0-f开头的数量为:

占比图为:

那么我们进行下一步
Redis->MySQL
使用脚本将数据从Redis中提取并保存到MySQL中。
数据大约为505万条,单线程耗时12个小时。
导入了5050679条数据,其余524条数据因数据字符问题无法导入。
磁力文件
磁力链接总数太多,选取get_peers中b开头的磁力链接,只有50万条,这样爬取的种子不会太多。
但是找不到有效的BT种子仓库或者找的仓库无法直接获取,无法批量获取*.torrent文件,可能需要考虑从dht网络中直接获取种子文件。
待实现功能
- 3系统实现
- 3.3前端 搜索引擎界面 搜索结果 详细信息
- 3.4后端 搜索引擎 关键词 分词 匹配 结果
- 3.5数据库
- 4系统优化
- 缓存
- ID优化
- 搜索优化
- 智能推荐
- 其他

