组保留的标签 余下为需要删除的标签
unset($oldtag[$key]);
}
}
}
if (!empty($oldtag)) {
$tagids = array();
foreach ($oldtag as $tagid => $tagname) {
$tagids[] = $tagid;
}
well_oldtag_delete($tagids, $tid);
}
$r = well_tag_process($tid, $fid, $create_tag, $tagarr);
return $r;
}
// 删除标签和绑定的主题
function well_oldtag_delete($tagids, $tid)
{
$pagesize = count($tagids);
$arrlist = well_tag_find_by_tagids($tagids, 1, $pagesize);
$delete_tagids = array(); // 删除
$tagids = array();
$n = 0;
foreach ($arrlist as $val) {
++$n;
if (1 == $val['count']) {
// 只有一个主题
$delete_tagids[] = $val['tagid'];
} else {
$tagids[] = $val['tagid'];
}
}
!empty($delete_tagids) and well_tag_delete($delete_tagids);
$arlist = well_tag_thread_find_by_tid($tid, 1, $n);
if ($arlist) {
$ids = array();
foreach ($arlist as $val) $ids[] = $val['id'];
well_tag_thread_delete($ids);
}
!empty($tagids) and well_tag_update($tagids, array('count-' => 1));
}
// 标签数据处理 $arr=新提交的数组 $tagarr=保留的旧标签
function well_tag_process($tid, $fid, $new_tags = array(), $tagarr = array())
{
if (empty($tid)) return '';
// 新标签处理入库
if ($new_tags) {
$threadarr = array();
$tagids = array();
$i = 0;
$size = 5;
$n = count($tagarr);
$n = $n > $size ? $size : $size - $n;
foreach ($new_tags as $name) {
++$i;
$name = trim($name);
$name = stripslashes($name);
$name = strip_tags($name);
$name = str_replace(array(' ', '#', "@", "$", "%", "^", '&', '·', '<', '>', ';', '`', '~', '!', '¥', '……', ';', '?', '?', '-', '—', '_', '=', '+', '.', '{', '}', '|', ':', ':', '、', '/', '。', '[', ']', '【', '】', '‘', ' ', ' ', ' ', ' ', ' '), '', $name);
$name = htmlspecialchars($name, ENT_QUOTES);
if ($name && $i <= $n) {
// 查询标签
$read = well_tag_read_name($name);
if ($read) {
// 存在 count+1
$tagids[] = $read['tagid'];
} else {
// 入库
$arr = array('name' => $name, 'count' => 1);
$tagid = well_tag_create($arr);
FALSE === $tagid and message(-1, lang('create_failed'));
$read = array('tagid' => $tagid, 'name' => $name);
}
$tag_thread = array('tagid' => $read['tagid'], 'tid' => $tid);
$threadarr[] = $tag_thread;
$tagarr[$read['tagid']] = $read['name'];
}
}
!empty($threadarr) and tag_thread_big_insert($threadarr);
!empty($tagids) and well_tag_update($tagids, array('count+' => 1));
}
$json = empty($tagarr) ? '' : xn_json_encode($tagarr);
return $json;
}
?> $v = implode(",", $v);
$temp[] = $v;
}
// 去掉重复的字符串,也就是重复的一维数组
$temp = array_unique($temp);
// 再将拆开的数组重新组装
$output = array();
foreach ($temp as $k => $v) {
if ($stkeep) $k = $starr[$k];
if ($ndformat) {
$temparr = explode(",", $v);
foreach ($temparr as $ndkey => $ndval) $output[$k][$ndarr[$ndkey]] = $ndval;
} else $output[$k] = explode(",", $v);
}
return $output;
}
// 合并二维数组 如重复 值以第一个数组值为准
function array2_merge($array1, $array2, $key = '')
{
if (empty($array1) || empty($array2)) return NULL;
$arr = array();
foreach ($array1 as $k => $v) {
isset($v[$key]) ? $arr[$v[$key]] = array_merge($v, $array2[$k]) : $arr[] = array_merge($v, $array2[$k]);
}
return $arr;
}
/*
* 对二维数组排序 两个数组必须有一个相同的键值
* $array1 需要排序数组
* $array2 按照该数组key排序
* */
function array2_sort_key($array1, $array2, $key = '')
{
if (empty($array1) || empty($array2)) return NULL;
$arr = array();
foreach ($array2 as $k => $v) {
if (isset($v[$key]) && $v[$key] == $array1[$v[$key]][$key]) {
$arr[$v[$key]] = $array1[$v[$key]];
} else {
$arr[] = $v;
}
}
return $arr;
}
?>
DHT爬虫和使用BEP协议完成metadata的下载(BT下载)编程频道|福州电脑网
DHT爬虫和使用BEP协议完成metadata的下载(BT下载)
编程之家460
更新时间:2026-04-03 20:28:09 在BitTorrent技术出世以来,很多网络资源被制作成种子进行传播,随后磁力链接加速了资源的传播。然后非常好奇,如今世界人民对什么资源需求大呢,所以在网上查询了许多资料和源代码,完成了这个爬虫。源代码在Github:https://github/1205628673/BT-Spider
首先我们先知道什么是" DHT网络"
如上图所示,每个人的机器都是一个"Peer",即对端...,而中间的那个服务器,就是中心叫做Tracker服务器,一些迅雷之流就是这种存在
既然是p2p,那么肯定也能去中心化,即上图去掉Tracker服务器。这样一来,每个使用BT下载软件的人,就遵循规则自动做种,那么在网络的其他端就能通过BEP协议下载到这个种子
什么是BEP协议,这里不多赘述,几个链接大家去阅读:
http://www.bittorrent/beps/bep_0005.html
大致意思就是在这个DHT网络中,只有遵循B编码发送标准消息才能得到答复,而消息主要分为几种:
ping
最基本的查询是ping。”q“=”ping”ping查询只有一个参数,“id”值是一个20字节的字符串,按网络字节顺序包含发送者节点id。对ping的适当响应只有一个键“id”,其中包含响应节点的节点id。
格式:
ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}
bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe
Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re
find_node
Find node用于查找给定ID的节点的联系信息。“q”=“Find_node”Find_node查询有两个参数,“ID”包含查询节点的节点ID,而“target”包含查询者所查找的节点的ID。当一个节点接收到一个find_node查询时,它应该用一个键“nodes”和一个字符串的值来响应,该字符串包含目标节点或其自身路由表中K(8)个最近的好节点的压缩节点信息。
格式:
find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}}
bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe
Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}}
bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re
由于我们这是DHT爬虫,所以就不实现Routetable了,只需要将自身id和对端id简单拼一下就行
get_peer
获取与torrent infohash关联的对等方。”q“=”get_peers“get_peers查询有两个参数,“id”包含查询节点的节点id,“info_hash”包含torrent的infohash。如果查询的节点有infohash的对等节点,则它们将作为字符串列表以键“value”的形式返回。每个字符串包含单个对等点的“压缩”格式对等信息。如果查询的节点没有infohash的对等节点,则返回一个键“nodes”,其中包含查询节点路由表中最接近查询中提供的infohash的K个节点。在这两种情况下,“token”密钥也包含在返回值中。to
本文发布于:2025-08-07,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:爬虫协议DHTBEPBT
发布评论