你知道Python或Perl的任何易于使用,整洁的API与BitTorrent Trackers交互吗?例如,我获取一个torrent文件,枚举文件中的所有跟踪器,并向跟踪器询问与下载文件相关的对等体的统计信息?
BitTorrent Tracker规范并不太复杂,但我不想重新发明轮子:)
请注意,我不想下载数据,只是为了获取一些统计数据(Net :: BitTorrent远远超过我的需要)
答案 0 :(得分:3)
只是简单的命令行是不够的? :-)(Transmission)为您提供传输远程工具,该工具允许枚举跟踪器并使用一个命令获取对等统计信息。看看
-pi --peer-info
List the current torrent's connected peers. In the `status' section of the list, the following shorthand is used:
D: Downloading from this peer
d: We would download from this peer if they would let us
E: Encrypted connection
I: Peer is an incoming connection
K: Peer has unchoked us, but we're not interested
O: Optimistic unchoked
U: Uploading to peer
u: We would upload to this peer if they asked
X: Peer was discovered through Peer Exchange (PEX)
?: We unchoked this peer, but they're not interested
...
-si --session-info
List session information from the server
好吧,要使用它,你必须使用传输作为你的torrent客户端,但如果你这样做,你可以用grep来做,这取决于你真正想要实现的目标。
答案 1 :(得分:2)
编辑:自从我写这篇文章以来,我发现如果您花时间学习基础知识,那么transmissionbt's RPC interface就会有很好的文档记录和用户友好性。
答案 2 :(得分:0)
我制作了Perl脚本以从.torrent文件中获取数据,汇集跟踪器并获取一些统计信息(文件哈希,连接到跟踪器的IP,文件大小等)。没有大科学,只有一些Perl-fu。要运行它,您需要:安装Perl模块 Bencode , curl 和传输 - 显示。调试垃圾被发送到 stderr 并正确输出到 stdout 。
#!/usr/bin/perl
use Bencode qw( bencode bdecode );
use Data::Dumper;
use warnings;
use strict;
my $G_PEER_ID = "hfgdbvnchdgfhvnfbghf";
my $G_MAX_TIME = 20;
sub peer_decode
{
my $d = shift;
my @a = split '', $d;
# printf ">>%d %d<<\n", length($d), scalar(@a);
my @ret;
while(@a) {
my $ip = sprintf "%d.%d.%d.%d" ,
unpack('C',shift(@a)),
unpack('C',shift(@a)),
unpack('C',shift(@a)),
unpack('C',shift(@a));
my $port = sprintf "%d", 256 * unpack('C',shift(@a))
+ unpack('C',shift(@a));
# printf "%d $ip $port\n",scalar(@a);
push @ret, $ip;
}
return \@ret;
}
sub get_tracker_data_from_file
{
my $fname = shift;
my $ret = {};
my $c = `transmission-show $fname`;
print STDERR "$c\n";
if ( $c =~ /^\s+Hash:\s*(\S+)/mg ) {
$ret->{'hash'} = $1;
}
if ( $c =~ /^\s+Total Size:\s*(.+)$/mg ) {
$ret->{'size'} = $1;
}
my @g;
@g = ($c =~ /Tier \#\d+[\n\r\s]+(\S+)/gm);
if ( @g ) {
$ret->{'tiers'} = \@g;
}
return $ret;
}
sub get_peer_ips
{
my $hash = shift;
my $tracker = shift;
my $ret = undef;
$hash =~ s/(..)/\%$1/g;
$tracker =~ s/\/$//;
my $c = "curl -m $G_MAX_TIME -s '$tracker?info_hash=$hash&peer_id=$G_PEER_ID&uploaded=0&downloaded=0&left=1'";
print STDERR "$c\n";
my $w = `$c`;
return undef if not $w;
printf STDERR "%s\n" , Dumper($w);
return undef if $w =~ /<\s*html\s*>/gi;
$w = bdecode($w, 1);
if ( defined $w->{'peers'} ) {
$ret = peer_decode($w->{'peers'});
}
return $ret;
}
# -- main
my @files = @ARGV;
if ( not @files ) {
print <<END
usage: $0 <file1.torrent> <file2.torrent> ...
(c) http://stackoverflow.com/users/497208
END
}
for my $fname ( @files ) {
printf STDERR "File: %s\n", $fname;
my $tr = get_tracker_data_from_file($fname);
printf STDERR "%s\n", Dumper $tr;
my $hash = undef;
$hash = $tr->{'hash'} if defined $tr->{'hash'};
exit if not defined $hash;
my $size = undef;
if ( defined $tr->{'size'} ) {
$size = $tr->{'size'};
}
else {
$size = "?";
}
if ( defined $tr->{'tiers'} ) {
# shift @{$tr->{'tiers'}} for (1..5);
for my $tracker ( @{$tr->{'tiers'}} ) {
my $ips = get_peer_ips( $hash, $tracker);
printf STDERR "%s\n", Dumper $ips;
if ( defined $ips ) {
for my $ip ( @$ips ) {
my $c = sprintf "%s; %16s; %s; %s", $hash, $ip, $size, $tracker;
printf STDERR "$c\n";
printf "$c\n";
}
}
}
}
}