磁力搜索网站搭建

需求来源

爬虫

之前偶然间看见这篇文章(20230211现在已经访问不了了),就想着自己也整一个。

整一个

现有问题

现有的BT搜索网站存在关键词匹配问题,导致搜索结果与关键词关联度不高。

需求

为了搭建DHT爬虫、改进现有网站搜索准确率、测试MySQL数据库性能、测试网站并发量、对大量数据进行数据分析,需要搭建一个完整的磁力链接搜索引擎网站。

需求分析

搜集相关信息,分析现有的磁力链接搜索网站信息。对需求进行细化。

一个磁力链接网站应该包括:

  • 支持前端页面显示
    • 支持搜索引擎页面显示,类似于百度首页
    • 支持搜索引擎页面热词显示
    • 支持搜索结果整合显示
    • 支持显示某个磁力链接的详细信息
  • 支持搜索引擎功能
    • 支持获取搜索引擎页面输入的关键词
    • 支持关键词拆分
    • 支持通过关键词搜索数据库
    • 支持获取数据库数据
  • 支持数据库功能
    • 保存从DHT网络获取的数据
    • 支持对搜索引擎提供数据
  • 支持爬虫功能
    • 支持DHT原理获取磁力链接和磁力链接的详细信息
    • 支持将获取的数据保存到数据库

数据保存

数据怎么获取取决于数据怎么保存,以什么格式保存,所以先说保存。一旦数据开始获取想要修改就很麻烦了,所有要先规划好。

首先数据库分为两类(当然,肯定在在同一个数据库中保存)简要信息(显示在搜索结果中的信息)和详细信息(点击搜索结果中的某一个)。磁力链接本质上是十六进制字符串,每类表都有16个。热词表用于显示搜索关键词热度。

数据库相关

在通过搜索引擎进行搜索时,只需要显示磁力链接的部分信息就可以了。

和这个类似

brief

字段包括:文件名、热度、文件大小、创建时间、文件格式

而显示详细信息时

info

字段包括:文件名、热度、磁力链接、文件大小、创建时间、文件数量、文件列表

文件列表这个字段,它的数量未知。我的处理是独立一个表。

表创建:

  • 简要信息一个表,详细信息中保存除简要信息的字段
  • 还有一种方法是详细信息保存所有字段,简要信息从详细信息中提取此部分信息,不知道两者有何差别,待网站搭建完成后再测试。

现在网站属于测试阶段,所以就先只保存在详细信息中,然后以索引的方式生成简要信息。

简要信息表

此表用于储存种子对应的信息。

1
2
3
4
5
6
7
8
9
10
11
12
create table if not exists `index_a` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hash` varchar(40) NOT NULL,
`name` varchar(1000) NOT NULL,
`hot` int(12) NOT NULL,
`create_time` int(12) NOT NULL,
`file_size` bigint(50) NOT NULL,
`file_num` int(8) NOT NULL,
`file_type` varchar(10) NOT NULL,
`update_time` int(12) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

这样的表有16个。

详细信息表

此表储存种子所表示的所有文件

1
2
3
4
5
6
create table if not exists `list_0` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(1000) NOT NULL,
`file_size` bigint(50) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

此表同样有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]

运行程序

running

这样就会有源源不断的数据填充到数据库表里面,除了本系列之外,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条

state

state

state

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

穷的想叮当

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

熬夜

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

peer

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

announce

占比图为:

percent

那么我们进行下一步

Redis->MySQL

使用脚本将数据从Redis中提取并保存到MySQL中。

数据大约为505万条,单线程耗时12个小时。

导入了5050679条数据,其余524条数据因数据字符问题无法导入。

磁力文件

磁力链接总数太多,选取get_peers中b开头的磁力链接,只有50万条,这样爬取的种子不会太多。

但是找不到有效的BT种子仓库或者找的仓库无法直接获取,无法批量获取*.torrent文件,可能需要考虑从dht网络中直接获取种子文件。

待实现功能


磁力搜索网站搭建
https://blog.jackeylea.com/bt/introduction-of-torrent-webiste/
作者
JackeyLea
发布于
2020年12月3日
许可协议